Skip to content

Commit fa7360d

Browse files
committed
实现微信支付交易保障的接口 binarywang#56
1 parent 0e8df66 commit fa7360d

File tree

5 files changed

+314
-11
lines changed

5 files changed

+314
-11
lines changed

weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
package me.chanjar.weixin.mp.api;
22

33
import me.chanjar.weixin.common.exception.WxErrorException;
4-
import me.chanjar.weixin.mp.bean.pay.request.WxEntPayRequest;
5-
import me.chanjar.weixin.mp.bean.pay.request.WxPayRefundRequest;
6-
import me.chanjar.weixin.mp.bean.pay.request.WxPaySendRedpackRequest;
7-
import me.chanjar.weixin.mp.bean.pay.request.WxPayUnifiedOrderRequest;
4+
import me.chanjar.weixin.mp.bean.pay.request.*;
85
import me.chanjar.weixin.mp.bean.pay.result.*;
96

107
import java.io.File;
@@ -182,7 +179,6 @@ public interface WxMpPayService {
182179
*/
183180
boolean checkSign(Map<String, String> params, String signKey);
184181

185-
186182
/**
187183
* 发送微信红包给个人用户
188184
* <pre>
@@ -264,4 +260,17 @@ public interface WxMpPayService {
264260
* @return 生成的二维码的字节数组
265261
*/
266262
byte[] createScanPayQrcodeMode2(String codeUrl, File logoFile, Integer sideLength);
263+
264+
/**
265+
* <pre>
266+
* 交易保障
267+
* 应用场景:
268+
* 商户在调用微信支付提供的相关接口时,会得到微信支付返回的相关信息以及获得整个接口的响应时间。
269+
* 为提高整体的服务水平,协助商户一起提高服务质量,微信支付提供了相关接口调用耗时和返回信息的主动上报接口,
270+
* 微信支付可以根据商户侧上报的数据进一步优化网络部署,完善服务监控,和商户更好的协作为用户提供更好的业务体验。
271+
* 接口地址: https://api.mch.weixin.qq.com/payitil/report
272+
* 是否需要证书:不需要
273+
* </pre>
274+
*/
275+
void report(WxPayReportRequest request) throws WxErrorException;
267276
}

weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ public WxPayRefundQueryResult refundQuery(String transactionId, String outTradeN
9595
private void checkResult(WxPayBaseResult result) throws WxErrorException {
9696
//校验返回结果签名
9797
Map<String, String> map = result.toMap();
98-
if (!this.checkSign(map)) {
98+
if (result.getSign() != null &&!this.checkSign(map)) {
9999
log.debug("校验结果签名失败,参数:{}", map);
100100
throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg("参数格式校验错误!").build());
101101
}
@@ -354,6 +354,17 @@ public byte[] createScanPayQrcodeMode2(String codeUrl, File logoFile, Integer si
354354
return QrcodeUtils.createQrcode(codeUrl, sideLength, logoFile);
355355
}
356356

357+
public void report(WxPayReportRequest request) throws WxErrorException {
358+
BeanUtils.checkRequiredFields(request);
359+
this.initRequest(request);
360+
request.setSign(this.createSign(request));
361+
362+
String url = PAY_BASE_URL + "/payitil/report";
363+
String responseContent = this.wxMpService.post(url, request.toXML());
364+
WxPayBaseResult result = WxPayBaseResult.fromXML(responseContent, WxPayBaseResult.class);
365+
this.checkResult(result);
366+
}
367+
357368
private String executeRequest(String url, String requestStr) throws WxErrorException {
358369
HttpPost httpPost = new HttpPost(url);
359370
if (this.wxMpService.getHttpProxy() != null) {
Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
package me.chanjar.weixin.mp.bean.pay.request;
2+
3+
import com.thoughtworks.xstream.annotations.XStreamAlias;
4+
import me.chanjar.weixin.common.annotation.Required;
5+
6+
/**
7+
* <pre>
8+
* 微信支付-交易保障请求参数
9+
* 注释中各行每个字段描述对应如下:
10+
* <li>字段名
11+
* <li>变量名
12+
* <li>是否必填
13+
* <li>类型
14+
* <li>示例值
15+
* <li>描述
16+
* </pre>
17+
*
18+
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
19+
*/
20+
@XStreamAlias("xml")
21+
public class WxPayReportRequest extends WxPayBaseRequest {
22+
/**
23+
* <pre>
24+
* 设备号
25+
* device_info
26+
* 否
27+
* String(32)
28+
* 013467007045764
29+
* 商户自定义的终端设备号,如门店编号、设备的ID等
30+
* </pre>
31+
*/
32+
@XStreamAlias("device_info")
33+
private String deviceInfo;
34+
35+
/**
36+
* <pre>
37+
* 签名类型
38+
* sign_type
39+
* 否
40+
* String(32)
41+
* HMAC-SHA256
42+
* 签名类型,目前支持HMAC-SHA256和MD5,默认为MD5
43+
* </pre>
44+
*/
45+
@XStreamAlias("sign_type")
46+
private String signType;
47+
48+
/**
49+
* <pre>
50+
* 接口URL
51+
* interface_url
52+
* 是
53+
* String(127)
54+
* https://api.mch.weixin.qq.com/pay/unifiedorder
55+
* 报对应的接口的完整URL,类似:https://api.mch.weixin.qq.com/pay/unifiedorder,
56+
* 对于刷卡支付,为更好的和商户共同分析一次业务行为的整体耗时情况,
57+
* 对于两种接入模式,请都在门店侧对一次刷卡支付进行一次单独的整体上报,
58+
* 上报URL指定为:https://api.mch.weixin.qq.com/pay/micropay/total,关于两种接入模式具体可参考本文档章节:
59+
* 刷卡支付商户接入模式,其它接口调用仍然按照调用一次,上报一次来进行。
60+
* </pre>
61+
*/
62+
@Required
63+
@XStreamAlias("interface_url")
64+
private String interfaceUrl;
65+
/**
66+
* <pre>
67+
* 接口耗时
68+
* execute_time
69+
* 是
70+
* Int
71+
* 1000
72+
* 接口耗时情况,单位为毫秒
73+
* </pre>
74+
*/
75+
@Required
76+
@XStreamAlias("execute_time_")//估计是官方接口搞错了
77+
private Integer executeTime;
78+
/**
79+
* <pre>
80+
* 返回状态码
81+
* return_code
82+
* 是
83+
* String(16)
84+
* SUCCESS
85+
* SUCCESS/FAIL,此字段是通信标识,非交易标识,交易是否成功需要查看trade_state来判断
86+
* </pre>
87+
*/
88+
@Required
89+
@XStreamAlias("return_code")
90+
private String returnCode;
91+
/**
92+
* <pre>
93+
* 返回信息
94+
* return_msg
95+
* 否
96+
* String(128)
97+
* 签名失败
98+
* 返回信息,如非空,为错误原因,签名失败,参数格式校验错误
99+
* </pre>
100+
*/
101+
@XStreamAlias("return_msg")
102+
private String returnMsg;
103+
/**
104+
* <pre>
105+
* 业务结果
106+
* result_code
107+
* 是
108+
* String(16)
109+
* SUCCESS
110+
* SUCCESS/FAIL
111+
* </pre>
112+
*/
113+
@Required
114+
@XStreamAlias("result_code")
115+
private String resultCode;
116+
/**
117+
* <pre>
118+
* 错误代码
119+
* err_code
120+
* 否
121+
* String(32)
122+
* SYSTEMERROR
123+
* ORDERNOTEXIST—订单不存在,SYSTEMERROR—系统错误
124+
* </pre>
125+
*/
126+
@XStreamAlias("err_code")
127+
private String errCode;
128+
/**
129+
* <pre>
130+
* 错误代码描述
131+
* err_code_des
132+
* 否
133+
* String(128)
134+
* 系统错误
135+
* 结果信息描述
136+
* </pre>
137+
*/
138+
@XStreamAlias("err_code_des")
139+
private String errCodeDes;
140+
/**
141+
* <pre>
142+
* 商户订单号
143+
* out_trade_no
144+
* 否
145+
* String(32)
146+
* 1217752501201407033233368018
147+
* 商户系统内部的订单号,商户可以在上报时提供相关商户订单号方便微信支付更好的提高服务质量。
148+
* </pre>
149+
*/
150+
@XStreamAlias("out_trade_no")
151+
private String outTradeNo;
152+
/**
153+
* <pre>
154+
* 访问接口IP
155+
* user_ip
156+
* 是
157+
* String(16)
158+
* 8.8.8.8
159+
* 发起接口调用时的机器IP
160+
* </pre>
161+
*/
162+
@Required
163+
@XStreamAlias("user_ip")
164+
private String userIp;
165+
/**
166+
* <pre>
167+
* 商户上报时间
168+
* time
169+
* 否
170+
* String(14)
171+
* 20091227091010
172+
* 系统时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。其他详见时间规则
173+
* </pre>
174+
*/
175+
@XStreamAlias("time")
176+
private String time;
177+
178+
public String getDeviceInfo() {
179+
return deviceInfo;
180+
}
181+
182+
public void setDeviceInfo(String deviceInfo) {
183+
this.deviceInfo = deviceInfo;
184+
}
185+
186+
public String getSignType() {
187+
return signType;
188+
}
189+
190+
public void setSignType(String signType) {
191+
this.signType = signType;
192+
}
193+
194+
public String getInterfaceUrl() {
195+
return interfaceUrl;
196+
}
197+
198+
public void setInterfaceUrl(String interfaceUrl) {
199+
this.interfaceUrl = interfaceUrl;
200+
}
201+
202+
public Integer getExecuteTime() {
203+
return executeTime;
204+
}
205+
206+
public void setExecuteTime(Integer executeTime) {
207+
this.executeTime = executeTime;
208+
}
209+
210+
public String getReturnCode() {
211+
return returnCode;
212+
}
213+
214+
public void setReturnCode(String returnCode) {
215+
this.returnCode = returnCode;
216+
}
217+
218+
public String getReturnMsg() {
219+
return returnMsg;
220+
}
221+
222+
public void setReturnMsg(String returnMsg) {
223+
this.returnMsg = returnMsg;
224+
}
225+
226+
public String getResultCode() {
227+
return resultCode;
228+
}
229+
230+
public void setResultCode(String resultCode) {
231+
this.resultCode = resultCode;
232+
}
233+
234+
public String getErrCode() {
235+
return errCode;
236+
}
237+
238+
public void setErrCode(String errCode) {
239+
this.errCode = errCode;
240+
}
241+
242+
public String getErrCodeDes() {
243+
return errCodeDes;
244+
}
245+
246+
public void setErrCodeDes(String errCodeDes) {
247+
this.errCodeDes = errCodeDes;
248+
}
249+
250+
public String getOutTradeNo() {
251+
return outTradeNo;
252+
}
253+
254+
public void setOutTradeNo(String outTradeNo) {
255+
this.outTradeNo = outTradeNo;
256+
}
257+
258+
public String getUserIp() {
259+
return userIp;
260+
}
261+
262+
public void setUserIp(String userIp) {
263+
this.userIp = userIp;
264+
}
265+
266+
public String getTime() {
267+
return time;
268+
}
269+
270+
public void setTime(String time) {
271+
this.time = time;
272+
}
273+
}

weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/result/WxPayBaseResult.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
2525
* </pre>
2626
*/
27-
public abstract class WxPayBaseResult {
27+
@XStreamAlias("xml")
28+
public class WxPayBaseResult {
2829
/**
2930
* 返回状态码
3031
*/

weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImplTest.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@
66
import me.chanjar.weixin.mp.api.ApiTestModule;
77
import me.chanjar.weixin.mp.api.WxMpService;
88
import me.chanjar.weixin.mp.api.WxXmlMpInMemoryConfigStorage;
9-
import me.chanjar.weixin.mp.bean.pay.request.WxEntPayRequest;
10-
import me.chanjar.weixin.mp.bean.pay.request.WxPayRefundRequest;
11-
import me.chanjar.weixin.mp.bean.pay.request.WxPaySendRedpackRequest;
12-
import me.chanjar.weixin.mp.bean.pay.request.WxPayUnifiedOrderRequest;
9+
import me.chanjar.weixin.mp.bean.pay.request.*;
1310
import me.chanjar.weixin.mp.bean.pay.result.*;
1411
import org.testng.Assert;
1512
import org.testng.annotations.Guice;
@@ -35,6 +32,18 @@ public void testGetPayInfo() throws Exception {
3532

3633
}
3734

35+
@Test
36+
public void testReport() throws Exception {
37+
WxPayReportRequest request = new WxPayReportRequest();
38+
request.setInterfaceUrl("hahahah");
39+
request.setSignType("HMAC-SHA256");//貌似接口未校验此字段
40+
request.setExecuteTime(1000);
41+
request.setReturnCode("aaa");
42+
request.setResultCode("aaa");
43+
request.setUserIp("8.8.8");
44+
this.wxService.getPayService().report(request);
45+
}
46+
3847
/**
3948
* 需要证书的接口需要先执行该方法
4049
*/

0 commit comments

Comments
 (0)