业务示例代码
更新时间:2025.09.031、目标
通过本教程的学习,你应该可以:
设置商户违规处置通知的回调地址
处理商户平台处置记录回调通知
2、业务处理流程
2.1、管理回调地址
从业机构/服务商/渠道商需要先设置商户平台处置通知回调URL后,才可以接收对应的违规、拦截、申诉事件通知。
1package com.java.violation_notification; 2 3// 使用合作伙伴平台创建商户违规通知回调地址接口https://pay.weixin.qq.com/doc/v3/partner/4012471333 4import com.java.demo.CreateViolationNotification; 5import static com.java.demo.CreateViolationNotification.*; 6// 使用合作伙伴平台修改商户违规通知回调地址接口https://pay.weixin.qq.com/doc/v3/partner/4012471330 7import com.java.demo.UpdateViolationNotification; 8import static com.java.demo.UpdateViolationNotification.*; 9// 使用合作伙伴平台删除商户违规通知回调地址接口https://pay.weixin.qq.com/doc/v3/partner/4012471334 10import com.java.demo.DeleteViolationNotification; 11import static com.java.demo.DeleteViolationNotification.*; 12// 使用合作伙伴平台查询商户违规通知回调地址接口https://pay.weixin.qq.com/doc/v3/partner/4012471327 13import com.java.demo.GetViolationNotification; 14import static com.java.demo.GetViolationNotification.*; 15 16public class ViolationNotificationUrlDemo { 17 // TODO: 请准备商户开发必要参数,参考:https://pay.weixin.qq.com/doc/v3/partner/4013080340 18 // 商户号,是由微信支付系统生成并分配给每个商户的唯一标识符,商户号获取方式参考 19 // https://pay.weixin.qq.com/doc/v3/partner/4013080340 20 private static String mchid = "19xxxxxxxx"; 21 // 商户API证书序列号,如何获取请参考 https://pay.weixin.qq.com/doc/v3/partner/4013058924 22 private static String certificateSerialNo = "1DDE55AD98Exxxxxxxxxx"; 23 // 商户API证书私钥文件路径,本地文件路径 24 private static String privateKeyFilePath = "/path/to/apiclient_key.pem"; 25 // 微信支付公钥ID,如何获取请参考 https://pay.weixin.qq.com/doc/v3/partner/4013038589 26 private static String wechatPayPublicKeyId = "PUB_KEY_ID_xxxxxxxxxxxxx"; 27 // 微信支付公钥文件路径,本地文件路径 28 private static String wechatPayPublicKeyFilePath = "/path/to/wxp_pub.pem"; 29 30 public static void main(String[] args) { 31 String notifyUrl = "https://www.example.com/notify"; 32 ViolationNotificationUrlDemo demo = new ViolationNotificationUrlDemo(); 33 34 // 1. 创建违约通知URL 35 String createNotifyUrl = demo.createViolationNotificationUrl(notifyUrl); 36 System.out.println("createNotifyUrl: " + createNotifyUrl); 37 38 // 2. 更新违约通知URL 39 // String updateNotifyUrl = demo.updateViolationNotificationUrl(notifyUrl); 40 // System.out.println("updateNotifyUrl: " + updateNotifyUrl); 41 42 // 3. 删除违约通知URL 43 // demo.deleteViolationNotificationUrl(); 44 45 // 4. 查询违约通知URL 46 String getNotifyUrl = demo.getViolationNotificationUrl(); 47 System.out.println("getNotifyUrl: " + getNotifyUrl); 48 } 49 50 private String createViolationNotificationUrl(String notifyUrl) { 51 CreateViolationNotification client = new CreateViolationNotification( 52 mchid, 53 certificateSerialNo, 54 privateKeyFilePath, 55 wechatPayPublicKeyId, 56 wechatPayPublicKeyFilePath); 57 58 CreateViolationNotificationRequest request = new CreateViolationNotificationRequest(); 59 request.notifyUrl = notifyUrl; 60 try { 61 CreateViolationNotificationResponse response = client.run(request); 62 System.out.println(response); 63 return response.notifyUrl; 64 } catch (WXPayUtility.ApiException e) { 65 // 创建违约通知URL处理异常处理逻辑 66 if (e.getErrorCode().equals("SYSTEM_ERROR")) { 67 // 错误:系统错误 68 // 解决方式:稍后重试 69 } else if (e.getErrorCode().equals("FREQUENCY_LIMITED")) { 70 // 错误:限频报错 71 // 解决方式:稍后重试 72 } else if (e.getErrorCode().equals("ALREADY_EXISTS")) { 73 // 错误:用户账户异常 74 // 解决方式:说明已经创建成功,可以通过查询接口确认是否符合预期 75 } else if (e.getErrorCode().equals("SIGN_ERROR")) { 76 // 错误:签名错误 77 // 解决方式:检查平台商户证书序列号,证书私钥文件,公钥ID,公钥文件,同时确认下签名过程是不是按照微信支付的签名方式 78 // 描述:签名报错,需要确认签名材料和签名流程是否正确 79 } else if (e.getErrorCode().equals("PARAM_ERROR")) { 80 // 错误:参数错误 81 // 解决方式:按照报错返回的message,重新输入请求参数 82 // 描述:参数的类型,长度,或者必填选项没有填写等 83 } else if (e.getErrorCode().equals("INVALID_REQUEST")) { 84 // 错误:请求非法,请求参数正确,但是不符合违约通知URL业务规则 85 // 解决方式:根据具体message查看具体哪里不符合业务规则,如果可以修改参数达到符合业务规则的修改请求符合业务规则之后再重试 86 } else { 87 // 其他类型错误:稍等一会后重试 88 } 89 } 90 return null; // 如果发生异常,返回null 91 } 92 93 private String updateViolationNotificationUrl(String notifyUrl) { 94 UpdateViolationNotification client = new UpdateViolationNotification( 95 mchid, 96 certificateSerialNo, 97 privateKeyFilePath, 98 wechatPayPublicKeyId, 99 wechatPayPublicKeyFilePath); 100 101 UpdateViolationNotificationRequest request = new UpdateViolationNotificationRequest(); 102 request.notifyUrl = notifyUrl; 103 try { 104 UpdateViolationNotificationResponse response = client.run(request); 105 System.out.println(response); 106 return response.notifyUrl; 107 } catch (WXPayUtility.ApiException e) { 108 // 更新违约通知URL处理异常处理逻辑 109 if (e.getErrorCode().equals("SYSTEM_ERROR")) { 110 // 错误:系统错误 111 // 解决方式:稍后重试 112 } else if (e.getErrorCode().equals("FREQUENCY_LIMITED")) { 113 // 错误:限频报错 114 // 解决方式:稍后重试 115 } else if (e.getErrorCode().equals("NOT_FOUND")) { 116 // 错误:回调地址不存在 117 // 解决方式:请检查是否已创建通知回调URL 118 } else if (e.getErrorCode().equals("SIGN_ERROR")) { 119 // 错误:签名错误 120 // 解决方式:检查平台商户证书序列号,证书私钥文件,公钥ID,公钥文件,同时确认下签名过程是不是按照微信支付的签名方式 121 // 描述:签名报错,需要确认签名材料和签名流程是否正确 122 } else if (e.getErrorCode().equals("PARAM_ERROR")) { 123 // 错误:参数错误 124 // 解决方式:按照报错返回的message,重新输入请求参数 125 // 描述:参数的类型,长度,或者必填选项没有填写等 126 } else if (e.getErrorCode().equals("INVALID_REQUEST")) { 127 // 错误:请求非法,请求参数正确,但是不符合违约通知URL业务规则 128 // 解决方式:根据具体message查看具体哪里不符合业务规则,如果可以修改参数达到符合业务规则的修改请求符合业务规则之后再重试 129 } else { 130 // 其他类型错误:稍等一会后重试 131 } 132 } 133 return null; // 如果发生异常,返回null 134 } 135 136 private void deleteViolationNotificationUrl() { 137 DeleteViolationNotification client = new DeleteViolationNotification( 138 mchid, 139 certificateSerialNo, 140 privateKeyFilePath, 141 wechatPayPublicKeyId, 142 wechatPayPublicKeyFilePath); 143 144 try { 145 client.run(); 146 System.out.println("删除成功"); 147 } catch (WXPayUtility.ApiException e) { 148 // 删除违约通知URL处理异常处理逻辑 149 if (e.getErrorCode().equals("SYSTEM_ERROR")) { 150 // 错误:系统错误 151 // 解决方式:稍后重试 152 } else if (e.getErrorCode().equals("FREQUENCY_LIMITED")) { 153 // 错误:限频报错 154 // 解决方式:稍后重试 155 } else if (e.getErrorCode().equals("NOT_FOUND")) { 156 // 错误:回调地址不存在 157 // 解决方式:请检查是否已创建通知回调URL 158 } else if (e.getErrorCode().equals("SIGN_ERROR")) { 159 // 错误:签名错误 160 // 解决方式:检查平台商户证书序列号,证书私钥文件,公钥ID,公钥文件,同时确认下签名过程是不是按照微信支付的签名方式 161 // 描述:签名报错,需要确认签名材料和签名流程是否正确 162 } else if (e.getErrorCode().equals("PARAM_ERROR")) { 163 // 错误:参数错误 164 // 解决方式:按照报错返回的message,重新输入请求参数 165 // 描述:参数的类型,长度,或者必填选项没有填写等 166 } else if (e.getErrorCode().equals("INVALID_REQUEST")) { 167 // 错误:请求非法,请求参数正确,但是不符合违约通知URL业务规则 168 // 解决方式:根据具体message查看具体哪里不符合业务规则,如果可以修改参数达到符合业务规则的修改请求符合业务规则之后再重试 169 } else { 170 // 其他类型错误:稍等一会后重试 171 } 172 } 173 } 174 175 private String getViolationNotificationUrl() { 176 GetViolationNotification client = new GetViolationNotification( 177 mchid, 178 certificateSerialNo, 179 privateKeyFilePath, 180 wechatPayPublicKeyId, 181 wechatPayPublicKeyFilePath); 182 183 try { 184 GetViolationNotificationResponse response = client.run(); 185 System.out.println(response); 186 return response.notifyUrl; 187 } catch (WXPayUtility.ApiException e) { 188 // 查询违约通知URL处理异常处理逻辑 189 if (e.getErrorCode().equals("SYSTEM_ERROR")) { 190 // 错误:系统错误 191 // 解决方式:稍后重试 192 } else if (e.getErrorCode().equals("FREQUENCY_LIMITED")) { 193 // 错误:限频报错 194 // 解决方式:稍后重试 195 } else if (e.getErrorCode().equals("NOT_FOUND")) { 196 // 错误:回调地址不存在 197 // 解决方式:请检查是否已创建通知回调URL 198 } else if (e.getErrorCode().equals("SIGN_ERROR")) { 199 // 错误:签名错误 200 // 解决方式:检查平台商户证书序列号,证书私钥文件,公钥ID,公钥文件,同时确认下签名过程是不是按照微信支付的签名方式 201 // 描述:签名报错,需要确认签名材料和签名流程是否正确 202 } else if (e.getErrorCode().equals("PARAM_ERROR")) { 203 // 错误:参数错误 204 // 解决方式:按照报错返回的message,重新输入请求参数 205 // 描述:参数的类型,长度,或者必填选项没有填写等 206 } else if (e.getErrorCode().equals("INVALID_REQUEST")) { 207 // 错误:请求非法,请求参数正确,但是不符合违约通知URL业务规则 208 // 解决方式:根据具体message查看具体哪里不符合业务规则,如果可以修改参数达到符合业务规则的修改请求符合业务规则之后再重试 209 } else { 210 // 其他类型错误:稍等一会后重试 211 } 212 } 213 return null; // 如果发生异常,返回null 214 } 215}
2.2、处理商户平台处置记录回调通知
回调地址设置成功后,确保回调地址可以正常访问的情况下,子商户违规处理记录和交易拦截记录时,可以接收到对应的推送
1import okhttp3.Headers; 2 3// 商户APIv3密钥 https://pay.weixin.qq.com/doc/v3/partner/4013059095 4String apiv3Key = "xxxxxxx"; 5// 微信支付公钥ID,如何获取请参考 https://pay.weixin.qq.com/doc/v3/partner/4013038589 6String wechatPayPublicKeyId = "PUB_KEY_ID_xxxxxxxxxxxxx"; 7// 微信支付公钥文件路径,本地文件路径 8String wechatPayPublicKeyFilePath = "/path/to/wxp_pub.pem"; 9// 此处为代码示例,获取微信支付通知 Header 列表 10Headers headers = getHeaders(); 11// 此处为代码示例,获取微信支付通知 Body 12String body = getBody(); 13 14PublicKey wechatPayPublicKey WXPayUtility.loadPublicKeyFromPath(wechatPayPublicKeyFilePath); 15 16Notification notification; 17try { 18 // 1. 解析微信支付回调包体,body为商户接收到微信回调的原始信息 19 notification = WXPayUtility.parseNotification(apiv3Key, wechatPayPublicKeyId, wechatPayPublicKey, headers, body); 20 // 2. 解析完回调包体之后,可以先返回给微信支付200或者204,表示回调成功 21 // 商户再异步处理包体逻辑,这样子能保证微信回调不会超时,微信支付超时多次之后不会再回调 22 send2MQ(notification); 23} catch (Exception e) { 24 // 处理回调异常 25} 26 27
文档是否有帮助
