+ * 三种http框架的response代理类,方便提取公共方法 + * Created by Binary Wang on 2017-8-3. + *+ * + * @author Binary Wang + */ +public class HttpResponseProxy { + private CloseableHttpResponse apacheHttpResponse; + private HttpResponse joddHttpResponse; + private Response okHttpResponse; + + public HttpResponseProxy(CloseableHttpResponse apacheHttpResponse) { + this.apacheHttpResponse = apacheHttpResponse; + } + + public HttpResponseProxy(HttpResponse joddHttpResponse) { + this.joddHttpResponse = joddHttpResponse; + } + + public HttpResponseProxy(Response okHttpResponse) { + this.okHttpResponse = okHttpResponse; + } + + public String getFileName() throws WxErrorException { + //由于对象只能由一个构造方法实现,因此三个response对象必定且只有一个不为空 + if (this.apacheHttpResponse != null) { + return this.getFileName(this.apacheHttpResponse); + } + + if (this.joddHttpResponse != null) { + return this.getFileName(this.joddHttpResponse); + } + + if (this.okHttpResponse != null) { + return this.getFileName(this.okHttpResponse); + } + + //cannot happen + return null; + } + + private String getFileName(CloseableHttpResponse response) throws WxErrorException { + Header[] contentDispositionHeader = response.getHeaders("Content-disposition"); + if (contentDispositionHeader == null || contentDispositionHeader.length == 0) { + throw new WxErrorException(WxError.newBuilder().setErrorMsg("无法获取到文件名").build()); + } + + return this.extractFileNameFromContentString(contentDispositionHeader[0].getValue()); + } + + private String getFileName(HttpResponse response) throws WxErrorException { + String content = response.header("Content-disposition"); + return this.extractFileNameFromContentString(content); + } + + private String getFileName(Response response) throws WxErrorException { + String content = response.header("Content-disposition"); + return this.extractFileNameFromContentString(content); + } + + private String extractFileNameFromContentString(String content) throws WxErrorException { + if (content == null || content.length() == 0) { + throw new WxErrorException(WxError.newBuilder().setErrorMsg("无法获取到文件名").build()); + } + + Pattern p = Pattern.compile(".*filename=\"(.*)\""); + Matcher m = p.matcher(content); + if (m.matches()) { + return m.group(1); + } + throw new WxErrorException(WxError.newBuilder().setErrorMsg("无法获取到文件名").build()); + } + +} diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheMediaDownloadRequestExecutor.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheMediaDownloadRequestExecutor.java index 6a928648e5..0a5a504873 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheMediaDownloadRequestExecutor.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/ApacheMediaDownloadRequestExecutor.java @@ -3,8 +3,10 @@ import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.fs.FileUtils; +import me.chanjar.weixin.common.util.http.HttpResponseProxy; import me.chanjar.weixin.common.util.http.MediaDownloadRequestExecutor; import me.chanjar.weixin.common.util.http.RequestHttp; +import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.StringUtils; import org.apache.http.Header; import org.apache.http.HttpHost; @@ -17,15 +19,12 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.util.regex.Matcher; -import java.util.regex.Pattern; /** * Created by ecoolper on 2017/5/5. */ public class ApacheMediaDownloadRequestExecutor extends MediaDownloadRequestExecutor
* 二维码相关操作接口 + * + * 接口A(createWxCode)加上接口C(createQrcode),总共生成的码数量限制为100,000,请谨慎调用。 + * * 文档地址:https://mp.weixin.qq.com/debug/wxadoc/dev/api/qrcode.html ** @@ -15,6 +18,7 @@ public interface WxMaQrcodeService { /** + * 接口C *
* 获取小程序页面二维码 * 适用于需要的码数量较少的业务场景 @@ -27,4 +31,83 @@ public interface WxMaQrcodeService { * @param width 默认430 二维码的宽度 */ File createQrcode(String path, int width) throws WxErrorException; + + File createQrcode(String path) throws WxErrorException; + + /** + * 接口A + * 获取小程序码 + * + * @param path 不能为空,最大长度 128 字节 + * @param width 默认430 二维码的宽度 + * @param autoColor 默认true 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 + * @param lineColor auth_color 为 false 时生效,使用 rgb 设置颜色 例如 {"r":"xxx","g":"xxx","b":"xxx"} + * @return + * @throws WxErrorException + */ + File createWxCode(String path, int width, boolean autoColor, LineColor lineColor) throws WxErrorException; + + File createWxCode(String path, int width) throws WxErrorException; + + File createWxCode(String path) throws WxErrorException; + + /** + * 接口B + * 获取小程序码(永久有效、数量暂无限制) + **/ -public class WxMpMenu { +public class WxMpMenu implements Serializable { + private static final long serialVersionUID = -5794350513426702252L; + @SerializedName("menu") private WxMpConditionalMenu menu; @@ -51,7 +54,9 @@ public String toJson() { return WxGsonBuilder.create().toJson(this); } - public static class WxMpConditionalMenu { + public static class WxMpConditionalMenu implements Serializable { + private static final long serialVersionUID = -2279946921755382289L; + @SerializedName("button") private List+ * 通过该接口生成的小程序码,永久有效,数量暂无限制。 + * 用户扫描该码进入小程序后,将统一打开首页,开发者需在对应页面根据获取的码中 scene 字段的值,再做处理逻辑。 + * 使用如下代码可以获取到二维码中的 scene 字段的值。 + * 调试阶段可以使用开发工具的条件编译自定义参数 scene=xxxx 进行模拟,开发工具模拟时的 scene 的参数值需要进行 urlencode + * + * @param scene 最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~,其它字符请自行编码为合法字符(因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式) + * @param page 必须是已经发布的小程序页面,例如 "pages/index/index" ,如果不填写这个字段,默认跳主页面 + * @param width 默认false 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 + * @param autoColor 默认true 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 + * @param lineColor auth_color 为 false 时生效,使用 rgb 设置颜色 例如 {"r":"xxx","g":"xxx","b":"xxx"} + * @return + * @throws WxErrorException + */ + File createWxCodeLimit(String scene, String page, int width, boolean autoColor, LineColor lineColor) throws WxErrorException; + + File createWxCodeLimit(String scene, String page) throws WxErrorException; + + /** + * lineColor 包装类 + * 用于描述二维码(小程序码)颜色(RGB参数值),详情请查看文档 + */ + public static class LineColor { + + private String r = "0", g = "0", b = "0"; + + public LineColor(String r, String g, String b) { + this.r = r; + this.g = g; + this.b = b; + } + + public String getR() { + return r; + } + + public void setR(String r) { + this.r = r; + } + + public String getG() { + return g; + } + + public void setG(String g) { + this.g = g; + } + + public String getB() { + return b; + } + + public void setB(String b) { + this.b = b; + } + } } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaQrcodeServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaQrcodeServiceImpl.java index f0fc36af16..fd58855b3d 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaQrcodeServiceImpl.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaQrcodeServiceImpl.java @@ -3,6 +3,8 @@ import cn.binarywang.wx.miniapp.api.WxMaQrcodeService; import cn.binarywang.wx.miniapp.api.WxMaService; import cn.binarywang.wx.miniapp.bean.WxMaQrcode; +import cn.binarywang.wx.miniapp.bean.WxMaWxcode; +import cn.binarywang.wx.miniapp.bean.WxMaWxcodeLimit; import cn.binarywang.wx.miniapp.util.http.QrCodeRequestExecutor; import me.chanjar.weixin.common.exception.WxErrorException; @@ -25,4 +27,49 @@ public File createQrcode(String path, int width) throws WxErrorException { url, new WxMaQrcode(path, width)); } + @Override + public File createQrcode(String path) throws WxErrorException { + return this.createQrcode(path, 430); + } + + @Override + public File createWxCode(String path, int width, boolean autoColor, LineColor lineColor) throws WxErrorException { + String url = "https://api.weixin.qq.com/wxa/getwxacode"; + WxMaWxcode wxMaWxcode = new WxMaWxcode(); + wxMaWxcode.setPath(path); + wxMaWxcode.setWidth(width); + wxMaWxcode.setAutoColor(autoColor); + wxMaWxcode.setLineColor(lineColor); + return this.wxMaService.execute(new QrCodeRequestExecutor(this.wxMaService.getRequestHttp()), + url, wxMaWxcode); + } + + @Override + public File createWxCode(String path, int width) throws WxErrorException { + return this.createWxCode(path, width, true, null); + } + + @Override + public File createWxCode(String path) throws WxErrorException { + return this.createWxCode(path, 430, true, null); + } + + @Override + public File createWxCodeLimit(String scene, String page, int width, boolean autoColor, LineColor lineColor) throws WxErrorException { + String url = "http://api.weixin.qq.com/wxa/getwxacodeunlimit"; + WxMaWxcodeLimit wxMaWxcodeLimit = new WxMaWxcodeLimit(); + wxMaWxcodeLimit.setScene(scene); + wxMaWxcodeLimit.setPage(page); + wxMaWxcodeLimit.setWidth(width); + wxMaWxcodeLimit.setAutoColor(autoColor); + wxMaWxcodeLimit.setLineColor(lineColor); + return this.wxMaService.execute(new QrCodeRequestExecutor(this.wxMaService.getRequestHttp()), + url, wxMaWxcodeLimit); + } + + @Override + public File createWxCodeLimit(String scene, String page) throws WxErrorException { + return this.createWxCodeLimit(scene, page, 430, true, null); + } + } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImpl.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImpl.java index 023306634b..106f020e53 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImpl.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaServiceImpl.java @@ -87,11 +87,7 @@ public String getAccessToken(boolean forceRefresh) throws WxErrorException { try { lock.lock(); - if (forceRefresh) { - this.getWxMaConfig().expireAccessToken(); - } - - if (this.getWxMaConfig().isAccessTokenExpired()) { + if (this.getWxMaConfig().isAccessTokenExpired() || forceRefresh) { String url = String.format(WxMaService.GET_ACCESS_TOKEN_URL, this.getWxMaConfig().getAppid(), this.getWxMaConfig().getSecret()); try { diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaJscode2SessionResult.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaJscode2SessionResult.java index 4b9cc93d6b..471e6c46ec 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaJscode2SessionResult.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaJscode2SessionResult.java @@ -18,6 +18,13 @@ public class WxMaJscode2SessionResult { @SerializedName("openid") private String openid; + @SerializedName("unionid") + private String unionid; + + public static WxMaJscode2SessionResult fromJson(String json) { + return WxMaGsonBuilder.create().fromJson(json, WxMaJscode2SessionResult.class); + } + public String getSessionKey() { return sessionKey; } @@ -42,8 +49,12 @@ public void setOpenid(String openid) { this.openid = openid; } - public static WxMaJscode2SessionResult fromJson(String json) { - return WxMaGsonBuilder.create().fromJson(json, WxMaJscode2SessionResult.class); + public String getUnionid() { + return unionid; + } + + public void setUnionid(String unionid) { + this.unionid = unionid; } } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaQrcode.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaQrcode.java index 83050f0619..a047d7c8b1 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaQrcode.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaQrcode.java @@ -7,7 +7,7 @@ /** * @author Binary Wang */ -public class WxMaQrcode implements Serializable { +public class WxMaQrcode extends WxMaQrcodeWrapper implements Serializable { private static final long serialVersionUID = 5777119669111011584L; private String path; private int width = 430; diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaQrcodeWrapper.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaQrcodeWrapper.java new file mode 100644 index 0000000000..37c5c5db88 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaQrcodeWrapper.java @@ -0,0 +1,16 @@ +package cn.binarywang.wx.miniapp.bean; + +import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; + +/** + * 微信二维码(小程序码)包装器 + * Created by Element on 2017/7/27. + */ +public abstract class WxMaQrcodeWrapper { + + @Override + public String toString() { + return WxMaGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaWxcode.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaWxcode.java new file mode 100644 index 0000000000..9ea674ed98 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaWxcode.java @@ -0,0 +1,64 @@ +package cn.binarywang.wx.miniapp.bean; + +import cn.binarywang.wx.miniapp.api.WxMaQrcodeService; +import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; +import com.google.gson.annotations.SerializedName; + +import java.io.Serializable; + +/** + * Created by Element on 2017/7/27. + */ +public class WxMaWxcode extends WxMaQrcodeWrapper implements Serializable { + + private static final long serialVersionUID = 1287399621649210322L; + private String path; + private int width = 430; + + @SerializedName("auto_color") + private boolean autoColor = true; + + @SerializedName("line_color") + private WxMaQrcodeService.LineColor lineColor = new WxMaQrcodeService.LineColor("0", "0", "0"); + + public static WxMaWxcode fromJson(String json) { + return WxMaGsonBuilder.create().fromJson(json, WxMaWxcode.class); + } + + public static long getSerialVersionUID() { + return serialVersionUID; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public int getWidth() { + return width; + } + + public void setWidth(int width) { + this.width = width; + } + + public boolean isAutoColor() { + return autoColor; + } + + public void setAutoColor(boolean autoColor) { + this.autoColor = autoColor; + } + + public WxMaQrcodeService.LineColor getLineColor() { + return lineColor; + } + + public void setLineColor(WxMaQrcodeService.LineColor lineColor) { + this.lineColor = lineColor; + } + +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaWxcodeLimit.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaWxcodeLimit.java new file mode 100644 index 0000000000..7619fe46f2 --- /dev/null +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaWxcodeLimit.java @@ -0,0 +1,68 @@ +package cn.binarywang.wx.miniapp.bean; + +import cn.binarywang.wx.miniapp.api.WxMaQrcodeService; +import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; +import com.google.gson.annotations.SerializedName; + +import java.io.Serializable; + +/** + * Created by Element on 2017/7/27. + */ +public class WxMaWxcodeLimit extends WxMaQrcodeWrapper implements Serializable { + private static final long serialVersionUID = 4782193774524960401L; + private String scene; + private String page; + + private int width = 430; + + @SerializedName("auto_color") + private boolean autoColor = true; + + @SerializedName("line_color") + private WxMaQrcodeService.LineColor lineColor = new WxMaQrcodeService.LineColor("0", "0", "0"); + + public static WxMaWxcodeLimit fromJson(String json) { + return WxMaGsonBuilder.create().fromJson(json, WxMaWxcodeLimit.class); + } + + public String getPage() { + return page; + } + + public void setPage(String page) { + this.page = page; + } + + public String getScene() { + return scene; + } + + public void setScene(String scene) { + this.scene = scene; + } + + public int getWidth() { + return width; + } + + public void setWidth(int width) { + this.width = width; + } + + public boolean isAutoColor() { + return autoColor; + } + + public void setAutoColor(boolean autoColor) { + this.autoColor = autoColor; + } + + public WxMaQrcodeService.LineColor getLineColor() { + return lineColor; + } + + public void setLineColor(WxMaQrcodeService.LineColor lineColor) { + this.lineColor = lineColor; + } +} diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/ImageBuilder.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/ImageBuilder.java index 219e3fd43b..a903e97c43 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/ImageBuilder.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/builder/ImageBuilder.java @@ -10,7 +10,7 @@ public final class ImageBuilder extends BaseBuilder
{ private String mediaId; public ImageBuilder() { - this.msgType = WxMaConstants.KefuMsgType.IMAGE; + this.msgType = WxMaConstants.KefuMsgType.IMAGE; } public ImageBuilder mediaId(String media_id) { diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/message/WxMaMessageInterceptor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/message/WxMaMessageInterceptor.java index 1b220a0baa..3443862fe1 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/message/WxMaMessageInterceptor.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/message/WxMaMessageInterceptor.java @@ -17,7 +17,7 @@ public interface WxMaMessageInterceptor { /** * 拦截微信消息 * - * @param context 上下文,如果handler或interceptor之间有信息要传递,可以用这个 + * @param context 上下文,如果handler或interceptor之间有信息要传递,可以用这个 * @return true代表OK,false代表不OK */ boolean intercept(WxMaMessage wxMessage, diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/http/QrCodeRequestExecutor.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/http/QrCodeRequestExecutor.java index 7883ffda9b..3c026f4a18 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/http/QrCodeRequestExecutor.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/http/QrCodeRequestExecutor.java @@ -1,6 +1,6 @@ package cn.binarywang.wx.miniapp.util.http; -import cn.binarywang.wx.miniapp.bean.WxMaQrcode; +import cn.binarywang.wx.miniapp.bean.WxMaQrcodeWrapper; import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.fs.FileUtils; @@ -25,7 +25,7 @@ /** * @author Binary Wang */ -public class QrCodeRequestExecutor implements RequestExecutor { +public class QrCodeRequestExecutor implements RequestExecutor { protected RequestHttp requestHttp; public QrCodeRequestExecutor(RequestHttp requestHttp) { @@ -33,7 +33,7 @@ public QrCodeRequestExecutor(RequestHttp requestHttp) { } @Override - public File execute(String uri, WxMaQrcode ticket) throws WxErrorException, IOException { + public File execute(String uri, WxMaQrcodeWrapper ticket) throws WxErrorException, IOException { HttpPost httpPost = new HttpPost(uri); if (requestHttp.getRequestHttpProxy() != null) { httpPost @@ -48,7 +48,7 @@ public File execute(String uri, WxMaQrcode ticket) throws WxErrorException, IOEx InputStream inputStream = InputStreamResponseHandler.INSTANCE.handleResponse(response);) { Header[] contentTypeHeader = response.getHeaders("Content-Type"); if (contentTypeHeader != null && contentTypeHeader.length > 0 - && ContentType.TEXT_PLAIN.getMimeType().equals(contentTypeHeader[0].getValue())) { + && ContentType.APPLICATION_JSON.getMimeType().equals(contentTypeHeader[0].getValue())) { String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); throw new WxErrorException(WxError.fromJson(responseContent)); } diff --git a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaKefuMessageGsonAdapter.java b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaKefuMessageGsonAdapter.java index 33c46d63cd..829469f872 100644 --- a/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaKefuMessageGsonAdapter.java +++ b/weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/util/json/WxMaKefuMessageGsonAdapter.java @@ -14,7 +14,6 @@ import com.google.gson.JsonObject; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; -import org.apache.commons.lang3.StringUtils; import java.lang.reflect.Type; diff --git a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaMsgServiceImplTest.java b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaMsgServiceImplTest.java index 9604a25691..37e3608bff 100644 --- a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaMsgServiceImplTest.java +++ b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaMsgServiceImplTest.java @@ -9,7 +9,8 @@ import com.google.inject.Inject; import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.exception.WxErrorException; -import org.testng.annotations.*; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; import java.text.SimpleDateFormat; import java.util.Date; diff --git a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaQrcodeServiceImplTest.java b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaQrcodeServiceImplTest.java index 48dad9362a..eba65f7c34 100644 --- a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaQrcodeServiceImplTest.java +++ b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/api/impl/WxMaQrcodeServiceImplTest.java @@ -23,4 +23,16 @@ public void testCreateQrCode() throws Exception { System.out.println(qrCode); } + @Test + public void testCreateWxCode() throws Exception { + final File wxCode = this.wxService.getQrcodeService().createWxCode("111", 122); + System.out.println(wxCode); + } + + @Test + public void testCreateWxCodeLimit() throws Exception { + final File wxCode = this.wxService.getQrcodeService().createWxCodeLimit("111", null); + System.out.println(wxCode); + } + } diff --git a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/WxMaMessageTest.java b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/WxMaMessageTest.java index 881091a1df..cdf989a6af 100644 --- a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/WxMaMessageTest.java +++ b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/bean/WxMaMessageTest.java @@ -1,6 +1,5 @@ package cn.binarywang.wx.miniapp.bean; -import cn.binarywang.wx.miniapp.bean.WxMaMessage; import me.chanjar.weixin.common.api.WxConsts; import org.testng.annotations.Test; diff --git a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/demo/WxMaDemoServer.java b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/demo/WxMaDemoServer.java index fe986c8e71..f6dcbae27b 100644 --- a/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/demo/WxMaDemoServer.java +++ b/weixin-java-miniapp/src/test/java/cn/binarywang/wx/miniapp/demo/WxMaDemoServer.java @@ -2,8 +2,8 @@ import cn.binarywang.wx.miniapp.api.WxMaService; import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl; -import cn.binarywang.wx.miniapp.bean.WxMaMessage; import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage; +import cn.binarywang.wx.miniapp.bean.WxMaMessage; import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage; import cn.binarywang.wx.miniapp.config.WxMaConfig; import cn.binarywang.wx.miniapp.constant.WxMaConstants; @@ -69,7 +69,7 @@ public void handle(WxMaMessage wxMessage, Map context, } } }; - + private static final WxMaMessageHandler qrcodeHandler = new WxMaMessageHandler() { @Override public void handle(WxMaMessage wxMessage, Map context, diff --git a/weixin-java-mp/pom.xml b/weixin-java-mp/pom.xml index 16648606b2..b4a1608b19 100644 --- a/weixin-java-mp/pom.xml +++ b/weixin-java-mp/pom.xml @@ -7,7 +7,7 @@ com.github.binarywang weixin-java-parent -2.7.6.BETA +2.8.1.BETA weixin-java-mp WeiXin Java Tools - MP diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInRedisConfigStorage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInRedisConfigStorage.java index d22214dfa1..3254972c26 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInRedisConfigStorage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInRedisConfigStorage.java @@ -1,11 +1,12 @@ package me.chanjar.weixin.mp.api; import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPool; /** * 基于Redis的微信配置provider * - * @author lly835 + * @author nickwong */ @SuppressWarnings("hiding") public class WxMpInRedisConfigStorage extends WxMpInMemoryConfigStorage { @@ -16,75 +17,115 @@ public class WxMpInRedisConfigStorage extends WxMpInMemoryConfigStorage { private final static String CARDAPI_TICKET_KEY = "wechat_cardapi_ticket_"; - protected Jedis jedis; + /** + * 使用连接池保证线程安全 + */ + protected final JedisPool jedisPool; + + private String accessTokenKey; + + private String jsapiTicketKey; + + private String cardapiTicketKey; + + public WxMpInRedisConfigStorage(JedisPool jedisPool) { + this.jedisPool = jedisPool; + } + + /** + * 每个公众号生成独有的存储key + * + * @param appId + */ + @Override + public void setAppId(String appId) { + super.setAppId(appId); + this.accessTokenKey = ACCESS_TOKEN_KEY.concat(appId); + this.jsapiTicketKey = JSAPI_TICKET_KEY.concat(appId); + this.cardapiTicketKey = CARDAPI_TICKET_KEY.concat(appId); + } @Override public String getAccessToken() { - return jedis.get(ACCESS_TOKEN_KEY.concat(appId)); + try (Jedis jedis = this.jedisPool.getResource()) { + return jedis.get(accessTokenKey); + } } @Override public boolean isAccessTokenExpired() { - return jedis.ttl(ACCESS_TOKEN_KEY.concat(appId)) < 2; + try (Jedis jedis = this.jedisPool.getResource()) { + return jedis.ttl(accessTokenKey) < 2; + } } @Override public synchronized void updateAccessToken(String accessToken, int expiresInSeconds) { - jedis.set(ACCESS_TOKEN_KEY.concat(appId), accessToken); - jedis.expire(ACCESS_TOKEN_KEY.concat(appId), expiresInSeconds - 200); + try (Jedis jedis = this.jedisPool.getResource()) { + jedis.setex(accessTokenKey, expiresInSeconds - 200, accessToken); + } } @Override public void expireAccessToken() { - jedis.expire(ACCESS_TOKEN_KEY.concat(appId), 0); + try (Jedis jedis = this.jedisPool.getResource()) { + jedis.expire(accessTokenKey, 0); + } } @Override public String getJsapiTicket() { - return jedis.get(JSAPI_TICKET_KEY.concat(appId)); + try (Jedis jedis = this.jedisPool.getResource()) { + return jedis.get(jsapiTicketKey); + } } @Override public boolean isJsapiTicketExpired() { - return jedis.ttl(JSAPI_TICKET_KEY.concat(appId)) < 2; + try (Jedis jedis = this.jedisPool.getResource()) { + return jedis.ttl(jsapiTicketKey) < 2; + } } @Override public synchronized void updateJsapiTicket(String jsapiTicket, int expiresInSeconds) { - jedis.set(JSAPI_TICKET_KEY.concat(appId), jsapiTicket); - jedis.expire(JSAPI_TICKET_KEY.concat(appId), expiresInSeconds - 200); + try (Jedis jedis = this.jedisPool.getResource()) { + jedis.setex(jsapiTicketKey, expiresInSeconds - 200, jsapiTicket); + } } @Override public void expireJsapiTicket() { - jedis.expire(JSAPI_TICKET_KEY.concat(appId), 0); + try (Jedis jedis = this.jedisPool.getResource()) { + jedis.expire(jsapiTicketKey, 0); + } } - /** - * 卡券api_ticket - */ @Override public String getCardApiTicket() { - return jedis.get(CARDAPI_TICKET_KEY.concat(appId)); + try (Jedis jedis = this.jedisPool.getResource()) { + return jedis.get(cardapiTicketKey); + } } @Override public boolean isCardApiTicketExpired() { - return jedis.ttl(CARDAPI_TICKET_KEY.concat(appId)) < 2; + try (Jedis jedis = this.jedisPool.getResource()) { + return jedis.ttl(cardapiTicketKey) < 2; + } } @Override public synchronized void updateCardApiTicket(String cardApiTicket, int expiresInSeconds) { - jedis.set(CARDAPI_TICKET_KEY.concat(appId), cardApiTicket); - jedis.expire(CARDAPI_TICKET_KEY.concat(appId), expiresInSeconds - 200); + try (Jedis jedis = this.jedisPool.getResource()) { + jedis.setex(cardapiTicketKey, expiresInSeconds - 200, cardApiTicket); + } } @Override public void expireCardApiTicket() { - jedis.expire(CARDAPI_TICKET_KEY.concat(appId), 0); - } - - public void setJedis(Jedis jedis) { - this.jedis = jedis; + try (Jedis jedis = this.jedisPool.getResource()) { + jedis.expire(cardapiTicketKey, 0); + } } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMassMessageService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMassMessageService.java new file mode 100644 index 0000000000..6d1f025728 --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMassMessageService.java @@ -0,0 +1,119 @@ +package me.chanjar.weixin.mp.api; + +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.mp.bean.*; +import me.chanjar.weixin.mp.bean.result.WxMpMassSendResult; +import me.chanjar.weixin.mp.bean.result.WxMpMassUploadResult; + +/** + *+ * 群发消息服务类 + * Created by Binary Wang on 2017-8-16. + *+ * + * @author Binary Wang + */ +public interface WxMpMassMessageService { + /** + * 上传群发用的图文消息 + */ + String MEDIA_UPLOAD_NEWS_URL = "https://api.weixin.qq.com/cgi-bin/media/uploadnews"; + /** + * 上传群发用的视频 + */ + String MEDIA_UPLOAD_VIDEO_URL = "https://api.weixin.qq.com/cgi-bin/media/uploadvideo"; + /** + * 分组群发消息 + */ + String MESSAGE_MASS_SENDALL_URL = "https://api.weixin.qq.com/cgi-bin/message/mass/sendall"; + /** + * 按openId列表群发消息 + */ + String MESSAGE_MASS_SEND_URL = "https://api.weixin.qq.com/cgi-bin/message/mass/send"; + /** + * 群发消息预览接口 + */ + String MESSAGE_MASS_PREVIEW_URL = "https://api.weixin.qq.com/cgi-bin/message/mass/preview"; + /** + * 删除群发接口 + */ + String MESSAGE_MASS_DELETE_URL = "https://api.weixin.qq.com/cgi-bin/message/mass/delete"; + + /** + *+ * 上传群发用的图文消息,上传后才能群发图文消息 + * + * 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140549&token=&lang=zh_CN + *+ * + * @see #massGroupMessageSend(WxMpMassTagMessage) + * @see #massOpenIdsMessageSend(WxMpMassOpenIdsMessage) + */ + WxMpMassUploadResult massNewsUpload(WxMpMassNews news) throws WxErrorException; + + /** + *+ * 上传群发用的视频,上传后才能群发视频消息 + * 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140549&token=&lang=zh_CN + *+ * + * @see #massGroupMessageSend(WxMpMassTagMessage) + * @see #massOpenIdsMessageSend(WxMpMassOpenIdsMessage) + */ + WxMpMassUploadResult massVideoUpload(WxMpMassVideo video) throws WxErrorException; + + /** + *+ * 分组群发消息 + * 如果发送图文消息,必须先使用 {@link #massNewsUpload(WxMpMassNews)} 获得media_id,然后再发送 + * 如果发送视频消息,必须先使用 {@link #massVideoUpload(WxMpMassVideo)} 获得media_id,然后再发送 + * 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140549&token=&lang=zh_CN + *+ */ + WxMpMassSendResult massGroupMessageSend(WxMpMassTagMessage message) throws WxErrorException; + + /** + *+ * 按openId列表群发消息 + * 如果发送图文消息,必须先使用 {@link #massNewsUpload(WxMpMassNews)} 获得media_id,然后再发送 + * 如果发送视频消息,必须先使用 {@link #massVideoUpload(WxMpMassVideo)} 获得media_id,然后再发送 + * 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140549&token=&lang=zh_CN + *+ */ + WxMpMassSendResult massOpenIdsMessageSend(WxMpMassOpenIdsMessage message) throws WxErrorException; + + /** + *+ * 群发消息预览接口 + * 开发者可通过该接口发送消息给指定用户,在手机端查看消息的样式和排版。为了满足第三方平台开发者的需求,在保留对openID预览能力的同时,增加了对指定微信号发送预览的能力,但该能力每日调用次数有限制(100次),请勿滥用。 + * 接口调用请求说明 + * http请求方式: POST + * https://api.weixin.qq.com/cgi-bin/message/mass/preview?access_token=ACCESS_TOKEN + * 详情请见:http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140549&token=&lang=zh_CN + *+ * + * @return wxMpMassSendResult + */ + WxMpMassSendResult massMessagePreview(WxMpMassPreviewMessage wxMpMassPreviewMessage) throws Exception; + + /** + *+ * 删除群发 + * 群发之后,随时可以通过该接口删除群发。 + * 请注意: + * 1、只有已经发送成功的消息才能删除 + * 2、删除消息是将消息的图文详情页失效,已经收到的用户,还是能在其本地看到消息卡片。 + * 3、删除群发消息只能删除图文消息和视频消息,其他类型的消息一经发送,无法删除。 + * 4、如果多次群发发送的是一个图文消息,那么删除其中一次群发,就会删除掉这个图文消息也,导致所有群发都失效 + * 接口调用请求说明: + * http请求方式: POST + * https://api.weixin.qq.com/cgi-bin/message/mass/delete?access_token=ACCESS_TOKEN + * 详情请见:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1481187827_i0l21 + *+ * + * @param msgId 发送出去的消息ID + * @param articleIndex 要删除的文章在图文消息中的位置,第一篇编号为1,该字段不填或填0会删除全部文章 + */ + void delete(Integer msgId, Integer articleIndex) throws Exception; + +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpQrcodeService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpQrcodeService.java index e2e17eb359..37ed7dcd12 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpQrcodeService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpQrcodeService.java @@ -26,6 +26,18 @@ public interface WxMpQrcodeService { */ WxMpQrCodeTicket qrCodeCreateTmpTicket(int sceneId, Integer expireSeconds) throws WxErrorException; + + /** + *+ * 换取临时二维码ticket + * 详情请见: 生成带参数的二维码 + *+ * + * @param sceneStr 场景值ID(字符串形式的ID),字符串类型,长度限制为1到64 + * @param expireSeconds 该二维码有效时间,以秒为单位。 最大不超过2592000(即30天),此字段如果不填,则默认有效期为30秒。 + */ + WxMpQrCodeTicket qrCodeCreateTmpTicket(String sceneStr, Integer expireSeconds) throws WxErrorException; + /** ** 换取永久二维码ticket diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java index e4da721c8e..914c902d44 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java @@ -20,26 +20,6 @@ public interface WxMpService { * 获得jsapi_ticket */ String GET_JSAPI_TICKET_URL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi"; - /** - * 上传群发用的图文消息 - */ - String MEDIA_UPLOAD_NEWS_URL = "https://api.weixin.qq.com/cgi-bin/media/uploadnews"; - /** - * 上传群发用的视频 - */ - String MEDIA_UPLOAD_VIDEO_URL = "https://api.weixin.qq.com/cgi-bin/media/uploadvideo"; - /** - * 分组群发消息 - */ - String MESSAGE_MASS_SENDALL_URL = "https://api.weixin.qq.com/cgi-bin/message/mass/sendall"; - /** - * 按openId列表群发消息 - */ - String MESSAGE_MASS_SEND_URL = "https://api.weixin.qq.com/cgi-bin/message/mass/send"; - /** - * 群发消息预览接口 - */ - String MESSAGE_MASS_PREVIEW_URL = "https://api.weixin.qq.com/cgi-bin/message/mass/preview"; /** * 长链接转短链接接口 */ @@ -141,63 +121,6 @@ public interface WxMpService { */ WxJsapiSignature createJsapiSignature(String url) throws WxErrorException; - /** - **/ public class WxDataCubeUserCumulate implements Serializable { - private static final JsonParser JSON_PARSER = new JsonParser(); private static final long serialVersionUID = -3570981300225093657L; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/AbstractDeviceBean.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/AbstractDeviceBean.java index 3a327069bc..4aef452270 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/AbstractDeviceBean.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/AbstractDeviceBean.java @@ -2,10 +2,14 @@ import me.chanjar.weixin.common.util.json.WxGsonBuilder; +import java.io.Serializable; + /** * Created by keungtung on 14/12/2016. */ -public abstract class AbstractDeviceBean { +public abstract class AbstractDeviceBean implements Serializable{ + private static final long serialVersionUID = 4359729626772515385L; + public String toJson() { return WxGsonBuilder.create().toJson(this); } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/BaseResp.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/BaseResp.java index 4b6e52d85c..7d1fd8aa77 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/BaseResp.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/BaseResp.java @@ -6,6 +6,8 @@ * Created by keungtung on 10/12/2016. */ public class BaseResp extends AbstractDeviceBean { + private static final long serialVersionUID = 4252655933699659073L; + @SerializedName("base_info") private BaseInfo baseInfo; @SerializedName("errcode") diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/RespMsg.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/RespMsg.java index 1932e1d166..9c62d36f93 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/RespMsg.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/RespMsg.java @@ -7,6 +7,8 @@ */ public class RespMsg extends AbstractDeviceBean { + private static final long serialVersionUID = -4241272701707684136L; + @SerializedName("ret_code") private Integer retCode; @SerializedName("error_info") diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/TransMsgResp.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/TransMsgResp.java index 31525f6bad..1572da75ac 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/TransMsgResp.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/TransMsgResp.java @@ -7,6 +7,8 @@ * Created by keungtung on 14/12/2016. */ public class TransMsgResp extends AbstractDeviceBean { + private static final long serialVersionUID = 5386954916622816491L; + private Integer ret; @SerializedName("ret_info") private String retInfo; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDevice.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDevice.java index c0f95dbf2a..4527d368d2 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDevice.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDevice.java @@ -2,10 +2,14 @@ import com.google.gson.annotations.SerializedName; +import java.io.Serializable; + /** * Created by keungtung on 10/12/2016. */ -public class WxDevice { +public class WxDevice implements Serializable { + private static final long serialVersionUID = -3284819760735456195L; + private String id; private String mac; @SerializedName("connect_protocol") diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceAuthorize.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceAuthorize.java index 0318754e57..055e41c879 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceAuthorize.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceAuthorize.java @@ -10,6 +10,8 @@ * Created by keungtung on 10/12/2016. */ public class WxDeviceAuthorize extends AbstractDeviceBean { + private static final long serialVersionUID = 8786321356569903887L; + @SerializedName("device_num") private String deviceNum; @SerializedName("op_type") diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceAuthorizeResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceAuthorizeResult.java index 83ea27c5b2..560f5498bb 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceAuthorizeResult.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceAuthorizeResult.java @@ -8,6 +8,8 @@ * Created by keungtung on 10/12/2016. */ public class WxDeviceAuthorizeResult extends AbstractDeviceBean { + private static final long serialVersionUID = 9105294570912249811L; + private List- * 上传群发用的图文消息,上传后才能群发图文消息 - * - * 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140549&token=&lang=zh_CN - *- * - * @see #massGroupMessageSend(me.chanjar.weixin.mp.bean.WxMpMassTagMessage) - * @see #massOpenIdsMessageSend(me.chanjar.weixin.mp.bean.WxMpMassOpenIdsMessage) - */ - WxMpMassUploadResult massNewsUpload(WxMpMassNews news) throws WxErrorException; - - /** - *- * 上传群发用的视频,上传后才能群发视频消息 - * 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140549&token=&lang=zh_CN - *- * - * @see #massGroupMessageSend(me.chanjar.weixin.mp.bean.WxMpMassTagMessage) - * @see #massOpenIdsMessageSend(me.chanjar.weixin.mp.bean.WxMpMassOpenIdsMessage) - */ - WxMpMassUploadResult massVideoUpload(WxMpMassVideo video) throws WxErrorException; - - /** - *- * 分组群发消息 - * 如果发送图文消息,必须先使用 {@link #massNewsUpload(me.chanjar.weixin.mp.bean.WxMpMassNews)} 获得media_id,然后再发送 - * 如果发送视频消息,必须先使用 {@link #massVideoUpload(me.chanjar.weixin.mp.bean.WxMpMassVideo)} 获得media_id,然后再发送 - * 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140549&token=&lang=zh_CN - *- */ - WxMpMassSendResult massGroupMessageSend(WxMpMassTagMessage message) throws WxErrorException; - - /** - *- * 按openId列表群发消息 - * 如果发送图文消息,必须先使用 {@link #massNewsUpload(me.chanjar.weixin.mp.bean.WxMpMassNews)} 获得media_id,然后再发送 - * 如果发送视频消息,必须先使用 {@link #massVideoUpload(me.chanjar.weixin.mp.bean.WxMpMassVideo)} 获得media_id,然后再发送 - * 详情请见: http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140549&token=&lang=zh_CN - *- */ - WxMpMassSendResult massOpenIdsMessageSend(WxMpMassOpenIdsMessage message) throws WxErrorException; - - /** - *- * 群发消息预览接口 - * 开发者可通过该接口发送消息给指定用户,在手机端查看消息的样式和排版。为了满足第三方平台开发者的需求,在保留对openID预览能力的同时,增加了对指定微信号发送预览的能力,但该能力每日调用次数有限制(100次),请勿滥用。 - * 接口调用请求说明 - * http请求方式: POST - * https://api.weixin.qq.com/cgi-bin/message/mass/preview?access_token=ACCESS_TOKEN - * 详情请见:http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140549&token=&lang=zh_CN - *- * - * @return wxMpMassSendResult - */ - WxMpMassSendResult massMessagePreview(WxMpMassPreviewMessage wxMpMassPreviewMessage) throws Exception; - /** ** 长链接转短链接接口 @@ -451,5 +374,39 @@ public interface WxMpService { */ RequestHttp getRequestHttp(); + /** + * 返回群发消息相关接口方法的实现类对象,以方便调用其各个接口 + * @return WxMpMassMessageService + */ + WxMpMassMessageService getMassMessageService(); + + void setKefuService(WxMpKefuService kefuService); + + void setMaterialService(WxMpMaterialService materialService); + + void setMenuService(WxMpMenuService menuService); + + void setUserService(WxMpUserService userService); + + void setTagService(WxMpUserTagService tagService); + + void setQrCodeService(WxMpQrcodeService qrCodeService); + + void setCardService(WxMpCardService cardService); + + void setStoreService(WxMpStoreService storeService); + + void setDataCubeService(WxMpDataCubeService dataCubeService); + + void setBlackListService(WxMpUserBlacklistService blackListService); + + void setTemplateMsgService(WxMpTemplateMsgService templateMsgService); + + void setDeviceService(WxMpDeviceService deviceService); + + void setShakeService(WxMpShakeService shakeService); + + void setMemberCardService(WxMpMemberCardService memberCardService); + void setMassMessageService(WxMpMassMessageService massMessageService); } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpUserTagService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpUserTagService.java index cee28b73ba..4a666eff1b 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpUserTagService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpUserTagService.java @@ -76,7 +76,7 @@ WxTagListUser tagListUser(Long tagId, String nextOpenid) ** - * @param openid + * @param openid openid * @return {@link WxMpUserQuery} */ public WxMpUserQuery add(String openid) { @@ -74,7 +76,7 @@ public WxMpUserQuery add(String openid) { /** * 删除指定的OpenId,语言使用默认(zh_CN) * - * @param openid + * @param openid openid * @return {@link WxMpUserQuery} */ public WxMpUserQuery remove(String openid) { @@ -85,7 +87,7 @@ public WxMpUserQuery remove(String openid) { /** * 删除指定的OpenId * - * @param openid + * @param openid openid * @param lang 国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语 * @return {@link WxMpUserQuery} */ diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/datacube/WxDataCubeArticleResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/datacube/WxDataCubeArticleResult.java index fe6627d244..e6518064bb 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/datacube/WxDataCubeArticleResult.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/datacube/WxDataCubeArticleResult.java @@ -14,8 +14,7 @@ * Created by Binary Wang on 2016/8/24. */ public class WxDataCubeArticleResult extends WxDataCubeBaseResult { - - private static final JsonParser JSON_PARSER = new JsonParser(); + private static final long serialVersionUID = -9222452497954511765L; /** * ref_hour diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/datacube/WxDataCubeArticleTotal.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/datacube/WxDataCubeArticleTotal.java index eee6240f7b..a059c45f3b 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/datacube/WxDataCubeArticleTotal.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/datacube/WxDataCubeArticleTotal.java @@ -14,8 +14,7 @@ * Created by Binary Wang on 2016/8/24. */ public class WxDataCubeArticleTotal extends WxDataCubeBaseResult { - - private static final JsonParser JSON_PARSER = new JsonParser(); + private static final long serialVersionUID = -7634365687303052699L; /** * msgid diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/datacube/WxDataCubeArticleTotalDetail.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/datacube/WxDataCubeArticleTotalDetail.java index 27f9b8aa12..86897427d1 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/datacube/WxDataCubeArticleTotalDetail.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/datacube/WxDataCubeArticleTotalDetail.java @@ -2,13 +2,16 @@ import com.google.gson.annotations.SerializedName; +import java.io.Serializable; + /** * 获取图文群发总数据接口(getarticletotal)中的详细字段 * * @author binarywang(Binary Wang) * Created by Binary Wang on 2016/8/24. */ -public class WxDataCubeArticleTotalDetail { +public class WxDataCubeArticleTotalDetail implements Serializable{ + private static final long serialVersionUID = -5136169129771430052L; /** * stat_date diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/datacube/WxDataCubeBaseResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/datacube/WxDataCubeBaseResult.java index 25fbcc62a9..cfc8636143 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/datacube/WxDataCubeBaseResult.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/datacube/WxDataCubeBaseResult.java @@ -1,15 +1,23 @@ package me.chanjar.weixin.mp.bean.datacube; +import com.google.gson.JsonParser; import com.google.gson.annotations.SerializedName; import me.chanjar.weixin.common.util.ToStringUtils; +import java.io.Serializable; + /** - * 统计接口的共用属性类 + ** 批量为用户取消标签 * 详情请见:用户标签管理 - * 接口url格式: https://api.weixin.qq.com/cgi-bin/tags/members/batchtagging?access_token=ACCESS_TOKEN + * 接口url格式: https://api.weixin.qq.com/cgi-bin/tags/members/batchuntagging?access_token=ACCESS_TOKEN **/ boolean batchUntagging(Long tagId, String[] openids) throws WxErrorException; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMassMessageServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMassMessageServiceImpl.java new file mode 100644 index 0000000000..c54fcc768c --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpMassMessageServiceImpl.java @@ -0,0 +1,67 @@ +package me.chanjar.weixin.mp.api.impl; + +import com.google.gson.JsonObject; +import me.chanjar.weixin.common.exception.WxErrorException; +import me.chanjar.weixin.mp.api.WxMpMassMessageService; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.*; +import me.chanjar.weixin.mp.bean.result.WxMpMassSendResult; +import me.chanjar.weixin.mp.bean.result.WxMpMassUploadResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + *+ * 群发消息服务类 + * Created by Binary Wang on 2017-8-16. + *+ * + * @author Binary Wang + */ +public class WxMpMassMessageServiceImpl implements WxMpMassMessageService { + protected final Logger log = LoggerFactory.getLogger(this.getClass()); + private WxMpService wxMpService; + + public WxMpMassMessageServiceImpl(WxMpService wxMpService) { + this.wxMpService = wxMpService; + } + + @Override + public WxMpMassUploadResult massNewsUpload(WxMpMassNews news) throws WxErrorException { + String responseContent = this.wxMpService.post(MEDIA_UPLOAD_NEWS_URL, news.toJson()); + return WxMpMassUploadResult.fromJson(responseContent); + } + + @Override + public WxMpMassUploadResult massVideoUpload(WxMpMassVideo video) throws WxErrorException { + String responseContent = this.wxMpService.post(MEDIA_UPLOAD_VIDEO_URL, video.toJson()); + return WxMpMassUploadResult.fromJson(responseContent); + } + + @Override + public WxMpMassSendResult massGroupMessageSend(WxMpMassTagMessage message) throws WxErrorException { + String responseContent = this.wxMpService.post(WxMpMassMessageService.MESSAGE_MASS_SENDALL_URL, message.toJson()); + return WxMpMassSendResult.fromJson(responseContent); + } + + @Override + public WxMpMassSendResult massOpenIdsMessageSend(WxMpMassOpenIdsMessage message) throws WxErrorException { + String responseContent = this.wxMpService.post(MESSAGE_MASS_SEND_URL, message.toJson()); + return WxMpMassSendResult.fromJson(responseContent); + } + + @Override + public WxMpMassSendResult massMessagePreview(WxMpMassPreviewMessage wxMpMassPreviewMessage) throws Exception { + String responseContent = this.wxMpService.post(MESSAGE_MASS_PREVIEW_URL, wxMpMassPreviewMessage.toJson()); + return WxMpMassSendResult.fromJson(responseContent); + } + + @Override + public void delete(Integer msgId, Integer articleIndex) throws Exception { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("msg_id", msgId); + jsonObject.addProperty("article_idx", articleIndex); + this.wxMpService.post(MESSAGE_MASS_DELETE_URL, jsonObject.toString()); + } + +} diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpQrcodeServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpQrcodeServiceImpl.java index 817a0b68f2..5f6c3ad54f 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpQrcodeServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpQrcodeServiceImpl.java @@ -7,6 +7,7 @@ import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; import me.chanjar.weixin.mp.util.http.QrCodeRequestExecutor; +import org.apache.commons.lang3.StringUtils; import java.io.File; import java.io.UnsupportedEncodingException; @@ -54,6 +55,38 @@ public WxMpQrCodeTicket qrCodeCreateTmpTicket(int sceneId, Integer expireSeconds return WxMpQrCodeTicket.fromJson(responseContent); } + + @Override + public WxMpQrCodeTicket qrCodeCreateTmpTicket(String sceneStr, Integer expireSeconds) throws WxErrorException { + if (StringUtils.isBlank(sceneStr)) { + throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg("临时二维码场景值不能为空!").build()); + } + + //expireSeconds 该二维码有效时间,以秒为单位。 最大不超过2592000(即30天),此字段如果不填,则默认有效期为30秒。 + if (expireSeconds != null && expireSeconds > 2592000) { + throw new WxErrorException(WxError.newBuilder().setErrorCode(-1) + .setErrorMsg("临时二维码有效时间最大不能超过2592000(即30天)!").build()); + } + + if (expireSeconds == null) { + expireSeconds = 30; + } + + String url = API_URL_PREFIX + "/create"; + JsonObject json = new JsonObject(); + json.addProperty("action_name", "QR_STR_SCENE"); + json.addProperty("expire_seconds", expireSeconds); + + JsonObject actionInfo = new JsonObject(); + JsonObject scene = new JsonObject(); + scene.addProperty("scene_str", sceneStr); + actionInfo.add("scene", scene); + json.add("action_info", actionInfo); + String responseContent = this.wxMpService.post(url, json.toString()); + return WxMpQrCodeTicket.fromJson(responseContent); + } + + @Override public WxMpQrCodeTicket qrCodeCreateLastTicket(int sceneId) throws WxErrorException { if (sceneId < 1 || sceneId > 100000) { diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/AbstractWxMpServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceAbstractImpl.java similarity index 87% rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/AbstractWxMpServiceImpl.java rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceAbstractImpl.java index cc965026c4..e4482d5aa7 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/AbstractWxMpServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceAbstractImpl.java @@ -22,7 +22,7 @@ import java.io.IOException; import java.util.concurrent.locks.Lock; -public abstract class AbstractWxMpServiceImplimplements WxMpService, RequestHttp { +public abstract class WxMpServiceAbstractImpl implements WxMpService, RequestHttp { private static final JsonParser JSON_PARSER = new JsonParser(); @@ -43,6 +43,7 @@ public abstract class AbstractWxMpServiceImpl implements WxMpService, Requ private WxMpDeviceService deviceService = new WxMpDeviceServiceImpl(this); private WxMpShakeService shakeService = new WxMpShakeServiceImpl(this); private WxMpMemberCardService memberCardService = new WxMpMemberCardServiceImpl(this); + private WxMpMassMessageService massMessageService = new WxMpMassMessageServiceImpl(this); private int retrySleepMillis = 1000; private int maxRetryTimes = 5; @@ -66,10 +67,9 @@ public String getJsapiTicket() throws WxErrorException { @Override public String getJsapiTicket(boolean forceRefresh) throws WxErrorException { - Lock lock = this.getWxMpConfigStorage().getJsapiTicketLock(); + Lock lock = this.getWxMpConfigStorage().getAccessTokenLock(); try { lock.lock(); - if (forceRefresh) { this.getWxMpConfigStorage().expireJsapiTicket(); } @@ -109,36 +109,6 @@ public String getAccessToken() throws WxErrorException { return getAccessToken(false); } - @Override - public WxMpMassUploadResult massNewsUpload(WxMpMassNews news) throws WxErrorException { - String responseContent = this.post(WxMpService.MEDIA_UPLOAD_NEWS_URL, news.toJson()); - return WxMpMassUploadResult.fromJson(responseContent); - } - - @Override - public WxMpMassUploadResult massVideoUpload(WxMpMassVideo video) throws WxErrorException { - String responseContent = this.post(WxMpService.MEDIA_UPLOAD_VIDEO_URL, video.toJson()); - return WxMpMassUploadResult.fromJson(responseContent); - } - - @Override - public WxMpMassSendResult massGroupMessageSend(WxMpMassTagMessage message) throws WxErrorException { - String responseContent = this.post(WxMpService.MESSAGE_MASS_SENDALL_URL, message.toJson()); - return WxMpMassSendResult.fromJson(responseContent); - } - - @Override - public WxMpMassSendResult massOpenIdsMessageSend(WxMpMassOpenIdsMessage message) throws WxErrorException { - String responseContent = this.post(WxMpService.MESSAGE_MASS_SEND_URL, message.toJson()); - return WxMpMassSendResult.fromJson(responseContent); - } - - @Override - public WxMpMassSendResult massMessagePreview(WxMpMassPreviewMessage wxMpMassPreviewMessage) throws Exception { - String responseContent = this.post(WxMpService.MESSAGE_MASS_PREVIEW_URL, wxMpMassPreviewMessage.toJson()); - return WxMpMassSendResult.fromJson(responseContent); - } - @Override public String shortUrl(String long_url) throws WxErrorException { JsonObject o = new JsonObject(); @@ -416,4 +386,84 @@ public WxMpMemberCardService getMemberCardService() { public RequestHttp getRequestHttp() { return this; } + + @Override + public WxMpMassMessageService getMassMessageService() { + return this.massMessageService; + } + + @Override + public void setKefuService(WxMpKefuService kefuService) { + this.kefuService = kefuService; + } + + @Override + public void setMaterialService(WxMpMaterialService materialService) { + this.materialService = materialService; + } + + @Override + public void setMenuService(WxMpMenuService menuService) { + this.menuService = menuService; + } + + @Override + public void setUserService(WxMpUserService userService) { + this.userService = userService; + } + + @Override + public void setTagService(WxMpUserTagService tagService) { + this.tagService = tagService; + } + + @Override + public void setQrCodeService(WxMpQrcodeService qrCodeService) { + this.qrCodeService = qrCodeService; + } + + @Override + public void setCardService(WxMpCardService cardService) { + this.cardService = cardService; + } + + @Override + public void setStoreService(WxMpStoreService storeService) { + this.storeService = storeService; + } + + @Override + public void setDataCubeService(WxMpDataCubeService dataCubeService) { + this.dataCubeService = dataCubeService; + } + + @Override + public void setBlackListService(WxMpUserBlacklistService blackListService) { + this.blackListService = blackListService; + } + + @Override + public void setTemplateMsgService(WxMpTemplateMsgService templateMsgService) { + this.templateMsgService = templateMsgService; + } + + @Override + public void setDeviceService(WxMpDeviceService deviceService) { + this.deviceService = deviceService; + } + + @Override + public void setShakeService(WxMpShakeService shakeService) { + this.shakeService = shakeService; + } + + @Override + public void setMemberCardService(WxMpMemberCardService memberCardService) { + this.memberCardService = memberCardService; + } + + @Override + public void setMassMessageService(WxMpMassMessageService massMessageService) { + this.massMessageService = massMessageService; + } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceApacheHttpClientImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceApacheHttpClientImpl.java index d929b0974c..dd8aaf6114 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceApacheHttpClientImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceApacheHttpClientImpl.java @@ -21,7 +21,7 @@ /** * apache-http方式实现 */ -public class WxMpServiceApacheHttpClientImpl extends AbstractWxMpServiceImpl { +public class WxMpServiceApacheHttpClientImpl extends WxMpServiceAbstractImpl { private CloseableHttpClient httpClient; private HttpHost httpProxy; @@ -65,12 +65,7 @@ public String getAccessToken(boolean forceRefresh) throws WxErrorException { Lock lock = this.getWxMpConfigStorage().getAccessTokenLock(); try { lock.lock(); - - if (forceRefresh) { - this.getWxMpConfigStorage().expireAccessToken(); - } - - if (this.getWxMpConfigStorage().isAccessTokenExpired()) { + if (this.getWxMpConfigStorage().isAccessTokenExpired() || forceRefresh) { String url = String.format(WxMpService.GET_ACCESS_TOKEN_URL, this.getWxMpConfigStorage().getAppId(), this.getWxMpConfigStorage().getSecret()); try { diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceJoddHttpImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceJoddHttpImpl.java index 5c0fb75300..f146c365e8 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceJoddHttpImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceJoddHttpImpl.java @@ -14,7 +14,7 @@ /** * jodd-http方式实现 */ -public class WxMpServiceJoddHttpImpl extends AbstractWxMpServiceImpl { +public class WxMpServiceJoddHttpImpl extends WxMpServiceAbstractImpl { private HttpConnectionProvider httpClient; private ProxyInfo httpProxy; @@ -51,11 +51,7 @@ public String getAccessToken(boolean forceRefresh) throws WxErrorException { try { lock.lock(); - if (forceRefresh) { - this.getWxMpConfigStorage().expireAccessToken(); - } - - if (this.getWxMpConfigStorage().isAccessTokenExpired()) { + if (this.getWxMpConfigStorage().isAccessTokenExpired() || forceRefresh) { String url = String.format(WxMpService.GET_ACCESS_TOKEN_URL, this.getWxMpConfigStorage().getAppId(), this.getWxMpConfigStorage().getSecret()); diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceOkHttpImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceOkHttpImpl.java index 81fb848909..9066dc8d17 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceOkHttpImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpServiceOkHttpImpl.java @@ -8,16 +8,21 @@ import me.chanjar.weixin.mp.api.WxMpConfigStorage; import me.chanjar.weixin.mp.api.WxMpService; import okhttp3.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.concurrent.locks.Lock; -public class WxMpServiceOkHttpImpl extends AbstractWxMpServiceImpl { - private ConnectionPool httpClient; +public class WxMpServiceOkHttpImpl extends WxMpServiceAbstractImpl { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private OkHttpClient httpClient; private OkHttpProxyInfo httpProxy; @Override - public ConnectionPool getRequestHttpClient() { + public OkHttpClient getRequestHttpClient() { return httpClient; } @@ -33,38 +38,17 @@ public HttpType getRequestType() { @Override public String getAccessToken(boolean forceRefresh) throws WxErrorException { + logger.debug("WxMpServiceOkHttpImpl is running"); Lock lock = this.getWxMpConfigStorage().getAccessTokenLock(); try { lock.lock(); - if (forceRefresh) { - this.getWxMpConfigStorage().expireAccessToken(); - } - - if (this.getWxMpConfigStorage().isAccessTokenExpired()) { + if (this.getWxMpConfigStorage().isAccessTokenExpired() || forceRefresh) { String url = String.format(WxMpService.GET_ACCESS_TOKEN_URL, this.getWxMpConfigStorage().getAppId(), this.getWxMpConfigStorage().getSecret()); - OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder().connectionPool(httpClient); - //设置代理 - if (httpProxy != null) { - clientBuilder.proxy(getRequestHttpProxy().getProxy()); - } - //设置授权 - clientBuilder.authenticator(new Authenticator() { - @Override - public Request authenticate(Route route, Response response) throws IOException { - String credential = Credentials.basic(httpProxy.getProxyUsername(), httpProxy.getProxyPassword()); - return response.request().newBuilder() - .header("Authorization", credential) - .build(); - } - }); - //得到httpClient - OkHttpClient client = clientBuilder.build(); - Request request = new Request.Builder().url(url).get().build(); - Response response = client.newCall(request).execute(); + Response response = getRequestHttpClient().newCall(request).execute(); String resultContent = response.body().string(); WxError error = WxError.fromJson(resultContent); if (error.getErrorCode() != 0) { @@ -84,13 +68,29 @@ public Request authenticate(Route route, Response response) throws IOException { @Override public void initHttp() { + logger.debug("WxMpServiceOkHttpImpl initHttp"); WxMpConfigStorage configStorage = this.getWxMpConfigStorage(); if (configStorage.getHttpProxyHost() != null && configStorage.getHttpProxyPort() > 0) { - httpProxy = new OkHttpProxyInfo(OkHttpProxyInfo.ProxyType.SOCKS5, configStorage.getHttpProxyHost(), configStorage.getHttpProxyPort(), configStorage.getHttpProxyUsername(), configStorage.getHttpProxyPassword()); + httpProxy = OkHttpProxyInfo.socks5Proxy(configStorage.getHttpProxyHost(), configStorage.getHttpProxyPort(), configStorage.getHttpProxyUsername(), configStorage.getHttpProxyPassword()); } + OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder(); + //设置代理 + if (httpProxy != null) { + clientBuilder.proxy(getRequestHttpProxy().getProxy()); - httpClient = new ConnectionPool(); + //设置授权 + clientBuilder.authenticator(new Authenticator() { + @Override + public Request authenticate(Route route, Response response) throws IOException { + String credential = Credentials.basic(httpProxy.getProxyUsername(), httpProxy.getProxyPassword()); + return response.request().newBuilder() + .header("Authorization", credential) + .build(); + } + }); + } + httpClient = clientBuilder.build(); } } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpCard.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpCard.java index bc50ce059e..76fc4a6451 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpCard.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpCard.java @@ -3,13 +3,16 @@ import me.chanjar.weixin.common.util.ToStringUtils; +import java.io.Serializable; + /** * 微信卡券 * * @author YuJian * @version 15/11/11 */ -public class WxMpCard { +public class WxMpCard implements Serializable{ + private static final long serialVersionUID = 9214301870017772921L; private String cardId; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassNews.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassNews.java index dc1acd3bd3..bb19f0e79e 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassNews.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassNews.java @@ -13,11 +13,8 @@ * @author chanjarster */ public class WxMpMassNews implements Serializable { - - /** - * - */ private static final long serialVersionUID = 565937155013581016L; + private List articles = new ArrayList<>(); public List getArticles() { diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassPreviewMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassPreviewMessage.java index d70ac57071..503bdec43b 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassPreviewMessage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassPreviewMessage.java @@ -9,6 +9,7 @@ */ public class WxMpMassPreviewMessage implements Serializable { private static final long serialVersionUID = 9095211638358424020L; + private String toWxUserName; private String toWxUserOpenid; private String msgType; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassTagMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassTagMessage.java index cdf14f79bd..acf9d0f4c1 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassTagMessage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassTagMessage.java @@ -10,8 +10,8 @@ * @author chanjarster */ public class WxMpMassTagMessage implements Serializable { - private static final long serialVersionUID = -6625914040986749286L; + private Long tagId; private String msgType; private String content; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassVideo.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassVideo.java index 38eef7c8a1..1683be5bdf 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassVideo.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpMassVideo.java @@ -10,11 +10,8 @@ * @author chanjarster */ public class WxMpMassVideo implements Serializable { - - /** - * - */ private static final long serialVersionUID = 9153925016061915637L; + private String mediaId; private String title; private String description; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpSemanticQuery.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpSemanticQuery.java index f4b1c3da00..8c18a6a9ea 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpSemanticQuery.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpSemanticQuery.java @@ -12,11 +12,8 @@ * @author Daniel Qian */ public class WxMpSemanticQuery implements Serializable { - - /** - * - */ private static final long serialVersionUID = 7685873048199870690L; + private String query; private String category; private Float latitude; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpShakeInfoResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpShakeInfoResult.java index ac94b457b0..5fb2ab1735 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpShakeInfoResult.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpShakeInfoResult.java @@ -11,6 +11,7 @@ * @author rememberber */ public class WxMpShakeInfoResult implements Serializable { + private static final long serialVersionUID = -1604561297395395468L; private Integer errcode; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpShakeQuery.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpShakeQuery.java index bb9d326fad..0f4aeadd19 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpShakeQuery.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpShakeQuery.java @@ -2,6 +2,7 @@ import com.google.gson.Gson; +import java.io.Serializable; import java.util.HashMap; import java.util.Map; @@ -10,7 +11,8 @@ * * @author rememberber */ -public class WxMpShakeQuery { +public class WxMpShakeQuery implements Serializable { + private static final long serialVersionUID = 4316527352035275412L; private String ticket; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpUserQuery.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpUserQuery.java index 800e03e915..243163c28b 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpUserQuery.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpUserQuery.java @@ -14,7 +14,9 @@ * * @author LiuJunGuang */ -public class WxMpUserQuery { +public class WxMpUserQuery implements Serializable { + private static final long serialVersionUID = -1344224837373149313L; + private List queryParamList = new ArrayList<>(); public WxMpUserQuery() { @@ -24,7 +26,7 @@ public WxMpUserQuery() { /** * 语言使用默认(zh_CN) * - * @param openids + * @param openids openid列表 */ public WxMpUserQuery(List openids) { super(); @@ -34,7 +36,7 @@ public WxMpUserQuery(List openids) { /** * 添加OpenId列表,语言使用默认(zh_CN) * - * @param openids + * @param openids openid列表 * @return {@link WxMpUserQuery} */ public WxMpUserQuery add(List openids) { @@ -47,7 +49,7 @@ public WxMpUserQuery add(List openids) { /** * 添加一个OpenId * - * @param openid + * @param openid openid * @param lang 国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语 * @return {@link WxMpUserQuery} */ @@ -63,7 +65,7 @@ public WxMpUserQuery add(String openid, String lang) { * 该方法默认lang = zh_CN * + * 统计接口的共用属性类 + * Created by Binary Wang on 2016/8/25. + ** * @author binarywang(Binary Wang) - * Created by Binary Wang on 2016/8/25. */ -public class WxDataCubeBaseResult { +public abstract class WxDataCubeBaseResult implements Serializable { + private static final long serialVersionUID = 8780389911053297600L; + protected static final JsonParser JSON_PARSER = new JsonParser(); + /** * ref_date * 数据的日期,需在begin_date和end_date之间 diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/datacube/WxDataCubeInterfaceResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/datacube/WxDataCubeInterfaceResult.java index 9606c6f98d..fce9fc2018 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/datacube/WxDataCubeInterfaceResult.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/datacube/WxDataCubeInterfaceResult.java @@ -14,8 +14,7 @@ * Created by Binary Wang on 2016/8/30. */ public class WxDataCubeInterfaceResult extends WxDataCubeBaseResult { - - private static final JsonParser JSON_PARSER = new JsonParser(); + private static final long serialVersionUID = 597734329161281398L; /** * ref_hour diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/datacube/WxDataCubeMsgResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/datacube/WxDataCubeMsgResult.java index b3592190dc..4800c9c422 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/datacube/WxDataCubeMsgResult.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/datacube/WxDataCubeMsgResult.java @@ -14,8 +14,7 @@ * Created by Binary Wang on 2016/8/29. */ public class WxDataCubeMsgResult extends WxDataCubeBaseResult { - - private static final JsonParser JSON_PARSER = new JsonParser(); + private static final long serialVersionUID = 6932121822150573659L; /** * ref_hour diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/datacube/WxDataCubeUserCumulate.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/datacube/WxDataCubeUserCumulate.java index 32f8d5f5c0..d3237a3b6e 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/datacube/WxDataCubeUserCumulate.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/datacube/WxDataCubeUserCumulate.java @@ -16,7 +16,6 @@ *resp; public static WxDeviceAuthorizeResult fromJson(String response) { diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceBind.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceBind.java index 1acf59628a..4945cfbbf2 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceBind.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceBind.java @@ -6,6 +6,8 @@ * Created by keungtung on 10/12/2016. */ public class WxDeviceBind extends AbstractDeviceBean { + private static final long serialVersionUID = 467559769037590880L; + private String ticket; @SerializedName("device_id") private String deviceId; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceBindDeviceResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceBindDeviceResult.java index d0ed2dcd60..52c5f45609 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceBindDeviceResult.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceBindDeviceResult.java @@ -9,6 +9,8 @@ * Created by keungtung on 16/12/2016. */ public class WxDeviceBindDeviceResult extends AbstractDeviceBean { + private static final long serialVersionUID = 725870295905935355L; + @SerializedName("resp_msg") private RespMsg respMsg; @SerializedName("openid") diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceBindResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceBindResult.java index 2cbf007835..c26e9c85d1 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceBindResult.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceBindResult.java @@ -7,6 +7,8 @@ * Created by keungtung on 10/12/2016. */ public class WxDeviceBindResult extends AbstractDeviceBean { + private static final long serialVersionUID = 4687725146279339359L; + @SerializedName("base_resp") private BaseResp baseResp; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceMsg.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceMsg.java index 680209fd71..182cb27241 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceMsg.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceMsg.java @@ -7,6 +7,8 @@ * Created by keungtung on 10/12/2016. */ public class WxDeviceMsg extends AbstractDeviceBean { + private static final long serialVersionUID = -5567110858455277963L; + @SerializedName("device_type") private String deviceType; @SerializedName("device_id") diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceOpenIdResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceOpenIdResult.java index 0a23eddd3a..a2ea56c080 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceOpenIdResult.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceOpenIdResult.java @@ -9,6 +9,8 @@ * Created by keungtung on 16/12/2016. */ public class WxDeviceOpenIdResult extends AbstractDeviceBean { + private static final long serialVersionUID = 4980885167833836220L; + @SerializedName("errcode") private Integer errCode; @SerializedName("errmsg") diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceQrCodeResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceQrCodeResult.java index ff3028be4f..8d6efac90b 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceQrCodeResult.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/device/WxDeviceQrCodeResult.java @@ -7,6 +7,8 @@ * Created by keungtung on 10/12/2016. */ public class WxDeviceQrCodeResult extends AbstractDeviceBean { + private static final long serialVersionUID = -4312858303060918266L; + @SerializedName("deviceid") private String deviceId; @SerializedName("qrticket") diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfList.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfList.java index b5cef947a9..5cce093dfc 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfList.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfList.java @@ -4,12 +4,15 @@ import me.chanjar.weixin.common.util.ToStringUtils; import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; +import java.io.Serializable; import java.util.List; /** * @author Binary Wang */ -public class WxMpKfList { +public class WxMpKfList implements Serializable { + private static final long serialVersionUID = -8194193505173564894L; + @SerializedName("kf_list") private List kfList; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfMsgList.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfMsgList.java index 02d249192f..253652a883 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfMsgList.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfMsgList.java @@ -4,12 +4,15 @@ import me.chanjar.weixin.common.util.ToStringUtils; import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; +import java.io.Serializable; import java.util.List; /** * Created by Binary Wang on 2016/7/15. */ -public class WxMpKfMsgList { +public class WxMpKfMsgList implements Serializable { + private static final long serialVersionUID = 4524296707435188202L; + @SerializedName("recordlist") private List records; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfMsgRecord.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfMsgRecord.java index c7ada50081..1b32164879 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfMsgRecord.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfMsgRecord.java @@ -3,10 +3,14 @@ import com.google.gson.annotations.SerializedName; import me.chanjar.weixin.common.util.ToStringUtils; +import java.io.Serializable; + /** * Created by Binary Wang on 2016/7/18. */ -public class WxMpKfMsgRecord { +public class WxMpKfMsgRecord implements Serializable { + private static final long serialVersionUID = -280692188908528688L; + /** * worker 完整客服帐号,格式为:帐号前缀@公众号微信号 */ diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfOnlineList.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfOnlineList.java index 1f7545cbfa..6778520c2b 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfOnlineList.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfOnlineList.java @@ -4,12 +4,15 @@ import me.chanjar.weixin.common.util.ToStringUtils; import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; +import java.io.Serializable; import java.util.List; /** * @author Binary Wang */ -public class WxMpKfOnlineList { +public class WxMpKfOnlineList implements Serializable { + private static final long serialVersionUID = -6154705288500854617L; + @SerializedName("kf_online_list") private List kfOnlineList; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSession.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSession.java index 500fc7577a..b36edb9f2d 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSession.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSession.java @@ -3,10 +3,14 @@ import com.google.gson.annotations.SerializedName; import me.chanjar.weixin.common.util.ToStringUtils; +import java.io.Serializable; + /** * @author Binary Wang */ -public class WxMpKfSession { +public class WxMpKfSession implements Serializable { + private static final long serialVersionUID = 7804332813164994062L; + /** * kf_account 正在接待的客服,为空表示没有人在接待 */ diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSessionGetResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSessionGetResult.java index b0177acdfd..d6ed763e9f 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSessionGetResult.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSessionGetResult.java @@ -4,10 +4,14 @@ import me.chanjar.weixin.common.util.ToStringUtils; import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; +import java.io.Serializable; + /** * @author Binary Wang */ -public class WxMpKfSessionGetResult { +public class WxMpKfSessionGetResult implements Serializable { + private static final long serialVersionUID = 8474846575200033152L; + /** * kf_account 正在接待的客服,为空表示没有人在接待 */ diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSessionList.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSessionList.java index dd03668695..f1eb4dd7cb 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSessionList.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSessionList.java @@ -4,12 +4,15 @@ import me.chanjar.weixin.common.util.ToStringUtils; import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; +import java.io.Serializable; import java.util.List; /** * @author Binary Wang */ -public class WxMpKfSessionList { +public class WxMpKfSessionList implements Serializable { + private static final long serialVersionUID = -7680371346226640206L; + /** * 会话列表 */ diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSessionWaitCaseList.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSessionWaitCaseList.java index 562113f191..7dd8def8cf 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSessionWaitCaseList.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/result/WxMpKfSessionWaitCaseList.java @@ -4,12 +4,15 @@ import me.chanjar.weixin.common.util.ToStringUtils; import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; +import java.io.Serializable; import java.util.List; /** * @author Binary Wang */ -public class WxMpKfSessionWaitCaseList { +public class WxMpKfSessionWaitCaseList implements Serializable { + private static final long serialVersionUID = 2432132626631361922L; + /** * count 未接入会话数量 */ diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/material/WxMediaImgUploadResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/material/WxMediaImgUploadResult.java index 387a791ac6..1110a1f16b 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/material/WxMediaImgUploadResult.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/material/WxMediaImgUploadResult.java @@ -8,9 +8,6 @@ * @author miller */ public class WxMediaImgUploadResult implements Serializable { - /** - * - */ private static final long serialVersionUID = 1996392453428768829L; private String url; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/material/WxMpMaterial.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/material/WxMpMaterial.java index 8725510a84..e176620f43 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/material/WxMpMaterial.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/material/WxMpMaterial.java @@ -1,10 +1,12 @@ package me.chanjar.weixin.mp.bean.material; import java.io.File; +import java.io.Serializable; import java.util.HashMap; import java.util.Map; -public class WxMpMaterial { +public class WxMpMaterial implements Serializable { + private static final long serialVersionUID = -1651816949780969485L; private String name; private File file; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/material/WxMpMaterialArticleUpdate.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/material/WxMpMaterialArticleUpdate.java index 371b7e0d30..f2f7aa1201 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/material/WxMpMaterialArticleUpdate.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/material/WxMpMaterialArticleUpdate.java @@ -5,11 +5,8 @@ import java.io.Serializable; public class WxMpMaterialArticleUpdate implements Serializable { - - /** - * - */ private static final long serialVersionUID = -7611963949517780270L; + private String mediaId; private int index; private WxMpMaterialNews.WxMpMaterialNewsArticle articles; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/material/WxMpMaterialCountResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/material/WxMpMaterialCountResult.java index 6dd74889ca..4a74b6b64b 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/material/WxMpMaterialCountResult.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/material/WxMpMaterialCountResult.java @@ -6,6 +6,7 @@ public class WxMpMaterialCountResult implements Serializable { private static final long serialVersionUID = -5568772662085874138L; + private int voiceCount; private int videoCount; private int imageCount; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/material/WxMpMaterialFileBatchGetResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/material/WxMpMaterialFileBatchGetResult.java index 5df9f4546c..b08a0ce3c4 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/material/WxMpMaterialFileBatchGetResult.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/material/WxMpMaterialFileBatchGetResult.java @@ -8,6 +8,7 @@ public class WxMpMaterialFileBatchGetResult implements Serializable { private static final long serialVersionUID = -560388368297267884L; + private int totalCount; private int itemCount; private List items; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/material/WxMpMaterialVideoInfoResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/material/WxMpMaterialVideoInfoResult.java index be5dd3f844..e0558cc888 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/material/WxMpMaterialVideoInfoResult.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/material/WxMpMaterialVideoInfoResult.java @@ -5,11 +5,8 @@ import java.io.Serializable; public class WxMpMaterialVideoInfoResult implements Serializable { - - /** - * - */ private static final long serialVersionUID = 1269131745333792202L; + private String title; private String description; private String downUrl; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/MemberCardUserInfo.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/MemberCardUserInfo.java index 336008b085..b9c771c487 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/MemberCardUserInfo.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/MemberCardUserInfo.java @@ -1,9 +1,12 @@ package me.chanjar.weixin.mp.bean.membercard; +import java.io.Serializable; + /** * Created by YuJian on 2017/7/11. */ -public class MemberCardUserInfo { +public class MemberCardUserInfo implements Serializable { + private static final long serialVersionUID = -4259196162619282129L; private NameValues[] commonFieldList; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/NameValues.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/NameValues.java index ae30d7a9a4..a5c62e5e6a 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/NameValues.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/NameValues.java @@ -1,9 +1,13 @@ package me.chanjar.weixin.mp.bean.membercard; +import java.io.Serializable; + /** * Created by YuJian on 2017/7/11. */ -public class NameValues { +public class NameValues implements Serializable{ + private static final long serialVersionUID = -8529369702944594330L; + private String name; private String value; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/NotifyOptional.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/NotifyOptional.java index a8adae8ac7..e44ec4b5ac 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/NotifyOptional.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/NotifyOptional.java @@ -2,26 +2,37 @@ import com.google.gson.annotations.SerializedName; +import java.io.Serializable; + /** + * * 控制原生消息结构体,包含各字段的消息控制字段。 * * 用于 `7 更新会员信息` 的接口参数调用 * https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1451025283 + ** * @author YuJian(mgcnrx11@gmail.com) * @version 2017/7/15 */ -public class NotifyOptional { +public class NotifyOptional implements Serializable { + private static final long serialVersionUID = 4488842021504939176L; - // 积分变动时是否触发系统模板消息,默认为true + /** + * 积分变动时是否触发系统模板消息,默认为true + */ @SerializedName("is_notify_bonus") private Boolean isNotifyBonus; - // 余额变动时是否触发系统模板消息,默认为true + /** + * 余额变动时是否触发系统模板消息,默认为true + */ @SerializedName("is_notify_balance") private Boolean isNotifyBalance; - // 自定义group1变动时是否触发系统模板消息,默认为false。(2、3同理) + /** + * 自定义group1变动时是否触发系统模板消息,默认为false。(2、3同理) + */ @SerializedName("is_notify_custom_field1") private Boolean isNotifyCustomField1; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardActivatedMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardActivatedMessage.java index 8040224a09..0c782e3c51 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardActivatedMessage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardActivatedMessage.java @@ -2,47 +2,74 @@ import com.google.gson.annotations.SerializedName; +import java.io.Serializable; + /** * 会员卡激活接口的参数 * * @author YuJian(mgcnrx11@hotmail.com) * @version 2017/7/8 */ -public class WxMpMemberCardActivatedMessage { +public class WxMpMemberCardActivatedMessage implements Serializable { + private static final long serialVersionUID = -5972713484594266480L; - // 会员卡编号,由开发者填入,作为序列号显示在用户的卡包里。可与Code码保持等值。 + /** + * 会员卡编号,由开发者填入,作为序列号显示在用户的卡包里。可与Code码保持等值。 + */ @SerializedName("membership_number") private String membershipNumber; - // 领取会员卡用户获得的code + /** + * 领取会员卡用户获得的code + */ private String code; - // 卡券ID,自定义code卡券必填 + /** + * 卡券ID,自定义code卡券必填 + */ @SerializedName("card_id") private String cardId; - // 商家自定义会员卡背景图,须先调用上传图片接口将背景图上传至CDN,否则报错。卡面设计请遵循微信会员卡自定义背景设计规范 + /** + * 商家自定义会员卡背景图,须先调用上传图片接口将背景图上传至CDN,否则报错。卡面设计请遵循微信会员卡自定义背景设计规范 + */ @SerializedName("background_pic_url") private String backgroundPicUrl; - // 激活后的有效起始时间。若不填写默认以创建时的 data_info 为准。Unix时间戳格式。 + /** + * 激活后的有效起始时间。若不填写默认以创建时的 data_info 为准。Unix时间戳格式。 + */ @SerializedName("activate_begin_time") private Integer activateBeginTime; - // 激活后的有效截至时间。若不填写默认以创建时的 data_info 为准。Unix时间戳格式。 + /** + * 激活后的有效截至时间。若不填写默认以创建时的 data_info 为准。Unix时间戳格式。 + */ @SerializedName("activate_end_time") private Integer activateEndTime; - // 初始积分,不填为0。 + /** + * 初始积分,不填为0。 + */ @SerializedName("init_bonus") private Integer initBonus; - // 积分同步说明。 + /** + * 积分同步说明。 + */ @SerializedName("init_bonus_record") private String initBonusRecord; - // 初始余额,不填为0。 + /** + * 初始余额,不填为0。 + */ @SerializedName("init_balance") private Integer initBalance; - // 创建时字段custom_field1定义类型的初始值,限制为4个汉字,12字节。 + /** + * 创建时字段custom_field1定义类型的初始值,限制为4个汉字,12字节。 + */ @SerializedName("init_custom_field_value1") private String initCustomFieldValue1; - // 创建时字段custom_field2定义类型的初始值,限制为4个汉字,12字节。 + /** + * 创建时字段custom_field2定义类型的初始值,限制为4个汉字,12字节。 + */ @SerializedName("init_custom_field_value2") private String initCustomFieldValue2; - // 创建时字段custom_field3定义类型的初始值,限制为4个汉字,12字节。 + /** + * 创建时字段custom_field3定义类型的初始值,限制为4个汉字,12字节。 + */ @SerializedName("init_custom_field_value3") private String initCustomFieldValue3; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardUpdateMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardUpdateMessage.java index f4d410185d..313ba66282 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardUpdateMessage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardUpdateMessage.java @@ -2,44 +2,69 @@ import com.google.gson.annotations.SerializedName; +import java.io.Serializable; + /** + ** 更新会员信息所需字段消息。 * * 1.开发者可以同时传入add_bonus和bonus解决由于同步失败带来的幂等性问题。同时传入add_bonus和bonus时 * add_bonus作为积分变动消息中的变量值,而bonus作为卡面上的总积分额度显示。余额变动同理。 * 2.开发者可以传入is_notify_bonus控制特殊的积分对账变动不发送消息,余额变动同理。 + ** * @author YuJian(mgcnrx11@gmail.com) * @version 2017/7/15 */ -public class WxMpMemberCardUpdateMessage { +public class WxMpMemberCardUpdateMessage implements Serializable { + private static final long serialVersionUID = 4953923160718911058L; - // 领取会员卡用户获得的code + /** + * 领取会员卡用户获得的code + */ private String code; - // 卡券ID,自定义code卡券必填 + /** + * 卡券ID,自定义code卡券必填 + */ @SerializedName("card_id") private String cardId; - // 支持商家激活时针对单个会员卡分配自定义的会员卡背景 + /** + * 支持商家激活时针对单个会员卡分配自定义的会员卡背景 + */ @SerializedName("background_pic_url") private String backgroundPicUrl; - // 需要设置的积分全量值,传入的数值会直接显示 + /** + * 需要设置的积分全量值,传入的数值会直接显示 + */ private Integer bonus; - // 本次积分变动值,传负数代表减少 + /** + * 本次积分变动值,传负数代表减少 + */ @SerializedName("add_bonus") private Integer addBounus; - // 商家自定义积分消耗记录,不超过14个汉字 + /** + * 商家自定义积分消耗记录,不超过14个汉字 + */ @SerializedName("record_bonus") private String recordBonus; - // 需要设置的余额全量值,传入的数值会直接显示在卡面 + /** + * 需要设置的余额全量值,传入的数值会直接显示在卡面 + */ private Integer balance; - // 本次余额变动值,传负数代表减少 + /** + * 本次余额变动值,传负数代表减少 + */ @SerializedName("add_balance") private Integer addBalance; - // 商家自定义金额消耗记录,不超过14个汉字。 + /** + * 商家自定义金额消耗记录,不超过14个汉字。 + */ @SerializedName("record_balance") private String recordBalance; - // 创建时字段custom_field定义类型的最新数值,限制为4个汉字,12字节。 + /** + * 创建时字段custom_field定义类型的最新数值,限制为4个汉字,12字节。 + */ @SerializedName("custom_field_value1") private String customFieldValue1; @SerializedName("custom_field_value2") diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardUpdateResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardUpdateResult.java index e615cb0721..2cbe2efb2f 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardUpdateResult.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardUpdateResult.java @@ -1,17 +1,20 @@ package me.chanjar.weixin.mp.bean.membercard; +import me.chanjar.weixin.common.util.ToStringUtils; import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; import java.io.Serializable; /** + ** 用于 `7 更新会员信息` 的接口调用后的返回结果 * https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1451025283 + ** * @author YuJian(mgcnrx11@gmail.com) * @version 2017/7/15 */ -public class WxMpMemberCardUpdateResult implements Serializable { +public class WxMpMemberCardUpdateResult implements Serializable { private static final long serialVersionUID = 9084886191442098311L; @@ -67,13 +70,7 @@ public void setResultBalance(Integer resultBalance) { @Override public String toString() { - return "WxMpMemberCardUpdateResult{" + - "errorCode='" + errorCode + '\'' + - ", errorMsg='" + errorMsg + '\'' + - ", openId='" + openId + '\'' + - ", resultBonus=" + resultBonus + - ", resultBalance=" + resultBalance + - '}'; + return ToStringUtils.toSimpleString(this); } public static WxMpMemberCardUpdateResult fromJson(String json) { diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardUserInfoResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardUserInfoResult.java index 1ddb57d34b..82a24cd297 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardUserInfoResult.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/membercard/WxMpMemberCardUserInfoResult.java @@ -1,13 +1,16 @@ package me.chanjar.weixin.mp.bean.membercard; +import me.chanjar.weixin.common.util.ToStringUtils; import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; import java.io.Serializable; /** + ** 拉取会员信息返回的结果 * * 字段格式参考https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1451025283 6.2.1小节的步骤5 + ** * @author YuJian * @version 2017/7/9 @@ -122,18 +125,7 @@ public void setHasActive(Boolean hasActive) { @Override public String toString() { - return "WxMpMemberCardUserInfoResult{" + - "errorCode='" + errorCode + '\'' + - ", errorMsg='" + errorMsg + '\'' + - ", openId='" + openId + '\'' + - ", nickname='" + nickname + '\'' + - ", membershipNumber='" + membershipNumber + '\'' + - ", bonus=" + bonus + - ", sex='" + sex + '\'' + - ", userInfo=" + userInfo + - ", userCardStatus='" + userCardStatus + '\'' + - ", hasActive=" + hasActive + - '}'; + return ToStringUtils.toSimpleString(this); } public static WxMpMemberCardUserInfoResult fromJson(String json) { diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/menu/WxMpGetSelfMenuInfoResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/menu/WxMpGetSelfMenuInfoResult.java index b78d2dc378..295a782696 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/menu/WxMpGetSelfMenuInfoResult.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/menu/WxMpGetSelfMenuInfoResult.java @@ -4,13 +4,17 @@ import me.chanjar.weixin.common.util.ToStringUtils; import me.chanjar.weixin.common.util.json.WxGsonBuilder; +import java.io.Serializable; + /** ** Created by Binary Wang on 2016-11-25. * @author binarywang(Binary Wang) **/ -public class WxMpGetSelfMenuInfoResult { +public class WxMpGetSelfMenuInfoResult implements Serializable { + private static final long serialVersionUID = -5612495636936835166L; + @SerializedName("selfmenu_info") private WxMpSelfMenuInfo selfMenuInfo; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/menu/WxMpMenu.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/menu/WxMpMenu.java index 366ca2f1ba..5e93d7e0d6 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/menu/WxMpMenu.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/menu/WxMpMenu.java @@ -6,6 +6,7 @@ import me.chanjar.weixin.common.util.ToStringUtils; import me.chanjar.weixin.common.util.json.WxGsonBuilder; +import java.io.Serializable; import java.util.List; /** @@ -15,7 +16,9 @@ * @author binarywang(Binary Wang) *
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/HardWare.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/HardWare.java index 32dfcd7e2f..1ef3ee6b7c 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/HardWare.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/HardWare.java @@ -5,6 +5,8 @@ import me.chanjar.weixin.common.util.ToStringUtils; import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; +import java.io.Serializable; + /** ** Created by BinaryWang on 2017/5/4. @@ -13,7 +15,9 @@ * @author Binary Wang */ @XStreamAlias("HardWare") -public class HardWare { +public class HardWare implements Serializable{ + private static final long serialVersionUID = -1295785297354896461L; + /** * 消息展示,目前支持myrank(排行榜) */ diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/ScanCodeInfo.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/ScanCodeInfo.java index ddebffdf61..c5c32cb522 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/ScanCodeInfo.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/ScanCodeInfo.java @@ -5,6 +5,8 @@ import me.chanjar.weixin.common.util.ToStringUtils; import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; +import java.io.Serializable; + /** ** Created by BinaryWang on 2017/5/4. @@ -13,7 +15,9 @@ * @author Binary Wang */ @XStreamAlias("ScanCodeInfo") -public class ScanCodeInfo { +public class ScanCodeInfo implements Serializable { + private static final long serialVersionUID = 4745181270645050122L; + @XStreamAlias("ScanType") @XStreamConverter(value = XStreamCDataConverter.class) private String scanType; @@ -30,7 +34,6 @@ public String toString() { * 扫描类型,一般是qrcode */ public String getScanType() { - return this.scanType; } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/SendLocationInfo.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/SendLocationInfo.java index a397ab8193..8ecb3c8bff 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/SendLocationInfo.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/SendLocationInfo.java @@ -5,6 +5,8 @@ import me.chanjar.weixin.common.util.ToStringUtils; import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; +import java.io.Serializable; + /** ** Created by BinaryWang on 2017/5/4. @@ -13,7 +15,8 @@ * @author Binary Wang */ @XStreamAlias("SendLocationInfo") -public class SendLocationInfo { +public class SendLocationInfo implements Serializable { + private static final long serialVersionUID = 6633214140499161130L; @XStreamAlias("Location_X") @XStreamConverter(value = XStreamCDataConverter.class) diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/SendPicsInfo.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/SendPicsInfo.java index 3461355c9a..cf5c374edf 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/SendPicsInfo.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/SendPicsInfo.java @@ -5,6 +5,7 @@ import me.chanjar.weixin.common.util.ToStringUtils; import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; +import java.io.Serializable; import java.util.ArrayList; import java.util.List; @@ -16,9 +17,12 @@ * @author Binary Wang */ @XStreamAlias("SendPicsInfo") -public class SendPicsInfo { +public class SendPicsInfo implements Serializable { + private static final long serialVersionUID = -4572837013294199227L; + @XStreamAlias("PicList") protected final List- picList = new ArrayList<>(); + @XStreamAlias("Count") private Long count; @@ -40,7 +44,9 @@ public List
- getPicList() { } @XStreamAlias("item") - public static class Item { + public static class Item implements Serializable { + private static final long serialVersionUID = 7706235740094081194L; + @XStreamAlias("PicMd5Sum") @XStreamConverter(value = XStreamCDataConverter.class) private String picMd5Sum; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlMessage.java index 262399b8f4..2ea17b9e07 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlMessage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlMessage.java @@ -25,7 +25,6 @@ */ @XStreamAlias("xml") public class WxMpXmlMessage implements Serializable { - private static final long serialVersionUID = -3586245291677274914L; /////////////////////// @@ -425,6 +424,8 @@ public class WxMpXmlMessage implements Serializable { private Integer deviceStatus; public static WxMpXmlMessage fromXml(String xml) { + //修改微信变态的消息内容格式,方便解析 + xml = xml.replace("
+ * 门店基础信息 + * Created by Binary Wang on 2016-09-23. + ** * @author binarywang(Binary Wang) - * Created by Binary Wang on 2016-09-23. */ -public class WxMpStoreBaseInfo { +public class WxMpStoreBaseInfo implements Serializable { + private static final long serialVersionUID = 829577606838118218L; + /** * sid * 商户自己的id,用于后续审核通过收到poi_id 的通知时,做对应关系。请商户自己保证唯一识别性 @@ -351,12 +356,21 @@ public void setPoiId(String poiId) { this.poiId = poiId; } - public static class WxMpStorePhoto { + public static class WxMpStorePhoto implements Serializable { + private static final long serialVersionUID = -2942447907614186861L; /** * 照片url */ @SerializedName("photo_url") private String photoUrl; + + public String getPhotoUrl() { + return photoUrl; + } + + public void setPhotoUrl(String photoUrl) { + this.photoUrl = photoUrl; + } } public static class WxMpStoreBaseInfoBuilder { diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/store/WxMpStoreInfo.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/store/WxMpStoreInfo.java index 8f0b040191..fcbb9aa5ea 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/store/WxMpStoreInfo.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/store/WxMpStoreInfo.java @@ -3,7 +3,11 @@ import com.google.gson.annotations.SerializedName; import me.chanjar.weixin.common.util.ToStringUtils; -public class WxMpStoreInfo { +import java.io.Serializable; + +public class WxMpStoreInfo implements Serializable{ + private static final long serialVersionUID = 7300598931768355461L; + @SerializedName("base_info") private WxMpStoreBaseInfo baseInfo; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/store/WxMpStoreListResult.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/store/WxMpStoreListResult.java index 3b2c2fc157..6ebb58901f 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/store/WxMpStoreListResult.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/store/WxMpStoreListResult.java @@ -4,15 +4,20 @@ import me.chanjar.weixin.common.util.ToStringUtils; import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; +import java.io.Serializable; import java.util.List; /** + *
* 门店列表结果类 + * Created by Binary Wang on 2016-09-27. + ** * @author binarywang(Binary Wang) - * Created by Binary Wang on 2016-09-27. */ -public class WxMpStoreListResult { +public class WxMpStoreListResult implements Serializable { + private static final long serialVersionUID = 5388907559949538663L; + /** * 错误码,0为正常 */ diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/tag/WxTagListUser.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/tag/WxTagListUser.java index 952b764c9c..a1bd50660e 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/tag/WxTagListUser.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/tag/WxTagListUser.java @@ -4,15 +4,19 @@ import me.chanjar.weixin.common.util.ToStringUtils; import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; +import java.io.Serializable; import java.util.List; /** + *
* 获取标签下粉丝列表的结果对象 + * Created by Binary Wang on 2016-09-19. + ** * @author binarywang(Binary Wang) - * Created by Binary Wang on 2016-09-19. */ -public class WxTagListUser { +public class WxTagListUser implements Serializable { + private static final long serialVersionUID = -4551768374200676112L; /** * "count":2,这次获取的粉丝数量 @@ -67,7 +71,9 @@ public void setNextOpenid(String nextOpenid) { this.nextOpenid = nextOpenid; } - public static class WxTagListUserData { + public static class WxTagListUserData implements Serializable { + private static final long serialVersionUID = -8584537400336245701L; + /** * openid 列表 */ diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/tag/WxUserTag.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/tag/WxUserTag.java index 59d2458fbc..a06a1ce40a 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/tag/WxUserTag.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/tag/WxUserTag.java @@ -5,15 +5,20 @@ import me.chanjar.weixin.common.util.ToStringUtils; import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; +import java.io.Serializable; import java.util.List; /** - * 用户标签对象 + *
+ * 用户标签对象 + * Created by Binary Wang on 2016/9/2. + ** * @author binarywang(Binary Wang) - * Created by Binary Wang on 2016/9/2. */ -public class WxUserTag { +public class WxUserTag implements Serializable { + private static final long serialVersionUID = -7722428695667031252L; + /** * id 标签id,由微信分配 */ diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/template/WxMpTemplate.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/template/WxMpTemplate.java index 38761f3d4e..079210775a 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/template/WxMpTemplate.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/template/WxMpTemplate.java @@ -6,18 +6,21 @@ import me.chanjar.weixin.common.util.ToStringUtils; import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; +import java.io.Serializable; import java.util.List; /** *
* 模板列表信息 * Created by Binary Wang on 2016-10-17. - * @author binarywang(Binary Wang) *+ * + * @author binarywang(Binary Wang) */ -public class WxMpTemplate { - +public class WxMpTemplate implements Serializable { private static final JsonParser JSON_PARSER = new JsonParser(); + private static final long serialVersionUID = -7366474522571199372L; + /** * template_id * 模板ID diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/template/WxMpTemplateData.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/template/WxMpTemplateData.java index 0eb0eaa58d..f9d81e4028 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/template/WxMpTemplateData.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/template/WxMpTemplateData.java @@ -6,8 +6,8 @@ * @author Daniel Qian */ public class WxMpTemplateData implements Serializable { - private static final long serialVersionUID = 6301835292940277870L; + private String name; private String value; private String color; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/template/WxMpTemplateIndustry.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/template/WxMpTemplateIndustry.java index 63576fc2ce..b142c3f70f 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/template/WxMpTemplateIndustry.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/template/WxMpTemplateIndustry.java @@ -11,6 +11,7 @@ */ public class WxMpTemplateIndustry implements Serializable { private static final long serialVersionUID = -7700398224795914722L; + private Industry primaryIndustry; private Industry secondIndustry; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/template/WxMpTemplateMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/template/WxMpTemplateMessage.java index 70034a63b4..95d619a486 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/template/WxMpTemplateMessage.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/template/WxMpTemplateMessage.java @@ -97,7 +97,9 @@ public String toJson() { return WxMpGsonBuilder.INSTANCE.create().toJson(this); } - public static class MiniProgram { + public static class MiniProgram implements Serializable { + private static final long serialVersionUID = -7945254706501974849L; + private String appid; private String pagePath; diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMaterialUploadRequestExecutor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMaterialUploadRequestExecutor.java index 474fcb9936..445ff2736e 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMaterialUploadRequestExecutor.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/util/http/apache/ApacheMaterialUploadRequestExecutor.java @@ -8,6 +8,7 @@ import me.chanjar.weixin.mp.bean.material.WxMpMaterial; import me.chanjar.weixin.mp.bean.material.WxMpMaterialUploadResult; import me.chanjar.weixin.mp.util.http.MaterialUploadRequestExecutor; +import org.apache.http.Consts; import org.apache.http.HttpHost; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; @@ -15,6 +16,7 @@ import org.apache.http.entity.ContentType; import org.apache.http.entity.mime.HttpMultipartMode; import org.apache.http.entity.mime.MultipartEntityBuilder; +import org.apache.http.entity.mime.content.StringBody; import org.apache.http.impl.client.CloseableHttpClient; import java.io.File; @@ -53,7 +55,8 @@ public WxMpMaterialUploadResult execute(String uri, WxMpMaterial material) throw .setMode(HttpMultipartMode.RFC6532); Map
+ * 微信支付接口请求数据封装对象 + * Created by Binary Wang on 2017-8-25. + *+ * + * @author Binary Wang + */ +public class WxPayApiData { + /** + * 接口请求地址 + */ + private String url; + + /** + * 请求数据 + */ + private String requestData; + + /** + * 响应数据 + */ + private String responseData; + + /** + * 接口请求异常信息 + */ + private String exceptionMsg; + + /** + * @param url 接口请求地址 + * @param requestData 请求数据 + * @param responseData 响应数据 + * @param exceptionMsg 接口请求异常信息 + */ + public WxPayApiData(String url, String requestData, String responseData, String exceptionMsg) { + this.url = url; + this.requestData = requestData; + this.responseData = responseData; + this.exceptionMsg = exceptionMsg; + } + + public String getUrl() { + return this.url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getRequestData() { + return this.requestData; + } + + public void setRequestData(String requestData) { + this.requestData = requestData; + } + + public String getResponseData() { + return this.responseData; + } + + public void setResponseData(String responseData) { + this.responseData = responseData; + } + + public String getExceptionMsg() { + return this.exceptionMsg; + } + + public void setExceptionMsg(String exceptionMsg) { + this.exceptionMsg = exceptionMsg; + } + + @Override + public String toString() { + if (this.exceptionMsg != null) { + return String.format("\n【请求地址】:%s\n【请求数据】:%s\n【异常信息】:%s", + this, url, this.requestData, this.exceptionMsg); + } + + return String.format("\n【请求地址】:%s\n【请求数据】:%s\n【响应数据】:%s", + this.url, this.requestData, this.responseData); + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/WxPayOrderNotifyResponse.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayNotifyResponse.java similarity index 79% rename from weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/WxPayOrderNotifyResponse.java rename to weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayNotifyResponse.java index e369293195..e7a7ea9099 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/WxPayOrderNotifyResponse.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayNotifyResponse.java @@ -1,4 +1,4 @@ -package com.github.binarywang.wxpay.bean; +package com.github.binarywang.wxpay.bean.notify; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; @@ -7,8 +7,11 @@ import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; import me.chanjar.weixin.common.util.xml.XStreamInitializer; +/** + * 微信支付订单和退款的异步通知共用的响应类 + */ @XStreamAlias("xml") -public class WxPayOrderNotifyResponse { +public class WxPayNotifyResponse { @XStreamOmitField private transient static final String FAIL = "FAIL"; @XStreamOmitField @@ -21,25 +24,25 @@ public class WxPayOrderNotifyResponse { @XStreamAlias("return_msg") private String returnMsg; - public WxPayOrderNotifyResponse() { + public WxPayNotifyResponse() { super(); } - public WxPayOrderNotifyResponse(String returnCode, String returnMsg) { + public WxPayNotifyResponse(String returnCode, String returnMsg) { super(); this.returnCode = returnCode; this.returnMsg = returnMsg; } public static String fail(String msg) { - WxPayOrderNotifyResponse response = new WxPayOrderNotifyResponse(FAIL, msg); + WxPayNotifyResponse response = new WxPayNotifyResponse(FAIL, msg); XStream xstream = XStreamInitializer.getInstance(); xstream.autodetectAnnotations(true); return xstream.toXML(response); } public static String success(String msg) { - WxPayOrderNotifyResponse response = new WxPayOrderNotifyResponse(SUCCESS, msg); + WxPayNotifyResponse response = new WxPayNotifyResponse(SUCCESS, msg); XStream xstream = XStreamInitializer.getInstance(); xstream.autodetectAnnotations(true); return xstream.toXML(response); diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/WxPayOrderNotifyCoupon.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayOrderNotifyCoupon.java similarity index 96% rename from weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/WxPayOrderNotifyCoupon.java rename to weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayOrderNotifyCoupon.java index c2b4e22e74..cd948dfbac 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/WxPayOrderNotifyCoupon.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayOrderNotifyCoupon.java @@ -1,4 +1,4 @@ -package com.github.binarywang.wxpay.bean; +package com.github.binarywang.wxpay.bean.notify; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayOrderNotifyResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayOrderNotifyResult.java similarity index 98% rename from weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayOrderNotifyResult.java rename to weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayOrderNotifyResult.java index a411cd2c70..54657ac6ae 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayOrderNotifyResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayOrderNotifyResult.java @@ -1,6 +1,6 @@ -package com.github.binarywang.wxpay.bean.result; +package com.github.binarywang.wxpay.bean.notify; -import com.github.binarywang.wxpay.bean.WxPayOrderNotifyCoupon; +import com.github.binarywang.wxpay.bean.result.WxPayBaseResult; import com.github.binarywang.wxpay.converter.WxPayOrderNotifyResultConverter; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; @@ -20,7 +20,6 @@ */ @XStreamAlias("xml") public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializable { - private static final long serialVersionUID = 5389718115223345496L; /** diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayRefundNotifyResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayRefundNotifyResult.java new file mode 100644 index 0000000000..392c10144c --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/notify/WxPayRefundNotifyResult.java @@ -0,0 +1,372 @@ +package com.github.binarywang.wxpay.bean.notify; + +import com.github.binarywang.wxpay.bean.result.WxPayBaseResult; +import com.github.binarywang.wxpay.exception.WxPayException; +import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.annotations.XStreamAlias; +import me.chanjar.weixin.common.util.ToStringUtils; +import me.chanjar.weixin.common.util.xml.XStreamInitializer; +import org.apache.commons.codec.binary.Base64; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import java.io.Serializable; +import java.math.BigInteger; +import java.security.MessageDigest; + +/** + *
+ * 退款结果通知对象 + * Created by BinaryWang on 2017/8/27. + *+ * + * @author Binary Wang + */ +@XStreamAlias("xml") +public class WxPayRefundNotifyResult extends WxPayBaseResult implements Serializable { + private static final long serialVersionUID = 4651725860079259186L; + + /** + * 从xml字符串创建bean对象 + * + * @param xmlString xml字符串 + * @param mchKey 商户密钥 + */ + public static WxPayRefundNotifyResult fromXML(String xmlString, String mchKey) throws WxPayException { + WxPayRefundNotifyResult result = WxPayBaseResult.fromXML(xmlString, WxPayRefundNotifyResult.class); + String reqInfoString = result.getReqInfoString(); + try { + Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); + + final MessageDigest md5 = MessageDigest.getInstance("MD5"); + md5.update(mchKey.getBytes()); + final String keyMd5String = new BigInteger(1, md5.digest()).toString(16).toLowerCase(); + SecretKeySpec key = new SecretKeySpec(keyMd5String.getBytes(), "AES"); + cipher.init(Cipher.DECRYPT_MODE, key); + result.setReqInfo(ReqInfo.fromXML(new String(cipher.doFinal(Base64.decodeBase64(reqInfoString))))); + } catch (Exception e) { + throw new WxPayException("解密退款通知加密信息时出错", e); + } + + return result; + } + + /** + *
+ * 字段名:加密信息 + * 变量名:req_info + * 是否必填:是 + * 类型:String(1024) + * 描述:加密信息请用商户证书与商户秘钥进行解密 + *+ */ + @XStreamAlias("req_info") + private String reqInfoString; + + private ReqInfo reqInfo; + + /** + * 加密信息字段解密后的内容 + */ + @XStreamAlias("root") + public static class ReqInfo { + @Override + public String toString() { + return ToStringUtils.toSimpleString(this); + } + + /** + *
+ * 字段名:微信订单号 + * 变量名:transaction_id + * 是否必填:是 + * 类型:String(32) + * 示例值:1217752501201407033233368018 + * 描述:微信订单号 + *+ */ + @XStreamAlias("transaction_id") + private String transactionId; + + /** + *
+ * 字段名:商户订单号 + * 变量名:out_trade_no + * 是否必填:是 + * 类型:String(32) + * 示例值:1217752501201407033233368018 + * 描述:商户系统内部的订单号 + *+ */ + @XStreamAlias("out_trade_no") + private String outTradeNo; + + /** + *
+ * 字段名:微信退款单号 + * 变量名:refund_id + * 是否必填:是 + * 类型:String(28) + * 示例值:1217752501201407033233368018 + * 描述:微信退款单号 + *+ */ + @XStreamAlias("refund_id") + private String refundId; + + /** + *
+ * 字段名:商户退款单号 + * 变量名:out_refund_no + * 是否必填:是 + * 类型:String(64) + * 示例值:1217752501201407033233368018 + * 描述:商户退款单号 + *+ */ + @XStreamAlias("out_refund_no") + private String outRefundNo; + + /** + *
+ * 字段名:订单金额 + * 变量名:total_fee + * 是否必填:是 + * 类型:Int + * 示例值:100 + * 描述:订单总金额,单位为分,只能为整数,详见支付金额 + *+ */ + @XStreamAlias("total_fee") + private Integer totalFee; + + /** + *
+ * 字段名:结订单金额 + * 变量名:settlement_total_fee + * 是否必填:否 + * 类型:Int + * 示例值:100 + * 描述:当该订单有使用非充值券时,返回此字段。应结订单金额=订单金额-非充值代金券金额,应结订单金额<=订单金额。 + *+ */ + @XStreamAlias("settlement_total_fee") + private Integer settlementTotalFee; + + /** + *
+ * 字段名:申请退款金额 + * 变量名:refund_fee + * 是否必填:是 + * 类型:Int + * 示例值:100 + * 描述:退款总金额,单位为分 + *+ */ + @XStreamAlias("refund_fee") + private Integer refundFee; + + /** + *
+ * 字段名:退款金额 + * 变量名:settlement_refund_fee + * 是否必填:是 + * 类型:Int + * 示例值:100 + * 描述:退款金额=申请退款金额-非充值代金券退款金额,退款金额<=申请退款金额 + *+ */ + @XStreamAlias("settlement_refund_fee") + private Integer settlementRefundFee; + + /** + *
+ * 字段名:退款状态 + * 变量名:refund_status + * 是否必填:是 + * 类型:String(16) + * 示例值:SUCCESS + * 描述:SUCCESS-退款成功,CHANGE-退款异常,REFUNDCLOSE—退款关闭 + *+ */ + @XStreamAlias("refund_status") + private String refundStatus; + + /** + *
+ * 字段名:退款成功时间 + * 变量名:success_time + * 是否必填:否 + * 类型: String(20) + * 示例值:20160725152626 + * 描述:- + */ + @XStreamAlias("success_time") + private String successTime; + + /** + *+ * 字段名:退款入账账户 + * 变量名:refund_recv_accout + * 是否必填:是 + * 类型:String(64) + * 示例值:招商银行信用卡0403 + * 描述:取当前退款单的退款入账方,1)退回银行卡:{银行名称}{卡类型}{卡尾号},2)退回支付用户零钱:支付用户零钱 ,3)退还商户: 商户基本账户,商户结算银行账户,4)退回支付用户零钱通: 支付用户零钱通 + *+ */ + @XStreamAlias("refund_recv_accout") + private String refundRecvAccout; + + /** + *+ * 字段名:退款资金来源 + * 变量名:refund_account + * 是否必填:是 + * 类型:String(30) + * 示例值:REFUND_SOURCE_RECHARGE_FUNDS + * 描述:REFUND_SOURCE_RECHARGE_FUNDS 可用余额退款/基本账户,REFUND_SOURCE_UNSETTLED_FUNDS 未结算资金退款 + *+ */ + @XStreamAlias("refund_account") + private String refundAccount; + + /** + *+ * 字段名:退款发起来源 + * 变量名:refund_request_source + * 是否必填:是 + * 类型:String(30) + * 示例值:API + * 描述:API接口,VENDOR_PLATFORM商户平台 + *+ */ + @XStreamAlias("refund_request_source") + private String refundRequestSource; + + public String getTransactionId() { + return transactionId; + } + + public void setTransactionId(String transactionId) { + this.transactionId = transactionId; + } + + public String getOutTradeNo() { + return outTradeNo; + } + + public void setOutTradeNo(String outTradeNo) { + this.outTradeNo = outTradeNo; + } + + public String getRefundId() { + return refundId; + } + + public void setRefundId(String refundId) { + this.refundId = refundId; + } + + public String getOutRefundNo() { + return outRefundNo; + } + + public void setOutRefundNo(String outRefundNo) { + this.outRefundNo = outRefundNo; + } + + public Integer getTotalFee() { + return totalFee; + } + + public void setTotalFee(Integer totalFee) { + this.totalFee = totalFee; + } + + public Integer getSettlementTotalFee() { + return settlementTotalFee; + } + + public void setSettlementTotalFee(Integer settlementTotalFee) { + this.settlementTotalFee = settlementTotalFee; + } + + public Integer getRefundFee() { + return refundFee; + } + + public void setRefundFee(Integer refundFee) { + this.refundFee = refundFee; + } + + public Integer getSettlementRefundFee() { + return settlementRefundFee; + } + + public void setSettlementRefundFee(Integer settlementRefundFee) { + this.settlementRefundFee = settlementRefundFee; + } + + public String getRefundStatus() { + return refundStatus; + } + + public void setRefundStatus(String refundStatus) { + this.refundStatus = refundStatus; + } + + public String getSuccessTime() { + return successTime; + } + + public void setSuccessTime(String successTime) { + this.successTime = successTime; + } + + public String getRefundRecvAccout() { + return refundRecvAccout; + } + + public void setRefundRecvAccout(String refundRecvAccout) { + this.refundRecvAccout = refundRecvAccout; + } + + public String getRefundAccount() { + return refundAccount; + } + + public void setRefundAccount(String refundAccount) { + this.refundAccount = refundAccount; + } + + public String getRefundRequestSource() { + return refundRequestSource; + } + + public void setRefundRequestSource(String refundRequestSource) { + this.refundRequestSource = refundRequestSource; + } + + public static ReqInfo fromXML(String xmlString) { + XStream xstream = XStreamInitializer.getInstance(); + xstream.processAnnotations(ReqInfo.class); + return (ReqInfo) xstream.fromXML(xmlString); + } + } + + public String getReqInfoString() { + return reqInfoString; + } + + public void setReqInfoString(String reqInfoString) { + this.reqInfoString = reqInfoString; + } + + public ReqInfo getReqInfo() { + return reqInfo; + } + + public void setReqInfo(ReqInfo reqInfo) { + this.reqInfo = reqInfo; + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/order/WxPayAppOrderResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/order/WxPayAppOrderResult.java new file mode 100644 index 0000000000..6688d602c9 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/order/WxPayAppOrderResult.java @@ -0,0 +1,145 @@ +package com.github.binarywang.wxpay.bean.order; + +/** + *+ * APP支付调用统一下单接口后的组装所需参数的实现类 + * 参考 https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_12 + * Created by Binary Wang on 2017-9-1. + *+ * + * @author Binary Wang + */ +public class WxPayAppOrderResult { + private String sign; + private String prepayId; + private String partnerId; + private String appId; + private String packageValue; + private String timeStamp; + private String nonceStr; + + public WxPayAppOrderResult() { + } + + private WxPayAppOrderResult(Builder builder) { + setSign(builder.sign); + setPrepayId(builder.prepayId); + setPartnerId(builder.partnerId); + setAppId(builder.appId); + setPackageValue(builder.packageValue); + setTimeStamp(builder.timeStamp); + setNonceStr(builder.nonceStr); + } + + public static Builder newBuilder() { + return new Builder(); + } + + public String getSign() { + return this.sign; + } + + public void setSign(String sign) { + this.sign = sign; + } + + public String getPrepayId() { + return this.prepayId; + } + + public void setPrepayId(String prepayId) { + this.prepayId = prepayId; + } + + public String getPartnerId() { + return this.partnerId; + } + + public void setPartnerId(String partnerId) { + this.partnerId = partnerId; + } + + public String getAppId() { + return this.appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + + public String getPackageValue() { + return this.packageValue; + } + + public void setPackageValue(String packageValue) { + this.packageValue = packageValue; + } + + public String getTimeStamp() { + return this.timeStamp; + } + + public void setTimeStamp(String timeStamp) { + this.timeStamp = timeStamp; + } + + public String getNonceStr() { + return this.nonceStr; + } + + public void setNonceStr(String nonceStr) { + this.nonceStr = nonceStr; + } + + public static final class Builder { + private String sign; + private String prepayId; + private String partnerId; + private String appId; + private String packageValue; + private String timeStamp; + private String nonceStr; + + private Builder() { + } + + public Builder sign(String sign) { + this.sign = sign; + return this; + } + + public Builder prepayId(String prepayId) { + this.prepayId = prepayId; + return this; + } + + public Builder partnerId(String partnerId) { + this.partnerId = partnerId; + return this; + } + + public Builder appId(String appId) { + this.appId = appId; + return this; + } + + public Builder packageValue(String packageValue) { + this.packageValue = packageValue; + return this; + } + + public Builder timeStamp(String timeStamp) { + this.timeStamp = timeStamp; + return this; + } + + public Builder nonceStr(String nonceStr) { + this.nonceStr = nonceStr; + return this; + } + + public WxPayAppOrderResult build() { + return new WxPayAppOrderResult(this); + } + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/order/WxPayMpOrderResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/order/WxPayMpOrderResult.java new file mode 100644 index 0000000000..d1ebdee051 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/order/WxPayMpOrderResult.java @@ -0,0 +1,133 @@ +package com.github.binarywang.wxpay.bean.order; + +/** + *+ * 微信公众号支付进行统一下单后组装所需参数的类 + * 文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6 + * Created by Binary Wang on 2017-9-1. + *+ * + * @author Binary Wang + */ +public class WxPayMpOrderResult { + private String appId; + private String timeStamp; + private String nonceStr; + /** + * 由于package为java保留关键字,因此改为packageValue + */ + private String packageValue; + private String signType; + private String paySign; + + private WxPayMpOrderResult(Builder builder) { + setAppId(builder.appId); + setTimeStamp(builder.timeStamp); + setNonceStr(builder.nonceStr); + setPackageValue(builder.packageValue); + setSignType(builder.signType); + setPaySign(builder.paySign); + } + + public static Builder newBuilder() { + return new Builder(); + } + + public String getAppId() { + return this.appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + + public String getTimeStamp() { + return this.timeStamp; + } + + public void setTimeStamp(String timeStamp) { + this.timeStamp = timeStamp; + } + + public String getNonceStr() { + return this.nonceStr; + } + + public void setNonceStr(String nonceStr) { + this.nonceStr = nonceStr; + } + + public String getPackageValue() { + return this.packageValue; + } + + public void setPackageValue(String packageValue) { + this.packageValue = packageValue; + } + + public String getSignType() { + return this.signType; + } + + public void setSignType(String signType) { + this.signType = signType; + } + + public String getPaySign() { + return this.paySign; + } + + public void setPaySign(String paySign) { + this.paySign = paySign; + } + + public WxPayMpOrderResult() { + } + + + public static final class Builder { + private String appId; + private String timeStamp; + private String nonceStr; + private String packageValue; + private String signType; + private String paySign; + + private Builder() { + } + + public Builder appId(String appId) { + this.appId = appId; + return this; + } + + public Builder timeStamp(String timeStamp) { + this.timeStamp = timeStamp; + return this; + } + + public Builder nonceStr(String nonceStr) { + this.nonceStr = nonceStr; + return this; + } + + public Builder packageValue(String packageValue) { + this.packageValue = packageValue; + return this; + } + + public Builder signType(String signType) { + this.signType = signType; + return this; + } + + public Builder paySign(String paySign) { + this.paySign = paySign; + return this; + } + + public WxPayMpOrderResult build() { + return new WxPayMpOrderResult(this); + } + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/order/WxPayNativeOrderResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/order/WxPayNativeOrderResult.java new file mode 100644 index 0000000000..3eb0e3748a --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/order/WxPayNativeOrderResult.java @@ -0,0 +1,48 @@ +package com.github.binarywang.wxpay.bean.order; + +/** + *+ * 微信扫码支付统一下单后发起支付拼接所需参数实现类 + * Created by Binary Wang on 2017-9-1. + *+ * + * @author Binary Wang + */ +public class WxPayNativeOrderResult { + private String codeUrl; + + private WxPayNativeOrderResult(Builder builder) { + setCodeUrl(builder.codeUrl); + } + + public static Builder newBuilder() { + return new Builder(); + } + + public String getCodeUrl() { + return this.codeUrl; + } + + public void setCodeUrl(String codeUrl) { + this.codeUrl = codeUrl; + } + + public WxPayNativeOrderResult() { + } + + public static final class Builder { + private String codeUrl; + + private Builder() { + } + + public Builder codeUrl(String codeUrl) { + this.codeUrl = codeUrl; + return this; + } + + public WxPayNativeOrderResult build() { + return new WxPayNativeOrderResult(this); + } + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxEntPayRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxEntPayRequest.java index fd43fb1aaa..7897ad02da 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxEntPayRequest.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxEntPayRequest.java @@ -1,18 +1,12 @@ package com.github.binarywang.wxpay.bean.request; import com.thoughtworks.xstream.annotations.XStreamAlias; +import me.chanjar.weixin.common.annotation.Required; import me.chanjar.weixin.common.util.ToStringUtils; /** ** 企业付款请求对象 - * 注释中各行每个字段描述对应如下: - *
- * 公众账号appid - * mch_appid - * 是 - * wx8888888888888888 - * String - * 微信分配的公众账号ID(企业号corpid即为此appId) + * 字段名:公众账号appid + * 变量名:mch_appid + * 是否必填:是 + * 示例值:wx8888888888888888 + * 类型:String + * 描述:微信分配的公众账号ID(企业号corpid即为此appId) **/ @XStreamAlias("mch_appid") @@ -35,12 +29,12 @@ public class WxEntPayRequest extends WxPayBaseRequest { /** *
- * 商户号 - * mchid - * 是 - * 1900000109 - * String(32) - * 微信支付分配的商户号 + * 字段名:商户号 + * 变量名:mchid + * 是否必填:是 + * 示例值:1900000109 + * 类型:String(32) + * 描述:微信支付分配的商户号 **/ @XStreamAlias("mchid") @@ -48,12 +42,12 @@ public class WxEntPayRequest extends WxPayBaseRequest { /** *
- * 设备号 - * device_info - * 否 - * 13467007045764 - * String(32) - * 微信支付分配的终端设备号 + * 字段名:设备号 + * 变量名:device_info + * 是否必填:否 + * 示例值:13467007045764 + * 类型:String(32) + * 描述:微信支付分配的终端设备号 **/ @XStreamAlias("device_info") @@ -61,53 +55,56 @@ public class WxEntPayRequest extends WxPayBaseRequest { /** *
- * 商户订单号 - * partner_trade_no - * 是 - * 10000098201411111234567890 - * String - * 商户订单号 + * 字段名:商户订单号 + * 变量名:partner_trade_no + * 是否必填:是 + * 示例值:10000098201411111234567890 + * 类型:String + * 描述:商户订单号 **/ + @Required @XStreamAlias("partner_trade_no") private String partnerTradeNo; /** *
- * 需保持唯一性 用户openid - * openid - * 是 - * oxTWIuGaIt6gTKsQRLau2M0yL16E - * String - * 商户appid下,某用户的openid + * 字段名:需保持唯一性 用户openid + * 变量名:openid + * 是否必填:是 + * 示例值:oxTWIuGaIt6gTKsQRLau2M0yL16E + * 类型:String + * 描述:商户appid下,某用户的openid **/ + @Required @XStreamAlias("openid") private String openid; /** *
- * 校验用户姓名选项 - * check_name - * 是 - * OPTION_CHECK - * String - * NO_CHECK:不校验真实姓名 + * 字段名:校验用户姓名选项 + * 变量名:check_name + * 是否必填:是 + * 示例值:OPTION_CHECK + * 类型:String + * 描述:NO_CHECK:不校验真实姓名 * FORCE_CHECK:强校验真实姓名(未实名认证的用户会校验失败,无法转账) * OPTION_CHECK:针对已实名认证的用户才校验真实姓名(未实名认证用户不校验,可以转账成功) **/ + @Required @XStreamAlias("check_name") private String checkName; /** *
- * 收款用户姓名 - * re_user_name - * 可选 - * 马花花 - * String - * 收款用户真实姓名。 + * 字段名:收款用户姓名 + * 变量名:re_user_name + * 是否必填:可选 + * 示例值:马花花 + * 类型:String + * 描述:收款用户真实姓名。 * 如果check_name设置为FORCE_CHECK或OPTION_CHECK, 则必填用户真实姓名 **/ @@ -116,43 +113,71 @@ public class WxEntPayRequest extends WxPayBaseRequest { /** *
- * 金额 - * amount - * 是 - * 10099 - * int - * 企业付款金额, 单位为分 + * 字段名:金额 + * 变量名:amount + * 是否必填:是 + * 示例值:10099 + * 类型:int + * 描述:企业付款金额, 单位为分 **/ + @Required @XStreamAlias("amount") private Integer amount; /** *
- * 企业付款描述信息 - * desc - * 是 - * 理赔 - * String - * 企业付款操作说明信息。必填。 + * 字段名:企业付款描述信息 + * 变量名:desc + * 是否必填:是 + * 示例值:理赔 + * 类型:String + * 描述:企业付款操作说明信息。必填。 **/ + @Required @XStreamAlias("desc") private String description; /** *
- * Ip地址 - * spbill_create_ip - * 是 - * 192.168.0.1 - * String(32) - * 调用接口的机器Ip地址 + * 字段名:Ip地址 + * 变量名:spbill_create_ip + * 是否必填:是 + * 示例值:192.168.0.1 + * 类型:String(32) + * 描述:调用接口的机器Ip地址 **/ + @Required @XStreamAlias("spbill_create_ip") private String spbillCreateIp; + public WxEntPayRequest() { + } + + private WxEntPayRequest(Builder builder) { + setAppid(builder.appid); + setMchId(builder.mchId); + setSubAppId(builder.subAppId); + setSubMchId(builder.subMchId); + setNonceStr(builder.nonceStr); + setSign(builder.sign); + mchAppid = builder.mchAppid; + setMchId(builder.mchId); + setDeviceInfo(builder.deviceInfo); + setPartnerTradeNo(builder.partnerTradeNo); + setOpenid(builder.openid); + setCheckName(builder.checkName); + setReUserName(builder.reUserName); + setAmount(builder.amount); + setDescription(builder.description); + setSpbillCreateIp(builder.spbillCreateIp); + } + + public static Builder newBuilder() { + return new Builder(); + } @Override protected void checkConstraints() { @@ -248,4 +273,103 @@ public String toString() { return ToStringUtils.toSimpleString(this); } + public static final class Builder { + private String appid; + private String mchId; + private String deviceInfo; + private String partnerTradeNo; + private String openid; + private String checkName; + private String reUserName; + private Integer amount; + private String description; + private String spbillCreateIp; + private String subAppId; + private String subMchId; + private String nonceStr; + private String sign; + private String mchAppid; + + private Builder() { + } + + public Builder appid(String appid) { + this.appid = appid; + return this; + } + + public Builder mchId(String mchId) { + this.mchId = mchId; + return this; + } + + public Builder deviceInfo(String deviceInfo) { + this.deviceInfo = deviceInfo; + return this; + } + + public Builder partnerTradeNo(String partnerTradeNo) { + this.partnerTradeNo = partnerTradeNo; + return this; + } + + public Builder openid(String openid) { + this.openid = openid; + return this; + } + + public Builder checkName(String checkName) { + this.checkName = checkName; + return this; + } + + public Builder reUserName(String reUserName) { + this.reUserName = reUserName; + return this; + } + + public Builder amount(Integer amount) { + this.amount = amount; + return this; + } + + public Builder description(String description) { + this.description = description; + return this; + } + + public Builder spbillCreateIp(String spbillCreateIp) { + this.spbillCreateIp = spbillCreateIp; + return this; + } + + public WxEntPayRequest build() { + return new WxEntPayRequest(this); + } + + public Builder subAppId(String subAppId) { + this.subAppId = subAppId; + return this; + } + + public Builder subMchId(String subMchId) { + this.subMchId = subMchId; + return this; + } + + public Builder nonceStr(String nonceStr) { + this.nonceStr = nonceStr; + return this; + } + + public Builder sign(String sign) { + this.sign = sign; + return this; + } + + public Builder mchAppid(String mchAppid) { + this.mchAppid = mchAppid; + return this; + } + } } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayBaseRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayBaseRequest.java index b0c2e85d5c..41a98d0ae4 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayBaseRequest.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayBaseRequest.java @@ -95,6 +95,19 @@ public abstract class WxPayBaseRequest { @XStreamAlias("sign") protected String sign; + /** + *
+ * 签名类型 + * sign_type + * 否 + * String(32) + * HMAC-SHA256 + * 签名类型,目前支持HMAC-SHA256和MD5 + *+ */ + @XStreamAlias("sign_type") + private String signType; + /** * 将单位为元转换为单位为分 * @@ -122,7 +135,7 @@ protected void checkFields() throws WxPayException { /** * 检查约束情况 */ - protected abstract void checkConstraints(); + protected abstract void checkConstraints() throws WxPayException; public String getAppid() { return this.appid; @@ -187,6 +200,14 @@ public void setSubMchId(String subMchId) { this.subMchId = subMchId; } + public String getSignType() { + return signType; + } + + public void setSignType(String signType) { + this.signType = signType; + } + @Override public String toString() { return ToStringUtils.toSimpleString(this); @@ -230,9 +251,8 @@ public void checkAndSign(WxPayConfig config) throws WxPayException { if (StringUtils.isBlank(getNonceStr())) { this.setNonceStr(String.valueOf(System.currentTimeMillis())); } - //设置签名字段的值 - this.setSign(SignUtils.createSign(this, config.getMchKey())); + this.setSign(SignUtils.createSign(this, config.getMchKey(), this.signType)); } } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayDownloadBillRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayDownloadBillRequest.java index ed02060f83..33e410cdd8 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayDownloadBillRequest.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayDownloadBillRequest.java @@ -1,5 +1,7 @@ package com.github.binarywang.wxpay.bean.request; +import com.github.binarywang.wxpay.constant.WxPayConstants.BillType; +import com.github.binarywang.wxpay.exception.WxPayException; import com.thoughtworks.xstream.annotations.XStreamAlias; import me.chanjar.weixin.common.annotation.Required; import org.apache.commons.lang3.ArrayUtils; @@ -16,7 +18,8 @@ */ @XStreamAlias("xml") public class WxPayDownloadBillRequest extends WxPayBaseRequest { - private static final String[] BILL_TYPE = new String[]{"ALL", "REFUND", "SUCCESS"}; + private static final String[] BILL_TYPES = new String[]{BillType.ALL, BillType.SUCCESS, BillType.REFUND, BillType.RECHARGE_REFUND}; + private static final String TAR_TYPE_GZIP = "GZIP"; /** *
@@ -128,14 +131,14 @@ public void setTarType(String tarType) { } @Override - protected void checkConstraints() { - if (StringUtils.isNotBlank(this.getTarType()) && !"GZIP".equals(this.getTarType())) { - throw new IllegalArgumentException("tar_type值如果存在,只能为GZIP"); + protected void checkConstraints() throws WxPayException { + if (StringUtils.isNotBlank(this.getTarType()) && !TAR_TYPE_GZIP.equals(this.getTarType())) { + throw new WxPayException("tar_type值如果存在,只能为GZIP"); } - if (!ArrayUtils.contains(BILL_TYPE, this.getBillType())) { - throw new IllegalArgumentException(String.format("bill_tpye目前必须为%s其中之一,实际值:%s", - Arrays.toString(BILL_TYPE), this.getBillType())); + if (!ArrayUtils.contains(BILL_TYPES, this.getBillType())) { + throw new WxPayException(String.format("bill_type目前必须为%s其中之一,实际值:%s", + Arrays.toString(BILL_TYPES), this.getBillType())); } } } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayOrderQueryRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayOrderQueryRequest.java index 499727995e..e7767da607 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayOrderQueryRequest.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayOrderQueryRequest.java @@ -1,5 +1,6 @@ package com.github.binarywang.wxpay.bean.request; +import com.github.binarywang.wxpay.exception.WxPayException; import com.thoughtworks.xstream.annotations.XStreamAlias; import org.apache.commons.lang3.StringUtils; @@ -64,10 +65,10 @@ public void setOutTradeNo(String outTradeNo) { } @Override - protected void checkConstraints() { + protected void checkConstraints() throws WxPayException { if ((StringUtils.isBlank(transactionId) && StringUtils.isBlank(outTradeNo)) || (StringUtils.isNotBlank(transactionId) && StringUtils.isNotBlank(outTradeNo))) { - throw new IllegalArgumentException("transaction_id 和 out_trade_no 不能同时存在或同时为空,必须二选一"); + throw new WxPayException("transaction_id 和 out_trade_no 不能同时存在或同时为空,必须二选一"); } } } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayOrderReverseRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayOrderReverseRequest.java index 6aef2aa0fa..075295238e 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayOrderReverseRequest.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayOrderReverseRequest.java @@ -1,5 +1,6 @@ package com.github.binarywang.wxpay.bean.request; +import com.github.binarywang.wxpay.exception.WxPayException; import com.thoughtworks.xstream.annotations.XStreamAlias; import org.apache.commons.lang3.StringUtils; @@ -91,9 +92,9 @@ public void setSignType(String signType) { } @Override - protected void checkConstraints() { + protected void checkConstraints() throws WxPayException { if (StringUtils.isBlank(transactionId) && StringUtils.isBlank(outTradeNo)) { - throw new IllegalArgumentException("transaction_id 和 out_trade_no不能同时为空!"); + throw new WxPayException("transaction_id 和 out_trade_no不能同时为空!"); } } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayQueryCommentRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayQueryCommentRequest.java new file mode 100644 index 0000000000..1bdbf9bf4e --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayQueryCommentRequest.java @@ -0,0 +1,112 @@ +package com.github.binarywang.wxpay.bean.request; + +import com.github.binarywang.wxpay.exception.WxPayException; +import com.thoughtworks.xstream.annotations.XStreamAlias; +import me.chanjar.weixin.common.annotation.Required; + +/** + *+ * 拉取订单评价数据接口的请求参数封装类 + * Created by BinaryWang on 2017/9/2. + *+ * + * @author Binary Wang + */ +@XStreamAlias("xml") +public class WxPayQueryCommentRequest extends WxPayBaseRequest { + /** + *+ * 字段名:开始时间 + * 变量名:begin_time + * 是否必填:是 + * 类型:String(19) + * 示例值:20170724000000 + * 描述:按用户评论时间批量拉取的起始时间,格式为yyyyMMddHHmmss + *+ */ + @Required + @XStreamAlias("begin_time") + private String beginTime; + + /** + *+ * 字段名:结束时间 + * 变量名:end_time + * 是否必填:是 + * 类型:String(19) + * 示例值:20170725000000 + * 描述:按用户评论时间批量拉取的结束时间,格式为yyyyMMddHHmmss + *+ */ + @Required + @XStreamAlias("end_time") + private String endTime; + + /** + *+ * 字段名:位移 + * 变量名:offset + * 是否必填:是 + * 类型:uint(64) + * 示例值:0 + * 描述:指定从某条记录的下一条开始返回记录。接口调用成功时,会返回本次查询最后一条数据的offset。商户需要翻页时,应该把本次调用返回的offset 作为下次调用的入参。注意offset是评论数据在微信支付后台保存的索引,未必是连续的 + *+ */ + @Required + @XStreamAlias("offset") + private Integer offset; + + /** + *+ * 字段名:条数 + * 变量名:limit + * 是否必填:否 + * 类型:uint(32) + * 示例值:100 + * 描述:一次拉取的条数, 最大值是200,默认是200 + *+ */ + @XStreamAlias("limit") + private Integer limit; + + /** + * 检查约束情况 + */ + @Override + protected void checkConstraints() throws WxPayException { + + } + + public String getBeginTime() { + return beginTime; + } + + public void setBeginTime(String beginTime) { + this.beginTime = beginTime; + } + + public String getEndTime() { + return endTime; + } + + public void setEndTime(String endTime) { + this.endTime = endTime; + } + + public Integer getOffset() { + return offset; + } + + public void setOffset(Integer offset) { + this.offset = offset; + } + + public Integer getLimit() { + return limit; + } + + public void setLimit(Integer limit) { + this.limit = limit; + } + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayRefundQueryRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayRefundQueryRequest.java index 1efa23db7a..00545f004c 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayRefundQueryRequest.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayRefundQueryRequest.java @@ -1,5 +1,6 @@ package com.github.binarywang.wxpay.bean.request; +import com.github.binarywang.wxpay.exception.WxPayException; import com.thoughtworks.xstream.annotations.XStreamAlias; import org.apache.commons.lang3.StringUtils; @@ -135,12 +136,12 @@ public void setRefundId(String refundId) { } @Override - protected void checkConstraints() { + protected void checkConstraints() throws WxPayException { if ((StringUtils.isBlank(transactionId) && StringUtils.isBlank(outTradeNo) && StringUtils.isBlank(outRefundNo) && StringUtils.isBlank(refundId)) || (StringUtils.isNotBlank(transactionId) && StringUtils.isNotBlank(outTradeNo) && StringUtils.isNotBlank(outRefundNo) && StringUtils.isNotBlank(refundId))) { - throw new IllegalArgumentException("transaction_id,out_trade_no,out_refund_no,refund_id 必须四选一"); + throw new WxPayException("transaction_id,out_trade_no,out_refund_no,refund_id 必须四选一"); } } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayRefundRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayRefundRequest.java index 7fae6fa0f5..66808738ca 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayRefundRequest.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayRefundRequest.java @@ -271,16 +271,16 @@ public void checkAndSign(WxPayConfig config) throws WxPayException { } @Override - protected void checkConstraints() { + protected void checkConstraints() throws WxPayException { if (StringUtils.isNotBlank(this.getRefundAccount())) { if (!ArrayUtils.contains(REFUND_ACCOUNT, this.getRefundAccount())) { - throw new IllegalArgumentException(String.format("refund_account目前必须为%s其中之一,实际值:%s", + throw new WxPayException(String.format("refund_account目前必须为%s其中之一,实际值:%s", Arrays.toString(REFUND_ACCOUNT), this.getRefundAccount())); } } if (StringUtils.isBlank(this.getOutTradeNo()) && StringUtils.isBlank(this.getTransactionId())) { - throw new IllegalArgumentException("transaction_id 和 out_trade_no 不能同时为空,必须提供一个"); + throw new WxPayException("transaction_id 和 out_trade_no 不能同时为空,必须提供一个"); } } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayUnifiedOrderRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayUnifiedOrderRequest.java index 7c927425de..8061556cc7 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayUnifiedOrderRequest.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayUnifiedOrderRequest.java @@ -500,18 +500,18 @@ public void setSceneInfo(String sceneInfo) { } @Override - protected void checkConstraints() { + protected void checkConstraints() throws WxPayException { // if (!ArrayUtils.contains(TRADE_TYPES, this.getTradeType())) { -// throw new IllegalArgumentException(String.format("trade_type目前必须为%s其中之一,实际值:%s", +// throw new WxPayException(String.format("trade_type目前必须为%s其中之一,实际值:%s", // Arrays.toString(TRADE_TYPES), this.getTradeType())); // } if ("JSAPI".equals(this.getTradeType()) && this.getOpenid() == null) { - throw new IllegalArgumentException("当 trade_type是'JSAPI'时未指定openid"); + throw new WxPayException("当 trade_type是'JSAPI'时未指定openid"); } if ("NATIVE".equals(this.getTradeType()) && this.getProductId() == null) { - throw new IllegalArgumentException("当 trade_type是'NATIVE'时未指定product_id"); + throw new WxPayException("当 trade_type是'NATIVE'时未指定product_id"); } } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayBaseResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayBaseResult.java index 802e22b312..d4b96dc408 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayBaseResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayBaseResult.java @@ -316,8 +316,8 @@ public void checkResult(WxPayServiceAbstractImpl wxPayService) throws WxPayExcep } //校验结果是否成功 - if (!"SUCCESS".equalsIgnoreCase(getReturnCode()) - || !"SUCCESS".equalsIgnoreCase(getResultCode())) { + if (!StringUtils.equalsAny(StringUtils.trimToEmpty(getReturnCode()).toUpperCase(), "SUCCESS", "") + || !StringUtils.equalsAny(StringUtils.trimToEmpty(getResultCode()).toUpperCase(), "SUCCESS", "")) { StringBuilder errorMsg = new StringBuilder(); if (getReturnCode() != null) { errorMsg.append("返回代码:").append(getReturnCode()); @@ -335,8 +335,7 @@ public void checkResult(WxPayServiceAbstractImpl wxPayService) throws WxPayExcep errorMsg.append(",错误详情:").append(getErrCodeDes()); } - this.getLogger().error("\n结果业务代码异常,返回結果:{},\n{}", - map, errorMsg.toString()); + this.getLogger().error("\n结果业务代码异常,返回結果:{},\n{}", map, errorMsg.toString()); throw WxPayException.from(this); } } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayBillBaseResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayBillBaseResult.java index e469ff4538..de58536445 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayBillBaseResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayBillBaseResult.java @@ -1,14 +1,22 @@ package com.github.binarywang.wxpay.bean.result; +import me.chanjar.weixin.common.util.ToStringUtils; + import java.io.Serializable; +/** + * 交易时间:2017-04-06 01:00:02 公众账号ID: 商户号: 子商户号:0 设备号:WEB 微信订单号: 商户订单号:2017040519091071873216 用户标识: 交易类型:NATIVE + * 交易状态:REFUND 付款银行:CFT 货币种类:CNY 总金额:0.00 企业红包金额:0.00 微信退款单号: 商户退款单号:20170406010000933 退款金额:0.01 企业红包退款金额:0.00 + * 退款类型:ORIGINAL 退款状态:SUCCESS 商品名称: 商户数据包: 手续费:0.00000 费率 :0.60% + */ public class WxPayBillBaseResult implements Serializable { - /* - * 交易时间:2017-04-06 01:00:02 公众账号ID: 商户号: 子商户号:0 设备号:WEB 微信订单号: 商户订单号:2017040519091071873216 用户标识: 交易类型:NATIVE - * 交易状态:REFUND 付款银行:CFT 货币种类:CNY 总金额:0.00 企业红包金额:0.00 微信退款单号: 商户退款单号:20170406010000933 退款金额:0.01 企业红包退款金额:0.00 - * 退款类型:ORIGINAL 退款状态:SUCCESS 商品名称: 商户数据包: 手续费:0.00000 费率 :0.60% - */ - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 2226245109137435453L; + + @Override + public String toString() { + return ToStringUtils.toSimpleString(this); + } + /** * 交易时间 */ @@ -32,7 +40,7 @@ public class WxPayBillBaseResult implements Serializable { /** * 微信订单号 */ - private String transationId; + private String transactionId; /** * 商户订单号 */ @@ -150,12 +158,12 @@ public void setDeviceInfo(String deviceInfo) { this.deviceInfo = deviceInfo; } - public String getTransationId() { - return transationId; + public String getTransactionId() { + return transactionId; } - public void setTransationId(String transationId) { - this.transationId = transationId; + public void setTransactionId(String transactionId) { + this.transactionId = transactionId; } public String getOutTradeNo() { diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayBillResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayBillResult.java index a7fb25bef2..f699a42ba8 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayBillResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayBillResult.java @@ -1,14 +1,21 @@ package com.github.binarywang.wxpay.bean.result; +import me.chanjar.weixin.common.util.ToStringUtils; + import java.io.Serializable; import java.util.List; public class WxPayBillResult implements Serializable { + private static final long serialVersionUID = -7687458652694204070L; + + @Override + public String toString() { + return ToStringUtils.toSimpleString(this); + } + /** * 对账返回对象 */ - private static final long serialVersionUID = 1L; - private ListwxPayBillBaseResultLst; /** * 总交易单数 diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayUnifiedOrderResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayUnifiedOrderResult.java index 92c98bda48..d8ab2ab6df 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayUnifiedOrderResult.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayUnifiedOrderResult.java @@ -5,7 +5,7 @@ /** * * 在发起微信支付前,需要调用统一下单接口,获取"预支付交易会话标识"返回的结果 - * 统一下单(详见http://com.github.binarywang.wechat.pay.bean.pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1) + * 统一下单(详见https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1) ** * @author chanjarster diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/config/WxPayConfig.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/config/WxPayConfig.java index aeab939a06..7d8cd5e1e3 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/config/WxPayConfig.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/config/WxPayConfig.java @@ -39,6 +39,10 @@ public class WxPayConfig { private SSLContext sslContext; private String keyPath; private boolean useSandboxEnv = false; + private String httpProxyHost; + private Integer httpProxyPort; + private String httpProxyUsername; + private String httpProxyPassword; public String getKeyPath() { return keyPath; @@ -159,20 +163,20 @@ public void setUseSandboxEnv(boolean useSandboxEnv) { } public SSLContext initSSLContext() throws WxPayException { - if (StringUtils.isBlank(mchId)) { - throw new IllegalArgumentException("请确保商户号mchId已设置"); + if (StringUtils.isBlank(this.getMchId())) { + throw new WxPayException("请确保商户号mchId已设置"); } - if (StringUtils.isBlank(this.keyPath)) { - throw new IllegalArgumentException("请确保证书文件地址keyPath已配置"); + if (StringUtils.isBlank(this.getKeyPath())) { + throw new WxPayException("请确保证书文件地址keyPath已配置"); } InputStream inputStream; final String prefix = "classpath:"; - String fileHasProblemMsg = "证书文件【" + this.keyPath + "】有问题,请核实!"; - String fileNotFoundMsg = "证书文件【" + this.keyPath + "】不存在,请核实!"; - if (this.keyPath.startsWith(prefix)) { - String path = StringUtils.removeFirst(this.keyPath, prefix); + String fileHasProblemMsg = "证书文件【" + this.getKeyPath() + "】有问题,请核实!"; + String fileNotFoundMsg = "证书文件【" + this.getKeyPath() + "】不存在,请核实!"; + if (this.getKeyPath().startsWith(prefix)) { + String path = StringUtils.removeFirst(this.getKeyPath(), prefix); if (!path.startsWith("/")) { path = "/" + path; } @@ -182,7 +186,7 @@ public SSLContext initSSLContext() throws WxPayException { } } else { try { - File file = new File(this.keyPath); + File file = new File(this.getKeyPath()); if (!file.exists()) { throw new WxPayException(fileNotFoundMsg); } @@ -195,7 +199,7 @@ public SSLContext initSSLContext() throws WxPayException { try { KeyStore keystore = KeyStore.getInstance("PKCS12"); - char[] partnerId2charArray = mchId.toCharArray(); + char[] partnerId2charArray = this.getMchId().toCharArray(); keystore.load(inputStream, partnerId2charArray); this.sslContext = SSLContexts.custom().loadKeyMaterial(keystore, partnerId2charArray).build(); return this.sslContext; @@ -227,4 +231,36 @@ public int getHttpTimeout() { public void setHttpTimeout(int httpTimeout) { this.httpTimeout = httpTimeout; } + + public String getHttpProxyHost() { + return httpProxyHost; + } + + public void setHttpProxyHost(String httpProxyHost) { + this.httpProxyHost = httpProxyHost; + } + + public Integer getHttpProxyPort() { + return httpProxyPort; + } + + public void setHttpProxyPort(Integer httpProxyPort) { + this.httpProxyPort = httpProxyPort; + } + + public String getHttpProxyUsername() { + return httpProxyUsername; + } + + public void setHttpProxyUsername(String httpProxyUsername) { + this.httpProxyUsername = httpProxyUsername; + } + + public String getHttpProxyPassword() { + return httpProxyPassword; + } + + public void setHttpProxyPassword(String httpProxyPassword) { + this.httpProxyPassword = httpProxyPassword; + } } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java new file mode 100644 index 0000000000..47f636d0fc --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/constant/WxPayConstants.java @@ -0,0 +1,111 @@ +package com.github.binarywang.wxpay.constant; + +import java.text.SimpleDateFormat; + +/** + *+ * 微信支付常量类 + * Created by Binary Wang on 2017-8-24. + *+ * + * @author Binary Wang + */ +public class WxPayConstants { + + /** + * 拉取订单评价数据接口的参数中日期格式 + */ + public static final SimpleDateFormat QUERY_COMMENT_DATE_FORMAT = new SimpleDateFormat("yyyyMMddHHmmss"); + + /** + * 校验用户姓名选项,企业付款时使用 + */ + public static class CheckNameOption { + /** + * 不校验真实姓名 + */ + public static final String NO_CHECK = "NO_CHECK"; + + /** + * 强校验真实姓名 + */ + public static final String FORCE_CHECK = "FORCE_CHECK"; + } + + /** + * 订单类型 + */ + public static class BillType { + /** + * 查询红包时使用:通过商户订单号获取红包信息 + */ + public static final String MCHT = "MCHT"; + + //以下为下载对账单时的账单类型 + /** + * 返回当日所有订单信息,默认值 + */ + public static final String ALL = "ALL"; + /** + * 返回当日成功支付的订单 + */ + public static final String SUCCESS = "SUCCESS"; + /** + * 返回当日退款订单 + */ + public static final String REFUND = "REFUND"; + /** + * 返回当日充值退款订单(相比其他对账单多一栏“返还手续费”) + */ + public static final String RECHARGE_REFUND = "RECHARGE_REFUND"; + } + + /** + * 交易类型 + */ + public static class TradeType { + /** + * 原生扫码支付 + */ + public static final String NATIVE = "NATIVE"; + + /** + * App支付 + */ + public static final String APP = "APP"; + + /** + * 公众号支付 + */ + public static final String JSAPI = "JSAPI"; + + /** + * H5支付 + */ + public static final String MWEB = "MWEB"; + + /** + * 刷卡支付,刷卡支付有单独的支付接口,不调用统一下单接口 + */ + public static final String MICROPAY = "MICROPAY"; + } + + /** + * 签名类型 + */ + public static class SignType { + public static final String HMAC_SHA256 = "HMAC-SHA256"; + public static final String MD5 = "MD5"; + } + + + /** + * 限定支付方式 + */ + public static class LimitPay { + /** + * no_credit--指定不能使用信用卡支付 + */ + public static final String NO_CREDIT = "no_credit"; + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/converter/WxPayOrderNotifyResultConverter.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/converter/WxPayOrderNotifyResultConverter.java index 0e375bd62f..fe35ed2129 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/converter/WxPayOrderNotifyResultConverter.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/converter/WxPayOrderNotifyResultConverter.java @@ -1,7 +1,7 @@ package com.github.binarywang.wxpay.converter; -import com.github.binarywang.wxpay.bean.WxPayOrderNotifyCoupon; -import com.github.binarywang.wxpay.bean.result.WxPayOrderNotifyResult; +import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyCoupon; +import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; import com.google.common.base.Function; import com.google.common.collect.Maps; import com.thoughtworks.xstream.annotations.XStreamAlias; diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java index 2eef29b85a..ae058e1478 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java @@ -1,12 +1,16 @@ package com.github.binarywang.wxpay.service; +import com.github.binarywang.wxpay.bean.WxPayApiData; import com.github.binarywang.wxpay.bean.coupon.*; +import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; +import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult; import com.github.binarywang.wxpay.bean.request.*; import com.github.binarywang.wxpay.bean.result.*; import com.github.binarywang.wxpay.config.WxPayConfig; import com.github.binarywang.wxpay.exception.WxPayException; import java.io.File; +import java.util.Date; import java.util.Map; /** @@ -21,7 +25,7 @@ public interface WxPayService { /** *- * 查询订单(详见https://com.github.binarywang.wechat.pay.bean.pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2) + * 查询订单(详见https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2) * 该接口提供所有微信支付订单的查询,商户可以通过查询订单接口主动查询订单状态,完成下一步的业务逻辑。 * 需要调用查询接口的情况: * ◆ 当商户后台、网络、服务器等出现异常,商户系统最终未接收到支付通知; @@ -53,7 +57,7 @@ public interface WxPayService { WxPayOrderCloseResult closeOrder(String outTradeNo) throws WxPayException; /** - * 统一下单(详见http://com.github.binarywang.wechat.pay.bean.pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1) + * 统一下单(详见https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1) * 在发起微信支付前,需要调用统一下单接口,获取"预支付交易会话标识" * 接口地址:https://api.mch.weixin.qq.com/pay/unifiedorder * @@ -63,7 +67,7 @@ public interface WxPayService { /** * 该接口调用“统一下单”接口,并拼装发起支付请求需要的参数 - * 详见http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CN + * 详见https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_5 * * @param request 请求对象,注意一些参数如appid、mchid等不用设置,方法内会自动从配置对象中获取到(前提是对应配置中已经设置) */ @@ -112,11 +116,24 @@ WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, Stri throws WxPayException; /** - * 读取支付结果通知 - * 详见https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7 + * @see WxPayService#parseOrderNotifyResult(String) + * @deprecated use WxPayService#parseOrderNotifyResult(String) instead */ + @Deprecated WxPayOrderNotifyResult getOrderNotifyResult(String xmlData) throws WxPayException; + /** + * 解析支付结果通知 + * 详见https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7 + */ + WxPayOrderNotifyResult parseOrderNotifyResult(String xmlData) throws WxPayException; + + /** + * 解析退款结果通知 + * 详见https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_16&index=9 + */ + WxPayRefundNotifyResult parseRefundNotifyResult(String xmlData) throws WxPayException; + /** * 发送微信红包给个人用户 *@@ -368,4 +385,28 @@ WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, Stri **/ WxPayCouponInfoQueryResult queryCouponInfo(WxPayCouponInfoQueryRequest request) throws WxPayException; + + /** + * 获取微信请求数据,方便接口调用方获取处理 + */ + WxPayApiData getWxApiData(); + + /** + *+ * 拉取订单评价数据 + * 商户可以通过该接口拉取用户在微信支付交易记录中针对你的支付记录进行的评价内容。商户可结合商户系统逻辑对该内容数据进行存储、分析、展示、客服回访以及其他使用。如商户业务对评价内容有依赖,可主动引导用户进入微信支付交易记录进行评价。 + * 注意: + * 1. 该内容所有权为提供内容的微信用户,商户在使用内容的过程中应遵从用户意愿 + * 2. 一次最多拉取200条评价数据,可根据时间区间分批次拉取 + * 3. 接口只能拉取最近三个月以内的评价数据 + * 接口链接:https://api.mch.weixin.qq.com/billcommentsp/batchquerycomment + * 是否需要证书:需要 + * 文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_17&index=10 + *+ * @param beginDate 开始时间 + * @param endDate 结束时间 + * @param offset 位移 + * @param limit 条数 + */ + String queryComment(Date beginDate, Date endDate, Integer offset, Integer limit) throws WxPayException; } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceAbstractImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceAbstractImpl.java index 8eef35043c..ae855d5b5d 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceAbstractImpl.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceAbstractImpl.java @@ -1,10 +1,19 @@ package com.github.binarywang.wxpay.service.impl; import com.github.binarywang.utils.qrcode.QrcodeUtils; +import com.github.binarywang.wxpay.bean.WxPayApiData; import com.github.binarywang.wxpay.bean.coupon.*; +import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; +import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult; +import com.github.binarywang.wxpay.bean.order.WxPayAppOrderResult; +import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult; +import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult; import com.github.binarywang.wxpay.bean.request.*; import com.github.binarywang.wxpay.bean.result.*; import com.github.binarywang.wxpay.config.WxPayConfig; +import com.github.binarywang.wxpay.constant.WxPayConstants.BillType; +import com.github.binarywang.wxpay.constant.WxPayConstants.SignType; +import com.github.binarywang.wxpay.constant.WxPayConstants.TradeType; import com.github.binarywang.wxpay.exception.WxPayException; import com.github.binarywang.wxpay.service.WxPayService; import com.github.binarywang.wxpay.util.SignUtils; @@ -14,21 +23,22 @@ import org.slf4j.LoggerFactory; import java.io.File; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; +import java.util.*; + +import static com.github.binarywang.wxpay.constant.WxPayConstants.QUERY_COMMENT_DATE_FORMAT; /** ** 微信支付接口请求抽象实现类 * Created by Binary Wang on 2017-7-8. *+ * * @author Binary Wang */ public abstract class WxPayServiceAbstractImpl implements WxPayService { private static final String PAY_BASE_URL = "https://api.mch.weixin.qq.com"; protected final Logger log = LoggerFactory.getLogger(this.getClass()); + protected static ThreadLocalwxApiData = new ThreadLocal<>(); protected WxPayConfig config; @@ -91,11 +101,17 @@ public WxPayRefundQueryResult refundQuery(String transactionId, String outTradeN } @Override + @Deprecated public WxPayOrderNotifyResult getOrderNotifyResult(String xmlData) throws WxPayException { + return this.parseOrderNotifyResult(xmlData); + } + + @Override + public WxPayOrderNotifyResult parseOrderNotifyResult(String xmlData) throws WxPayException { try { - log.debug("微信支付回调参数详细:{}", xmlData); + log.debug("微信支付异步通知请求参数:{}", xmlData); WxPayOrderNotifyResult result = WxPayOrderNotifyResult.fromXML(xmlData); - log.debug("微信支付回调结果对象:{}", result); + log.debug("微信支付异步通知请求解析后的对象:{}", result); result.checkResult(this); return result; } catch (WxPayException e) { @@ -107,6 +123,19 @@ public WxPayOrderNotifyResult getOrderNotifyResult(String xmlData) throws WxPayE } } + @Override + public WxPayRefundNotifyResult parseRefundNotifyResult(String xmlData) throws WxPayException { + try { + log.debug("微信支付退款异步通知参数:{}", xmlData); + WxPayRefundNotifyResult result = WxPayRefundNotifyResult.fromXML(xmlData, this.getConfig().getMchKey()); + log.debug("微信支付退款异步通知解析后的对象:{}", result); + return result; + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new WxPayException("发生异常," + e.getMessage(), e); + } + } + @Override public WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request) throws WxPayException { request.checkAndSign(this.getConfig()); @@ -128,7 +157,7 @@ public WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request) throw public WxPayRedpackQueryResult queryRedpack(String mchBillNo) throws WxPayException { WxPayRedpackQueryRequest request = new WxPayRedpackQueryRequest(); request.setMchBillNo(mchBillNo); - request.setBillType("MCHT"); + request.setBillType(BillType.MCHT); request.checkAndSign(this.getConfig()); String url = this.getPayBaseUrl() + "/mmpaymkttransfers/gethbinfo"; @@ -160,7 +189,7 @@ public WxPayOrderQueryResult queryOrder(String transactionId, String outTradeNo) @Override public WxPayOrderCloseResult closeOrder(String outTradeNo) throws WxPayException { if (StringUtils.isBlank(outTradeNo)) { - throw new IllegalArgumentException("out_trade_no不能为空"); + throw new WxPayException("out_trade_no不能为空"); } WxPayOrderCloseRequest request = new WxPayOrderCloseRequest(); @@ -175,6 +204,65 @@ public WxPayOrderCloseResult closeOrder(String outTradeNo) throws WxPayException return result; } + public T createOrder(WxPayUnifiedOrderRequest request) throws WxPayException { + WxPayUnifiedOrderResult unifiedOrderResult = this.unifiedOrder(request); + String prepayId = unifiedOrderResult.getPrepayId(); + if (StringUtils.isBlank(prepayId)) { + throw new RuntimeException(String.format("无法获取prepay id,错误代码: '%s',信息:%s。", + unifiedOrderResult.getErrCode(), unifiedOrderResult.getErrCodeDes())); + } + + String timestamp = String.valueOf(System.currentTimeMillis() / 1000); + String nonceStr = String.valueOf(System.currentTimeMillis()); + Object payResult = null; + switch (request.getTradeType()) { + case TradeType.NATIVE: { + payResult = WxPayNativeOrderResult.newBuilder().codeUrl(unifiedOrderResult.getCodeURL()) + .build(); + break; + } + case TradeType.APP: { + // APP支付绑定的是微信开放平台上的账号,APPID为开放平台上绑定APP后发放的参数 + String appId = this.getConfig().getAppId(); + Map configMap = new HashMap<>(); + // 此map用于参与调起sdk支付的二次签名,格式全小写,timestamp只能是10位,格式固定,切勿修改 + String partnerId = getConfig().getMchId(); + configMap.put("prepayid", prepayId); + configMap.put("partnerid", partnerId); + String packageValue = "Sign=WXPay"; + configMap.put("package", packageValue); + configMap.put("timestamp", timestamp); + configMap.put("noncestr", nonceStr); + configMap.put("appid", appId); + + payResult = WxPayAppOrderResult.newBuilder() + .sign(SignUtils.createSign(configMap, this.getConfig().getMchKey(), null)) + .prepayId(prepayId) + .partnerId(partnerId) + .appId(appId) + .packageValue(packageValue) + .timeStamp(timestamp) + .nonceStr(nonceStr) + .build(); + break; + } + case TradeType.JSAPI: { + payResult = WxPayMpOrderResult.newBuilder() + .appId(unifiedOrderResult.getAppid()) + .timeStamp(timestamp) + .nonceStr(nonceStr) + .packageValue("prepay_id=" + prepayId) + .signType(SignType.MD5) + .build(); + ((WxPayMpOrderResult) payResult) + .setPaySign(SignUtils.createSign(payResult, this.getConfig().getMchKey(), null)); + break; + } + } + + return (T) payResult; + } + @Override public WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request) throws WxPayException { request.checkAndSign(this.getConfig()); @@ -196,37 +284,41 @@ public Map getPayInfo(WxPayUnifiedOrderRequest request) throws W } Map payInfo = new HashMap<>(); - if ("NATIVE".equals(request.getTradeType())) { + String timestamp = String.valueOf(System.currentTimeMillis() / 1000); + String nonceStr = String.valueOf(System.currentTimeMillis()); + if (TradeType.NATIVE.equals(request.getTradeType())) { payInfo.put("codeUrl", unifiedOrderResult.getCodeURL()); - } else if ("APP".equals(request.getTradeType())) { + } else if (TradeType.APP.equals(request.getTradeType())) { // APP支付绑定的是微信开放平台上的账号,APPID为开放平台上绑定APP后发放的参数 String appId = getConfig().getAppId(); Map configMap = new HashMap<>(); // 此map用于参与调起sdk支付的二次签名,格式全小写,timestamp只能是10位,格式固定,切勿修改 - String partnerid = getConfig().getMchId(); + String partnerId = getConfig().getMchId(); configMap.put("prepayid", prepayId); - configMap.put("partnerid", partnerid); - configMap.put("package", "Sign=WXPay"); - configMap.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000)); - configMap.put("noncestr", String.valueOf(System.currentTimeMillis())); + configMap.put("partnerid", partnerId); + String packageValue = "Sign=WXPay"; + configMap.put("package", packageValue); + configMap.put("timestamp", timestamp); + configMap.put("noncestr", nonceStr); configMap.put("appid", appId); // 此map用于客户端与微信服务器交互 - payInfo.put("sign", SignUtils.createSign(configMap, this.getConfig().getMchKey())); + payInfo.put("sign", SignUtils.createSign(configMap, this.getConfig().getMchKey(), null)); payInfo.put("prepayId", prepayId); - payInfo.put("partnerId", partnerid); + payInfo.put("partnerId", partnerId); payInfo.put("appId", appId); - payInfo.put("packageValue", "Sign=WXPay"); - payInfo.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000)); - payInfo.put("nonceStr", String.valueOf(System.currentTimeMillis())); - } else if ("JSAPI".equals(request.getTradeType())) { + payInfo.put("packageValue", packageValue); + payInfo.put("timeStamp", timestamp); + payInfo.put("nonceStr", nonceStr); + } else if (TradeType.JSAPI.equals(request.getTradeType())) { payInfo.put("appId", unifiedOrderResult.getAppid()); // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符 - payInfo.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000)); - payInfo.put("nonceStr", String.valueOf(System.currentTimeMillis())); + payInfo.put("timeStamp", timestamp); + payInfo.put("nonceStr", nonceStr); payInfo.put("package", "prepay_id=" + prepayId); - payInfo.put("signType", "MD5"); - payInfo.put("paySign", SignUtils.createSign(payInfo, this.getConfig().getMchKey())); + payInfo.put("signType", SignType.MD5); + payInfo.put("paySign", SignUtils.createSign(payInfo, this.getConfig().getMchKey(), null)); } + return payInfo; } @@ -271,10 +363,9 @@ public String createScanPayQrcodeMode1(String productId) { params.put("time_stamp", String.valueOf(System.currentTimeMillis() / 1000));//这里需要秒,10位数字 params.put("nonce_str", String.valueOf(System.currentTimeMillis())); - String sign = SignUtils.createSign(params, this.getConfig().getMchKey()); + String sign = SignUtils.createSign(params, this.getConfig().getMchKey(), null); params.put("sign", sign); - for (String key : params.keySet()) { codeUrl.append(key + "=" + params.get(key) + "&"); } @@ -319,16 +410,13 @@ public WxPayBillResult downloadBill(String billDate, String billType, String tar String url = this.getPayBaseUrl() + "/pay/downloadbill"; String responseContent = this.post(url, request.toXML(), false); if (responseContent.startsWith("<")) { - WxPayCommonResult result = WxPayBaseResult.fromXML(responseContent, WxPayCommonResult.class); - result.checkResult(this); - return null; + throw WxPayException.from(WxPayBaseResult.fromXML(responseContent, WxPayCommonResult.class)); } else { - WxPayBillResult wxPayBillResult = billInformationDeal(responseContent); - return wxPayBillResult; + return this.handleBillInformation(responseContent); } } - private WxPayBillResult billInformationDeal(String responseContent) { + private WxPayBillResult handleBillInformation(String responseContent) { WxPayBillResult wxPayBillResult = new WxPayBillResult(); String listStr = ""; @@ -342,10 +430,8 @@ private WxPayBillResult billInformationDeal(String responseContent) { * 交易时间:2017-04-06 01:00:02 公众账号ID: 商户号: 子商户号:0 设备号:WEB 微信订单号: 商户订单号:2017040519091071873216 用户标识: 交易类型:NATIVE * 交易状态:REFUND 付款银行:CFT 货币种类:CNY 总金额:0.00 企业红包金额:0.00 微信退款单号: 商户退款单号:20170406010000933 退款金额:0.01 企业红包退款金额:0.00 * 退款类型:ORIGINAL 退款状态:SUCCESS 商品名称: 商户数据包: 手续费:0.00000 费率 :0.60% + * 参考以上格式进行取值 */ - - // 参考以上格式进行取值 - List wxPayBillBaseResultLst = new LinkedList<>(); String newStr = listStr.replaceAll(",", " "); // 去空格 String[] tempStr = newStr.split("`"); // 数据分组 @@ -355,39 +441,39 @@ private WxPayBillResult billInformationDeal(String responseContent) { for (int i = 0; i < j; i++) { WxPayBillBaseResult wxPayBillBaseResult = new WxPayBillBaseResult(); - wxPayBillBaseResult.setTradeTime(tempStr[k]); - wxPayBillBaseResult.setAppId(tempStr[k + 1]); - wxPayBillBaseResult.setMchId(tempStr[k + 2]); - wxPayBillBaseResult.setSubMchId(tempStr[k + 3]); - wxPayBillBaseResult.setDeviceInfo(tempStr[k + 4]); - wxPayBillBaseResult.setTransationId(tempStr[k + 5]); - wxPayBillBaseResult.setOutTradeNo(tempStr[k + 6]); - wxPayBillBaseResult.setOpenId(tempStr[k + 7]); - wxPayBillBaseResult.setTradeType(tempStr[k + 8]); - wxPayBillBaseResult.setTradeState(tempStr[k + 9]); - wxPayBillBaseResult.setBankType(tempStr[k + 10]); - wxPayBillBaseResult.setFeeType(tempStr[k + 11]); - wxPayBillBaseResult.setTotalFee(tempStr[k + 12]); - wxPayBillBaseResult.setCouponFee(tempStr[k + 13]); - wxPayBillBaseResult.setRefundId(tempStr[k + 14]); - wxPayBillBaseResult.setOutRefundNo(tempStr[k + 15]); - wxPayBillBaseResult.setSettlementRefundFee(tempStr[k + 16]); - wxPayBillBaseResult.setCouponRefundFee(tempStr[k + 17]); - wxPayBillBaseResult.setRefundChannel(tempStr[k + 18]); - wxPayBillBaseResult.setRefundState(tempStr[k + 19]); - wxPayBillBaseResult.setBody(tempStr[k + 20]); - wxPayBillBaseResult.setAttach(tempStr[k + 21]); - wxPayBillBaseResult.setPoundage(tempStr[k + 22]); - wxPayBillBaseResult.setPoundageRate(tempStr[k + 23]); + wxPayBillBaseResult.setTradeTime(tempStr[k].trim()); + wxPayBillBaseResult.setAppId(tempStr[k + 1].trim()); + wxPayBillBaseResult.setMchId(tempStr[k + 2].trim()); + wxPayBillBaseResult.setSubMchId(tempStr[k + 3].trim()); + wxPayBillBaseResult.setDeviceInfo(tempStr[k + 4].trim()); + wxPayBillBaseResult.setTransactionId(tempStr[k + 5].trim()); + wxPayBillBaseResult.setOutTradeNo(tempStr[k + 6].trim()); + wxPayBillBaseResult.setOpenId(tempStr[k + 7].trim()); + wxPayBillBaseResult.setTradeType(tempStr[k + 8].trim()); + wxPayBillBaseResult.setTradeState(tempStr[k + 9].trim()); + wxPayBillBaseResult.setBankType(tempStr[k + 10].trim()); + wxPayBillBaseResult.setFeeType(tempStr[k + 11].trim()); + wxPayBillBaseResult.setTotalFee(tempStr[k + 12].trim()); + wxPayBillBaseResult.setCouponFee(tempStr[k + 13].trim()); + wxPayBillBaseResult.setRefundId(tempStr[k + 14].trim()); + wxPayBillBaseResult.setOutRefundNo(tempStr[k + 15].trim()); + wxPayBillBaseResult.setSettlementRefundFee(tempStr[k + 16].trim()); + wxPayBillBaseResult.setCouponRefundFee(tempStr[k + 17].trim()); + wxPayBillBaseResult.setRefundChannel(tempStr[k + 18].trim()); + wxPayBillBaseResult.setRefundState(tempStr[k + 19].trim()); + wxPayBillBaseResult.setBody(tempStr[k + 20].trim()); + wxPayBillBaseResult.setAttach(tempStr[k + 21].trim()); + wxPayBillBaseResult.setPoundage(tempStr[k + 22].trim()); + wxPayBillBaseResult.setPoundageRate(tempStr[k + 23].trim()); wxPayBillBaseResultLst.add(wxPayBillBaseResult); k += t.length; } + wxPayBillResult.setWxPayBillBaseResultLst(wxPayBillBaseResultLst); + /* * 总交易单数,总交易额,总退款金额,总代金券或立减优惠退款金额,手续费总金额 `2,`0.02,`0.0,`0.0,`0 + * 参考以上格式进行取值 */ - - // 参考以上格式进行取值 - String totalStr = objStr.replaceAll(",", " "); String[] totalTempStr = totalStr.split("`"); wxPayBillResult.setTotalRecord(totalTempStr[1]); @@ -497,4 +583,36 @@ public WxPayCouponInfoQueryResult queryCouponInfo(WxPayCouponInfoQueryRequest re result.checkResult(this); return result; } + + @Override + public WxPayApiData getWxApiData() { + try { + return wxApiData.get(); + } finally { + //一般来说,接口请求会在一个线程内进行,这种情况下,每个线程get的会是之前所存入的数据, + // 但以防万一有同一线程多次请求的问题,所以每次获取完数据后移除对应数据 + wxApiData.remove(); + } + } + + @Override + public String queryComment(Date beginDate, Date endDate, Integer offset, Integer limit) throws WxPayException { + WxPayQueryCommentRequest request = new WxPayQueryCommentRequest(); + request.setBeginTime(QUERY_COMMENT_DATE_FORMAT.format(beginDate)); + request.setEndTime(QUERY_COMMENT_DATE_FORMAT.format(endDate)); + request.setOffset(offset); + request.setLimit(limit); + request.setSignType(SignType.HMAC_SHA256); + + request.checkAndSign(this.getConfig()); + + String url = this.getPayBaseUrl() + "/billcommentsp/batchquerycomment"; + + String responseContent = this.post(url, request.toXML(), true); + if (responseContent.startsWith("<")) { + throw WxPayException.from(WxPayBaseResult.fromXML(responseContent, WxPayCommonResult.class)); + } + + return responseContent; + } } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceApacheHttpImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceApacheHttpImpl.java index c5da982c13..1b3284f95f 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceApacheHttpImpl.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceApacheHttpImpl.java @@ -1,12 +1,18 @@ package com.github.binarywang.wxpay.service.impl; +import com.github.binarywang.wxpay.bean.WxPayApiData; import com.github.binarywang.wxpay.exception.WxPayException; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.CredentialsProvider; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.ssl.DefaultHostnameVerifier; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; @@ -41,24 +47,37 @@ protected String post(String url, String requestStr, boolean useKey) throws WxPa } HttpPost httpPost = new HttpPost(url); + httpPost.setConfig(RequestConfig.custom() .setConnectionRequestTimeout(this.getConfig().getHttpConnectionTimeout()) .setConnectTimeout(this.getConfig().getHttpConnectionTimeout()) .setSocketTimeout(this.getConfig().getHttpTimeout()) .build()); + if (StringUtils.isNotBlank(this.getConfig().getHttpProxyHost()) + && this.getConfig().getHttpProxyPort() > 0) { + // 使用代理服务器 需要用户认证的代理服务器 + CredentialsProvider provider = new BasicCredentialsProvider(); + provider.setCredentials( + new AuthScope(this.getConfig().getHttpProxyHost(), this.getConfig().getHttpProxyPort()), + new UsernamePasswordCredentials(this.getConfig().getHttpProxyUsername(), this.getConfig().getHttpProxyPassword())); + httpClientBuilder.setDefaultCredentialsProvider(provider); + } + try (CloseableHttpClient httpclient = httpClientBuilder.build()) { httpPost.setEntity(new StringEntity(new String(requestStr.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1))); try (CloseableHttpResponse response = httpclient.execute(httpPost)) { - String result = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); - this.log.info("\n【请求地址】:{}\n【请求数据】:{}\n【响应数据】:{}", url, requestStr, result); - return result; + String responseString = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); + this.log.info("\n【请求地址】:{}\n【请求数据】:{}\n【响应数据】:{}", url, requestStr, responseString); + wxApiData.set(new WxPayApiData(url, requestStr, responseString, null)); + return responseString; } } finally { httpPost.releaseConnection(); } } catch (Exception e) { this.log.error("\n【请求地址】:{}\n【请求数据】:{}\n【异常信息】:{}", url, requestStr, e.getMessage()); + wxApiData.set(new WxPayApiData(url, requestStr, null, e.getMessage())); throw new WxPayException(e.getMessage(), e); } } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceJoddHttpImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceJoddHttpImpl.java index 29008e26bd..bbe024a309 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceJoddHttpImpl.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/WxPayServiceJoddHttpImpl.java @@ -1,9 +1,14 @@ package com.github.binarywang.wxpay.service.impl; +import com.github.binarywang.wxpay.bean.WxPayApiData; import com.github.binarywang.wxpay.exception.WxPayException; +import jodd.http.HttpConnectionProvider; import jodd.http.HttpRequest; import jodd.http.HttpResponse; +import jodd.http.ProxyInfo; +import jodd.http.ProxyInfo.ProxyType; import jodd.http.net.SSLSocketHttpConnectionProvider; +import jodd.http.net.SocketHttpConnectionProvider; import org.apache.commons.lang3.StringUtils; import javax.net.ssl.SSLContext; @@ -22,8 +27,8 @@ protected String post(String url, String requestStr, boolean useKey) throws WxPa try { HttpRequest request = HttpRequest .post(url) - .timeout(this.config.getHttpTimeout()) - .connectionTimeout(this.config.getHttpConnectionTimeout()) + .timeout(this.getConfig().getHttpTimeout()) + .connectionTimeout(this.getConfig().getHttpConnectionTimeout()) .bodyText(requestStr); if (useKey) { @@ -31,15 +36,29 @@ protected String post(String url, String requestStr, boolean useKey) throws WxPa if (null == sslContext) { sslContext = this.getConfig().initSSLContext(); } - request.withConnectionProvider(new SSLSocketHttpConnectionProvider(sslContext)); + final SSLSocketHttpConnectionProvider provider = new SSLSocketHttpConnectionProvider(sslContext); + request.withConnectionProvider(provider); + } + + if (StringUtils.isNotBlank(this.getConfig().getHttpProxyHost()) && this.getConfig().getHttpProxyPort() > 0) { + ProxyInfo httpProxy = new ProxyInfo(ProxyType.HTTP, this.getConfig().getHttpProxyHost(), this.getConfig().getHttpProxyPort(), + this.getConfig().getHttpProxyUsername(), this.getConfig().getHttpProxyPassword()); + HttpConnectionProvider provider = request.connectionProvider(); + if (null == provider) { + provider = new SocketHttpConnectionProvider(); + } + provider.useProxy(httpProxy); + request.withConnectionProvider(provider); } String responseString = this.getResponseString(request.send()); this.log.info("\n【请求地址】:{}\n【请求数据】:{}\n【响应数据】:{}", url, requestStr, responseString); + wxApiData.set(new WxPayApiData(url, requestStr, responseString, null)); return responseString; } catch (Exception e) { this.log.error("\n【请求地址】:{}\n【请求数据】:{}\n【异常信息】:{}", url, requestStr, e.getMessage()); + wxApiData.set(new WxPayApiData(url, requestStr, null, e.getMessage())); throw new WxPayException(e.getMessage(), e); } } diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/SignUtils.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/SignUtils.java index 33e18c49f3..b13175a724 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/SignUtils.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/util/SignUtils.java @@ -1,9 +1,15 @@ package com.github.binarywang.wxpay.util; +import com.github.binarywang.wxpay.constant.WxPayConstants.SignType; import me.chanjar.weixin.common.util.BeanUtils; +import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.lang3.StringUtils; +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; @@ -20,22 +26,24 @@ public class SignUtils { /** * 微信公众号支付签名算法(详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=4_3) * - * @param xmlBean Bean需要标记有XML注解 - * @param signKey 签名Key + * @param xmlBean Bean需要标记有XML注解 + * @param signKey 签名Key + * @param signType 签名类型,如果为空,则默认为MD5 * @return 签名字符串 */ - public static String createSign(Object xmlBean, String signKey) { - return createSign(BeanUtils.xmlBean2Map(xmlBean), signKey); + public static String createSign(Object xmlBean, String signKey, String signType) { + return createSign(BeanUtils.xmlBean2Map(xmlBean), signKey, signType); } /** * 微信公众号支付签名算法(详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=4_3) * - * @param params 参数信息 - * @param signKey 签名Key + * @param params 参数信息 + * @param signKey 签名Key + * @param signType 签名类型,如果为空,则默认为md5 * @return 签名字符串 */ - public static String createSign(Map params, String signKey) { + public static String createSign(Map params, String signKey, String signType) { // if (this.getConfig().useSandbox()) { // //使用仿真测试环境 // //TODO 目前测试发现,以下两行代码都会出问题,所以暂不建议使用仿真测试环境 @@ -48,13 +56,32 @@ public static String createSign(Map params, String signKey) { StringBuilder toSign = new StringBuilder(); for (String key : sortedMap.keySet()) { String value = params.get(key); - if (StringUtils.isNotEmpty(value) && !"sign".equals(key) && !"key".equals(key)) { + if (StringUtils.isNotEmpty(value) + && !StringUtils.equalsAny(key, "sign", "key", "sign_type")) { toSign.append(key).append("=").append(value).append("&"); } } toSign.append("key=").append(signKey); - return DigestUtils.md5Hex(toSign.toString()).toUpperCase(); + if (SignType.HMAC_SHA256.equals(signType)) { + return createHMACSha256Sign(toSign.toString(), signKey); + } else { + return DigestUtils.md5Hex(toSign.toString()).toUpperCase(); + } + } + + private static String createHMACSha256Sign(String message, String key) { + try { + Mac hmacSHA256 = Mac.getInstance("HmacSHA256"); + SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "HmacSHA256"); + hmacSHA256.init(secretKeySpec); + byte[] bytes = hmacSHA256.doFinal(message.getBytes()); + return Hex.encodeHexString(bytes).toUpperCase(); + } catch (NoSuchAlgorithmException | InvalidKeyException e) { + e.printStackTrace(); + } + + return null; } /** @@ -78,7 +105,7 @@ public static boolean checkSign(Object xmlBean, String signKey) { * @see #checkSign(Map, String) */ public static boolean checkSign(Map params, String signKey) { - String sign = createSign(params, signKey); + String sign = createSign(params, signKey, null); return sign.equals(params.get("sign")); } } diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/WxPayOrderNotifyResultTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/notify/WxPayOrderNotifyResultTest.java similarity index 95% rename from weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/WxPayOrderNotifyResultTest.java rename to weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/notify/WxPayOrderNotifyResultTest.java index 389b374d9e..384de4c983 100644 --- a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/result/WxPayOrderNotifyResultTest.java +++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/notify/WxPayOrderNotifyResultTest.java @@ -1,5 +1,6 @@ -package com.github.binarywang.wxpay.bean.result; +package com.github.binarywang.wxpay.bean.notify; +import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; import org.testng.*; import org.testng.annotations.*; diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/notify/WxPayRefundNotifyResultTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/notify/WxPayRefundNotifyResultTest.java new file mode 100644 index 0000000000..cd1777f836 --- /dev/null +++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/bean/notify/WxPayRefundNotifyResultTest.java @@ -0,0 +1,70 @@ +package com.github.binarywang.wxpay.bean.notify; + +import com.github.binarywang.wxpay.config.WxPayConfig; +import com.github.binarywang.wxpay.exception.WxPayException; +import com.github.binarywang.wxpay.testbase.ApiTestModule; +import org.apache.commons.codec.binary.Base64; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import javax.inject.Inject; +import java.math.BigInteger; +import java.security.MessageDigest; + +import static org.testng.Assert.assertNotNull; + +/** + * + * Created by BinaryWang on 2017/8/27. + *+ * + * @author Binary Wang + */ +@Test +@Guice(modules = ApiTestModule.class) +public class WxPayRefundNotifyResultTest { + @Inject + private WxPayConfig wxPayConfig; + + public void testFromXML() throws WxPayException { + String xmlString = "" + + " "; + + WxPayRefundNotifyResult refundNotifyResult = WxPayRefundNotifyResult.fromXML(xmlString, this.wxPayConfig.getMchKey()); + + assertNotNull(refundNotifyResult); + System.out.println(refundNotifyResult); + } + + public void encodeReqInfo() throws Exception { + String xml = "SUCCESS " + + "" + + " " + + " " + + " \n" + + " "; + + Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); + final MessageDigest md5 = MessageDigest.getInstance("MD5"); + md5.update(this.wxPayConfig.getMchKey().getBytes()); + final String keyMd5String = new BigInteger(1, md5.digest()).toString(16).toLowerCase(); + SecretKeySpec key = new SecretKeySpec(keyMd5String.getBytes(), "AES"); + cipher.init(Cipher.ENCRYPT_MODE, key); + System.out.println(Base64.encodeBase64String(cipher.doFinal(xml.getBytes()))); + } +} diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/WxPayServiceAbstractImplTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/WxPayServiceAbstractImplTest.java index bbf444d901..afea13d8fd 100644 --- a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/WxPayServiceAbstractImplTest.java +++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/WxPayServiceAbstractImplTest.java @@ -4,6 +4,10 @@ import com.github.binarywang.wxpay.bean.coupon.*; import com.github.binarywang.wxpay.bean.request.*; import com.github.binarywang.wxpay.bean.result.*; +import com.github.binarywang.wxpay.constant.WxPayConstants; +import com.github.binarywang.wxpay.constant.WxPayConstants.BillType; +import com.github.binarywang.wxpay.constant.WxPayConstants.SignType; +import com.github.binarywang.wxpay.constant.WxPayConstants.TradeType; import com.github.binarywang.wxpay.exception.WxPayException; import com.github.binarywang.wxpay.service.WxPayService; import com.github.binarywang.wxpay.testbase.ApiTestModule; @@ -15,6 +19,8 @@ import java.nio.file.Files; import java.nio.file.Path; +import java.util.Calendar; +import java.util.Date; import java.util.Map; import static org.testng.Assert.*; @@ -33,25 +39,74 @@ public class WxPayServiceAbstractImplTest { @Inject private WxPayService payService; + /** + * Test method for {@link WxPayService#unifiedOrder(WxPayUnifiedOrderRequest)}. + */ + @Test + public void testUnifiedOrder() throws WxPayException { + WxPayUnifiedOrderResult result = this.payService + .unifiedOrder(WxPayUnifiedOrderRequest.newBuilder() + .body("我去") + .totalFee(1) + .spbillCreateIp("11.1.11.1") + .notifyURL("111111") + .tradeType(TradeType.JSAPI) + .openid(((XmlWxPayConfig) this.payService.getConfig()).getOpenid()) + .outTradeNo("1111112") + .build()); + this.logger.info(result.toString()); + this.logger.warn(this.payService.getWxApiData().toString()); + } + @Test public void testGetPayInfo() throws Exception { Map\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " payInfo = this.payService.getPayInfo(WxPayUnifiedOrderRequest.newBuilder() .body("我去") .totalFee(1) - .spbillCreateIp("111111") + .spbillCreateIp("1.11.1.11") .notifyURL("111111") - .tradeType("JSAPI") - .outTradeNo("111111") + .tradeType(TradeType.JSAPI) + .outTradeNo("1111113") .openid(((XmlWxPayConfig) this.payService.getConfig()).getOpenid()) .build()); this.logger.info(payInfo.toString()); } + /** + * Test method for {@link WxPayService#queryOrder(String, String)} . + */ @Test - public void testDownloadBill() throws Exception { - WxPayBillResult wxPayBillResult = this.payService.downloadBill("20170101", "ALL", "GZIP", "1111111"); - //前一天没有账单记录返回null - assertNotNull(wxPayBillResult); + public void testQueryOrder() throws WxPayException { + this.logger.info(this.payService.queryOrder("11212121", null).toString()); + this.logger.info(this.payService.queryOrder(null, "11111").toString()); + } + + /** + * Test method for {@link WxPayService#closeOrder(String)} . + */ + @Test + public void testCloseOrder() throws WxPayException { + this.logger.info(this.payService.closeOrder("11212121").toString()); + } + + @DataProvider + public Object[][] billingData() { + return new Object[][]{ +// {"20170831", BillType.ALL, null, "deviceInfo"}, + {"20170831", BillType.SUCCESS, null, "deviceInfo"} + }; + } + + @Test(dataProvider = "billingData") + public void testDownloadBill(String billDate, String billType, + String tarType, String deviceInfo) throws Exception { + WxPayBillResult billResult = this.payService.downloadBill(billDate, billType, tarType, deviceInfo); + assertNotNull(billResult); + this.logger.info(billResult.toString()); + } + + @Test + public void testDownloadBill_withNoParams() throws Exception { //必填字段为空时,抛出异常 this.payService.downloadBill("", "", "", null); } @@ -60,7 +115,7 @@ public void testDownloadBill() throws Exception { public void testReport() throws Exception { WxPayReportRequest request = new WxPayReportRequest(); request.setInterfaceUrl("hahahah"); - request.setSignType("HMAC-SHA256");//貌似接口未校验此字段 + request.setSignType(SignType.HMAC_SHA256);//貌似接口未校验此字段 request.setExecuteTime(1000); request.setReturnCode("aaa"); request.setResultCode("aaa"); @@ -107,6 +162,11 @@ public void testRefundQuery() throws Exception { this.logger.info(result.toString()); } + @Test + public void testParseRefundNotifyResult() throws Exception { + // 请参考com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResultTest里的单元测试 + } + /** * Test method for {@link WxPayService#sendRedpack(WxPaySendRedpackRequest)} . */ @@ -130,47 +190,20 @@ public void testQueryRedpack() throws Exception { this.logger.info(redpackResult.toString()); } - /** - * Test method for {@link WxPayService#unifiedOrder(WxPayUnifiedOrderRequest)}. - */ - @Test - public void testUnifiedOrder() throws WxPayException { - WxPayUnifiedOrderResult result = this.payService - .unifiedOrder(WxPayUnifiedOrderRequest.newBuilder() - .body("我去") - .totalFee(1) - .spbillCreateIp("111111") - .notifyURL("111111") - .tradeType("JSAPI") - .openid(((XmlWxPayConfig) this.payService.getConfig()).getOpenid()) - .outTradeNo("111111") - .build()); - this.logger.info(result.toString()); - } - - /** - * Test method for {@link WxPayService#queryOrder(String, String)} . - */ - @Test - public void testQueryOrder() throws WxPayException { - this.logger.info(this.payService.queryOrder("11212121", null).toString()); - this.logger.info(this.payService.queryOrder(null, "11111").toString()); - } - - /** - * Test method for {@link WxPayService#closeOrder(String)} . - */ - @Test - public void testCloseOrder() throws WxPayException { - this.logger.info(this.payService.closeOrder("11212121").toString()); - } - /** * Test method for {@link WxPayService#entPay(WxEntPayRequest)}. */ @Test public void testEntPay() throws WxPayException { - WxEntPayRequest request = new WxEntPayRequest(); + WxEntPayRequest request = WxEntPayRequest.newBuilder() + .partnerTradeNo("Eb6Aep7uVTdbkJqrP4") + .openid("ojOQA0y9o-Eb6Aep7uVTdbkJqrP4") + .amount(1) + .spbillCreateIp("10.10.10.10") + .checkName(WxPayConstants.CheckNameOption.NO_CHECK) + .description("描述信息") + .build(); + this.logger.info(this.payService.entPay(request).toString()); } @@ -294,10 +327,24 @@ public void testQueryCouponStock() throws Exception { @Test public void testQueryCouponInfo() throws Exception { WxPayCouponInfoQueryResult result = this.payService.queryCouponInfo(WxPayCouponInfoQueryRequest.newBuilder() - .openid("onqOjjrXT-776SpHnfexGm1_P7iE") + .openid("ojOQA0y9o-Eb6Aep7uVTdbkJqrP4") .couponId("11") .stockId("1121") .build()); this.logger.info(result.toString()); } + + /** + * 目前调用接口总报“系统繁忙,清稍后再试”,怀疑根本没法使用 + */ + @Test + public void testQueryComment() throws Exception { + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.DAY_OF_MONTH, -2); + Date beginDate = calendar.getTime(); + calendar.add(Calendar.MONTH, -1); + Date endDate = calendar.getTime(); + this.payService.queryComment(beginDate, endDate, 0, null); + } + } diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/testbase/ApiTestModule.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/testbase/ApiTestModule.java index d5a028d1fb..207dc194f5 100644 --- a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/testbase/ApiTestModule.java +++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/testbase/ApiTestModule.java @@ -12,11 +12,16 @@ import java.io.InputStream; public class ApiTestModule implements Module { + private static final String TEST_CONFIG_XML = "test-config.xml"; @Override public void configure(Binder binder) { - try (InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml")) { - XmlWxPayConfig config = this.fromXml(XmlWxPayConfig.class, is1); + try (InputStream inputStream = ClassLoader.getSystemResourceAsStream(TEST_CONFIG_XML)) { + if (inputStream == null) { + throw new RuntimeException("测试配置文件【" + TEST_CONFIG_XML + "】未找到"); + } + + XmlWxPayConfig config = this.fromXml(XmlWxPayConfig.class, inputStream); WxPayService wxService = new WxPayServiceImpl(); wxService.setConfig(config); diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/util/SignUtilsTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/util/SignUtilsTest.java new file mode 100644 index 0000000000..23d7088b7b --- /dev/null +++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/util/SignUtilsTest.java @@ -0,0 +1,40 @@ +package com.github.binarywang.wxpay.util; + +import com.google.common.base.Splitter; +import org.testng.annotations.Test; + +import static com.github.binarywang.wxpay.constant.WxPayConstants.SignType.HMAC_SHA256; +import static org.testng.Assert.assertEquals; + +/** + * + * 测试中使用的测试数据参考的是官方文档,地址: + * https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3 + * Created by BinaryWang on 2017/9/2. + *+ * + * @author Binary Wang + */ +public class SignUtilsTest { + @Test + public void testCreateSign() throws Exception { + String signKey = "192006250b4c09247ec02edce69f6a2d"; + String message = "appid=wxd930ea5d5a258f4f&body=test&device_info=1000&mch_id=10000100&nonce_str=ibuaiVcKdpRxkhJA"; + assertEquals(SignUtils.createSign((Splitter.on("&").withKeyValueSeparator("=").split(message)), signKey, null), + "9A0A8659F005D6984697E2CA0A9CF3B7"); + } + + @Test + public void testCreateSign_HMACSHA256() throws Exception { + String signKey = "192006250b4c09247ec02edce69f6a2d"; + final String message = "appid=wxd930ea5d5a258f4f&body=test&device_info=1000&mch_id=10000100&nonce_str=ibuaiVcKdpRxkhJA"; + String sign = SignUtils.createSign(Splitter.on("&").withKeyValueSeparator("=").split(message), + signKey, HMAC_SHA256); + assertEquals(sign, "6A9AE1657590FD6257D693A078E1C3E4BB6BA4DC30B23E0EE2496E54170DACD6"); + } + + @Test + public void testCheckSign() throws Exception { + } + +}