Skip to content

Commit 0195f14

Browse files
authored
Merge branch 'binarywang:develop' into develop
2 parents 0a31386 + 673af5e commit 0195f14

20 files changed

Lines changed: 514 additions & 12 deletions

File tree

.github/agents/my-agent.agent.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ description: 需要用中文,包括PR标题和分析总结过程
1212

1313
- 1、请使用中文输出思考过程和总结,包括PR标题,提交commit信息也要使用中文;
1414
- 2、生成代码时需要提供必要的单元测试代码;
15-
- 3、新增加的代码如果标记作者信息,请注意不要把作者名设为binarywang或者其他无关人员,要改为 GitHub Copilot。
15+
- 3、实现接口时请严格按照官方文档编写代码,严禁瞎编乱造、臆想并实现不存在的接口;
16+
- 4、新增加的代码如果标记作者信息,请注意不要把作者名设为binarywang或者其他无关人员,要改为 GitHub Copilot。

weixin-java-common/src/main/java/me/chanjar/weixin/common/error/WxMaErrorMsgEnum.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -838,6 +838,34 @@ public enum WxMaErrorMsgEnum {
838838
*/
839839
CODE_89424(89424, "授权次数到达上限"),
840840

841+
/**
842+
* 微信小程序虚拟支付错误码
843+
*
844+
* @see <a href="https://developers.weixin.qq.com/miniprogram/dev/server/API/VirtualPayment/api_query_order.html">虚拟支付 API 文档</a>
845+
*/
846+
CODE_268490001(268490001, "openid错误"),
847+
CODE_268490002(268490002, "请求参数字段错误,具体看errmsg"),
848+
CODE_268490003(268490003, "签名错误"),
849+
CODE_268490004(268490004, "重复操作(赠送和代币支付和充值广告金相关接口会返回,表示之前的操作已经成功)"),
850+
CODE_268490005(268490005, "订单已经通过cancel_currency_pay接口退款,不支持再退款"),
851+
CODE_268490006(268490006, "代币的退款/支付操作金额不足"),
852+
CODE_268490007(268490007, "图片或文字存在敏感内容,禁止使用"),
853+
CODE_268490008(268490008, "代币未发布,不允许进行代币操作"),
854+
CODE_268490009(268490009, "用户session_key不存在或已过期,请重新登录"),
855+
CODE_268490011(268490011, "数据生成中,请稍后调用本接口获取"),
856+
CODE_268490012(268490012, "批量任务运行中,请等待完成后才能再次运行"),
857+
CODE_268490013(268490013, "禁止对核销状态的单进行退款"),
858+
CODE_268490014(268490014, "退款操作进行中,稍后可以使用相同参数重试"),
859+
CODE_268490015(268490015, "频率限制"),
860+
CODE_268490016(268490016, "退款的left_fee字段与实际不符,请通过query_order接口查询确认"),
861+
CODE_268490018(268490018, "广告金充值账户行业id不匹配"),
862+
CODE_268490019(268490019, "广告金充值账户id已绑定其他appid"),
863+
CODE_268490020(268490020, "广告金充值账户主体名称错误"),
864+
CODE_268490021(268490021, "账户未完成进件"),
865+
CODE_268490022(268490022, "广告金充值账户无效"),
866+
CODE_268490023(268490023, "广告金余额不足"),
867+
CODE_268490024(268490024, "广告金充值金额必须大于0"),
868+
841869
;
842870

843871
private final int code;
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package me.chanjar.weixin.common.error;
2+
3+
import org.testng.annotations.Test;
4+
5+
import static org.testng.Assert.assertEquals;
6+
import static org.testng.Assert.assertNotNull;
7+
import static org.testng.Assert.assertNull;
8+
9+
/**
10+
* 微信小程序错误码枚举测试
11+
*
12+
* @author GitHub Copilot
13+
*/
14+
@Test
15+
public class WxMaErrorMsgEnumTest {
16+
17+
public void testFindMsgByCodeForExistingCode() {
18+
String msg = WxMaErrorMsgEnum.findMsgByCode(40001);
19+
assertNotNull(msg);
20+
}
21+
22+
public void testFindMsgByCodeForNonExistingCode() {
23+
String msg = WxMaErrorMsgEnum.findMsgByCode(999999);
24+
assertNull(msg);
25+
}
26+
27+
/**
28+
* 验证微信小程序虚拟支付错误码
29+
*/
30+
public void testVirtualPaymentErrorCodes() {
31+
assertEquals(WxMaErrorMsgEnum.findMsgByCode(268490001), "openid错误");
32+
assertEquals(WxMaErrorMsgEnum.findMsgByCode(268490002), "请求参数字段错误,具体看errmsg");
33+
assertEquals(WxMaErrorMsgEnum.findMsgByCode(268490003), "签名错误");
34+
assertEquals(WxMaErrorMsgEnum.findMsgByCode(268490004), "重复操作(赠送和代币支付和充值广告金相关接口会返回,表示之前的操作已经成功)");
35+
assertEquals(WxMaErrorMsgEnum.findMsgByCode(268490005), "订单已经通过cancel_currency_pay接口退款,不支持再退款");
36+
assertEquals(WxMaErrorMsgEnum.findMsgByCode(268490006), "代币的退款/支付操作金额不足");
37+
assertEquals(WxMaErrorMsgEnum.findMsgByCode(268490007), "图片或文字存在敏感内容,禁止使用");
38+
assertEquals(WxMaErrorMsgEnum.findMsgByCode(268490008), "代币未发布,不允许进行代币操作");
39+
assertEquals(WxMaErrorMsgEnum.findMsgByCode(268490009), "用户session_key不存在或已过期,请重新登录");
40+
assertEquals(WxMaErrorMsgEnum.findMsgByCode(268490011), "数据生成中,请稍后调用本接口获取");
41+
assertEquals(WxMaErrorMsgEnum.findMsgByCode(268490012), "批量任务运行中,请等待完成后才能再次运行");
42+
assertEquals(WxMaErrorMsgEnum.findMsgByCode(268490013), "禁止对核销状态的单进行退款");
43+
assertEquals(WxMaErrorMsgEnum.findMsgByCode(268490014), "退款操作进行中,稍后可以使用相同参数重试");
44+
assertEquals(WxMaErrorMsgEnum.findMsgByCode(268490015), "频率限制");
45+
assertEquals(WxMaErrorMsgEnum.findMsgByCode(268490016), "退款的left_fee字段与实际不符,请通过query_order接口查询确认");
46+
assertEquals(WxMaErrorMsgEnum.findMsgByCode(268490018), "广告金充值账户行业id不匹配");
47+
assertEquals(WxMaErrorMsgEnum.findMsgByCode(268490019), "广告金充值账户id已绑定其他appid");
48+
assertEquals(WxMaErrorMsgEnum.findMsgByCode(268490020), "广告金充值账户主体名称错误");
49+
assertEquals(WxMaErrorMsgEnum.findMsgByCode(268490021), "账户未完成进件");
50+
assertEquals(WxMaErrorMsgEnum.findMsgByCode(268490022), "广告金充值账户无效");
51+
assertEquals(WxMaErrorMsgEnum.findMsgByCode(268490023), "广告金余额不足");
52+
assertEquals(WxMaErrorMsgEnum.findMsgByCode(268490024), "广告金充值金额必须大于0");
53+
}
54+
55+
/**
56+
* 验证虚拟支付错误码中不存在的编号(如268490010、268490017)返回null
57+
*/
58+
public void testVirtualPaymentMissingCodes() {
59+
assertNull(WxMaErrorMsgEnum.findMsgByCode(268490010));
60+
assertNull(WxMaErrorMsgEnum.findMsgByCode(268490017));
61+
}
62+
}

weixin-java-cp/src/main/java/me/chanjar/weixin/cp/config/impl/AbstractWxCpTpInRedisConfigImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ public WxAccessToken getAccessTokenEntity(String authCorpId) {
224224

225225
WxAccessToken accessTokenEntity = new WxAccessToken();
226226
accessTokenEntity.setAccessToken(accessToken);
227-
accessTokenEntity.setExpiresIn((int) ((expire - System.currentTimeMillis()) / 1000 + 200));
227+
accessTokenEntity.setExpiresIn(Math.max(Math.toIntExact(expire), 0));
228228
return accessTokenEntity;
229229
}
230230

weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/WxMaUserService.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,4 +108,20 @@ public interface WxMaUserService {
108108
* @throws WxErrorException 调用微信接口失败时抛出
109109
*/
110110
WxMaCode2VerifyInfoResult getCode2VerifyInfo(String code, String checkcode) throws WxErrorException;
111+
112+
/**
113+
* 检查登录态(checkSessionKey).
114+
* <p>
115+
* 检验登录态是否有效,用于虚拟支付等场景构建用户签名前的登录态验证。
116+
* 登录态有效时返回 {@code true};登录态已失效时,微信服务端将返回错误码(如 87009),
117+
* 并以 {@link me.chanjar.weixin.common.error.WxErrorException} 的形式抛出。
118+
* </p>
119+
* 文档地址:<a href="https://developers.weixin.qq.com/miniprogram/dev/server/API/user-login/api_checksessionkey.html">检查登录态</a>
120+
*
121+
* @param openid 用户唯一标识符
122+
* @param sessionKey 用户的 session_key,通过 {@link #getSessionInfo(String)} 获取
123+
* @return 登录态有效时返回 {@code true}
124+
* @throws WxErrorException 登录态已失效或调用微信接口失败时抛出(失效时 errcode 为 87009)
125+
*/
126+
boolean checkSessionKey(String openid, String sessionKey) throws WxErrorException;
111127
}

weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/api/impl/WxMaUserServiceImpl.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import java.util.Map;
2121

22+
import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.User.CHECK_SESSION_KEY_URL;
2223
import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.User.CODE_2_VERIFY_INFO_URL;
2324
import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.User.GET_PHONE_NUMBER_URL;
2425
import static cn.binarywang.wx.miniapp.constant.WxMaApiUrlConstants.User.SET_USER_STORAGE;
@@ -97,4 +98,12 @@ public WxMaCode2VerifyInfoResult getCode2VerifyInfo(String code, String checkcod
9798
return WxMaCode2VerifyInfoResult.fromJson(responseContent);
9899
}
99100

101+
@Override
102+
public boolean checkSessionKey(String openid, String sessionKey) throws WxErrorException {
103+
String signature = SignUtils.createHmacSha256Sign(openid, sessionKey);
104+
String url = String.format(CHECK_SESSION_KEY_URL, openid, signature);
105+
this.service.get(url, null);
106+
return true;
107+
}
108+
100109
}

weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/WxMaMessage.java

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ public class WxMaMessage implements Serializable {
189189
@XStreamConverter(value = XStreamCDataConverter.class)
190190
private String revokeInfo;
191191

192-
@SerializedName("OpenID")
192+
@SerializedName(value = "OpenID", alternate = {"OpenId"})
193193
@XStreamAlias("OpenID")
194194
@XStreamConverter(value = XStreamCDataConverter.class)
195195
private String openId;
@@ -418,6 +418,52 @@ public class WxMaMessage implements Serializable {
418418
@XStreamAlias("TeamInfo")
419419
private WxMaXPayTeamInfo teamInfo;
420420

421+
// xpay_complaint_notify 用户投诉推送字段
422+
423+
/**
424+
* 微信支付交易单号.
425+
* xpay_complaint_notify
426+
*/
427+
@SerializedName("TransactionId")
428+
@XStreamAlias("TransactionId")
429+
@XStreamConverter(value = XStreamCDataConverter.class)
430+
private String complaintTransactionId;
431+
432+
/**
433+
* 投诉单号.
434+
* xpay_complaint_notify
435+
*/
436+
@SerializedName("ComplaintId")
437+
@XStreamAlias("ComplaintId")
438+
@XStreamConverter(value = XStreamCDataConverter.class)
439+
private String complaintId;
440+
441+
/**
442+
* 投诉详情.
443+
* xpay_complaint_notify
444+
*/
445+
@SerializedName("ComplaintDetail")
446+
@XStreamAlias("ComplaintDetail")
447+
@XStreamConverter(value = XStreamCDataConverter.class)
448+
private String complaintDetail;
449+
450+
/**
451+
* 投诉时间,秒级时间戳.
452+
* xpay_complaint_notify
453+
*/
454+
@SerializedName("ComplaintTime")
455+
@XStreamAlias("ComplaintTime")
456+
private Long complaintTime;
457+
458+
/**
459+
* 请求编号.
460+
* xpay_complaint_notify
461+
*/
462+
@SerializedName("RequestId")
463+
@XStreamAlias("RequestId")
464+
@XStreamConverter(value = XStreamCDataConverter.class)
465+
private String requestId;
466+
421467
/**
422468
* 不要直接使用这个字段,
423469
* 这个字段只是为了适配 SubscribeMsgPopupEvent SubscribeMsgChangeEvent SubscribeMsgSentEvent

weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/bean/xpay/WxMaXPayQueryOrderResponse.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,11 @@ public static class OrderInfo {
5656
@SerializedName("token")
5757
private String token;
5858

59-
@SerializedName("leftFee")
60-
private Long leftFee; //支付单类型时表示此单经过退款还剩余的金额,单位分
61-
@SerializedName("wxOrderId")
59+
/** 支付单类型时表示此单经过退款还剩余的金额,单位分 */
60+
@SerializedName("left_fee")
61+
private Long leftFee;
62+
/** 微信内部单号 */
63+
@SerializedName("wx_order_id")
6264
private String wxOrderId;
6365

6466
/** 渠道单号,为用户微信支付详情页面上的商户单号 */
@@ -70,7 +72,14 @@ public static class OrderInfo {
7072
/** 结算时间的秒级时间戳,大于0表示结算成功 */
7173
@SerializedName("sett_time")
7274
private Long settTime;
73-
/** 结算状态:0-未开始结算 1-结算中 2-结算成功 3-待结算(与0相同) */
75+
/**
76+
* 结算状态:
77+
* 0-未开始结算
78+
* 1-结算中
79+
* 2-结算成功
80+
* 3-待结算(与0相同)
81+
* 4-苹果iOS订单,Apple公司结算中
82+
*/
7483
@SerializedName("sett_state")
7584
private Integer settState;
7685
/** 虚拟支付技术服务费,单位为分;sett_state = 2时返回 */

weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/constant/WxMaApiUrlConstants.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,9 @@ public interface User {
366366
String GET_PHONE_NUMBER_URL = "https://api.weixin.qq.com/wxa/business/getuserphonenumber";
367367
/** 多端登录验证接口 */
368368
String CODE_2_VERIFY_INFO_URL = "https://api.weixin.qq.com/wxa/sec/checkcode2verifyinfo";
369+
/** 检查登录态接口 */
370+
String CHECK_SESSION_KEY_URL =
371+
"https://api.weixin.qq.com/wxa/checksessionkey?openid=%s&signature=%s&sig_method=hmac_sha256";
369372
}
370373

371374
public interface Ocr {

weixin-java-miniapp/src/main/java/cn/binarywang/wx/miniapp/constant/WxMaConstants.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -261,9 +261,10 @@ public static final class XPayOrderStatus {
261261
}
262262
@UtilityClass
263263
public static final class XPayNotifyEvent {
264-
public static String COIN_PAY = "xpay_coin_pay_notify";
265-
public static String GOODS_DELIVER = "xpay_goods_deliver_notify";
266-
public static String REFUND = "xpay_refund_notify";
264+
public static final String COIN_PAY = "xpay_coin_pay_notify";
265+
public static final String GOODS_DELIVER = "xpay_goods_deliver_notify";
266+
public static final String REFUND = "xpay_refund_notify";
267+
public static final String COMPLAINT = "xpay_complaint_notify";
267268

268269
}
269270
@UtilityClass

0 commit comments

Comments
 (0)