支付成功回调通知
当用户支付成功之后,长天优选开放平台会对创建订单时传递的通知url进行异步通知(POST的Http请求)
通知频率:支付成功立马通知一次, 如果第三方未正确的应答返回 success
,之后每2分钟通知一次,连续通知5次。
通知参数:
通知请求的body数据为json格式,具体各字段说明如下:
字段名称 | 数据类型 | 说明 |
---|---|---|
appKey | string | 长天优选分配的appkey |
notifyTime | date | 通知时间 |
notifyType | int | 通知类型 1:订单支付成功通知 |
signType | string | 签名方式,例如SHA-256,通知消息验签时使用的签名算法 |
sign | string | 通知消息的签名 |
orderNo | string | 长天优选订单号 |
outOrderNo | string | 第三方订单号 |
payTime | date | 支付时间 |
originAmount | int | 订单原金额,单位:分(创建订单时传递的订单金额) |
通知回调验签步骤
第一步:将接收到的对象json转换为map, 去除 sign、signType,并按照key1=value1&key2=value2&key3=value3的形式拼接成字符串,注意 在拼接前需要按照key的ASCII码从小到大排序(升序),key区分大小写
第二步:对第一步拼接的字符串尾部拼接提供密钥AppSecret,得到SignValue字符串
第三步:对第二步拼接得到的SignValue字符串按照签名算法signType进行加密处理(小写)
签名实现(java)
private String calculateNotifySign(ThirdPartyNotifyArgVO argsVO, String appSecret) {
Map<String, Object> argsMap = BeanUtil.beanToMap(argsVO);
// sign、signType不参与签名
final String SIGN_TYPE_KEY_NAME = "signType";
final String SIGN_KEY_NAME = "sign";
Map<String, String> filterArgsMap = new HashMap<>();
argsMap.forEach((key, value) -> {
if (!SIGN_TYPE_KEY_NAME.equals(key) && !SIGN_KEY_NAME.equals(key)) {
filterArgsMap.put(key, String.valueOf(value));
}
});
// 排序拼接并追加appsecret
Map<String, String> sortMap = com.jxchangtian.ctmall.open.util.HttpUtil.sortMapByAscii(filterArgsMap);
String linkString = com.jxchangtian.ctmall.open.util.HttpUtil.cerateLinkString(sortMap);
String signString = linkString + appSecret;
// 签名算法
if (ThirdPartyNotifyArgVO.SIGN_TYPE_SHA256.equals(argsVO.getSignType())) {
return DigestUtil.sha256Hex(signString);
} else {
return null;
}
}
异步通知处理Demo
@PostMapping("/paySuccessNotifyCallBackDemo")
@ApiOperation("第三方订单支付成功通知处理demo")
public void paySuccessNotifyCallBackDemo(RequestReaderHttpServletRequestWrapper request, ContentCachingResponseWrapper resonse) {
String content = "fail";
String requestBodyConent = request.getBodyConent();
if (StrUtil.isNotBlank(requestBodyConent)) {
ThirdPartyNotifyArgVO argVO = JSONUtil.toBean(requestBodyConent, ThirdPartyNotifyArgVO.class);
boolean signOk = notifyService.isSignOk(argVO);
if (signOk) {
content = "success";
}
}
// 返回字符串
try {
resonse.setCharacterEncoding("utf-8");
resonse.setContentType("text/html; charset=utf-8");
PrintWriter writer = resonse.getWriter();
writer.write(content.toCharArray());
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}