Continuing from the previous article on WeChat payment, let’s briefly talk about the WeChat payment callback.
1. Payment callback
When the user pays successfully, the payment platform will send a request to our designated server interface to deliver the order payment status data.
2. WeChat callback address problem
1. Local/online testing
If you are testing locally, you need to use the intranet penetration tool ( NATAPP - intranet penetration domestic high-speed intranet mapping tool based on ngrok ). The obtained address must be accessible from the external network. For specific usage, click directly to The official website has documentation, so I won’t go into details here.
When testing online, change it to the corresponding environment address yourself.
WeChat callback address example:
v3PayNotifyUrl: https://***.mynatapp.cc/jsapiPay/payNotify # WeChat callback address
2. Controller call interface (code)
code show as below:
@PostMapping("/payNotify")
public void payNotify(HttpServletRequest request, HttpServletResponse response) throws Exception{
//获取报文
String body = getRequestBody(request);
//随机串
String nonceStr = request.getHeader("Wechatpay-Nonce");
//微信传递过来的签名
String signature = request.getHeader("Wechatpay-Signature");
//证书序列号(微信平台)
String serialNo = request.getHeader("Wechatpay-Serial");
//时间戳
String timestamp = request.getHeader("Wechatpay-Timestamp");
InputStream is = null;
try {
is = request.getInputStream();
// 构造 RequestParam
RequestParam requestParam = new RequestParam.Builder()
.serialNumber(serialNo)
.nonce(nonceStr)
.signature(signature)
.timestamp(timestamp)
.body(body)
.build();
// 如果已经初始化了 RSAAutoCertificateConfig,可以直接使用 config
// 初始化 NotificationParser
NotificationParser parser = new NotificationParser(config);
// 验签、解密并转换成 Transaction
Transaction transaction = parser.parse(requestParam, Transaction.class);
//记录日志信息
Transaction.TradeStateEnum state = transaction.getTradeState();
String openid = transaction.getPayer().getOpenid();
if (!StringUtils.equals("SUCCESS", state.toString())) {
log.error("微信回调失败,JsapiPayController.payNotify.transaction:{}",transaction.toString());
//通知微信回调失败
response.getWriter().write("<xml><return_code><![CDATA[FAIL]]></return_code></xml>");
}
//TODO------
//根据自己的需求处理相应的业务逻辑,异步
//通知微信回调成功
response.getWriter().write("<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>");
} catch (Exception e) {
e.printStackTrace();
}finally {
is.close();
}
}
/**
* 读取请求数据流
* @param request
* @return
*/
private String getRequestBody(HttpServletRequest request) {
StringBuffer sb = new StringBuffer();
try (ServletInputStream inputStream = request.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
) {
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
log.error("读取数据流异常:{}", e);
}
return sb.toString();
}
Summarize
Callbacks are basically mentioned in the official documents, and I won’t go into much else. Basically, it’s just about dealing with your own business logic issues.