1.支付分對接時(shí)注意的坑
創(chuàng)建支付分訂單API? ??https://api.mch.weixin.qq.com/v3/payscore/serviceorder
修改訂單金額API? ? ? ?https://api.mch.weixin.qq.com/v3/payscore/serviceorder/{out_order_no}/modify
取消支付分訂單API? ? https://api.mch.weixin.qq.com/v3/payscore/serviceorder/{out_order_no}/cancel
完結(jié)支付分訂單API? ? https://api.mch.weixin.qq.com/v3/payscore/serviceorder/{out_order_no}/complete
注:劃刪除線的部分是在url上拼接path的乒融,并且傳輸時(shí)param不可包含 out_order_no這個(gè)參數(shù)。
所以,我作了如下處理:
回調(diào)處理 :
@PostMapping("/confirmNotify")
@ResponseBody
public JSONObjectconfirmNotify(HttpServletRequest request){
try{
ServletInputStream servletInputStream = request.getInputStream();
? ? ? ? int contentLength = request.getContentLength();
? ? ? ? byte[] callBackInBytes =new byte[contentLength];
? ? ? ? servletInputStream.read(callBackInBytes, 0, contentLength);
? ? ? ? String callBackIn =new String(callBackInBytes, StandardCharsets.UTF_8);
? ? ? ? logger.info("【微信支付分回調(diào)】{}" , callBackIn);
? ? ? ? JSONObject notifyIn = JSONObject.parseObject(callBackIn);
? ? ? ? if (notifyIn ==null) {
logger.info("支付回調(diào)失敗古胆,參數(shù)不正確疗认,反序列化失敗");
? ? ? ? }
//解密回調(diào)信息
? ? ? ? assert notifyIn !=null;
? ? ? ? JSONObject resource = notifyIn.getJSONObject("resource");
? ? ? ? byte[] key = (wxConfig.IV3KEY).getBytes(StandardCharsets.UTF_8);
? ? ? ? ApiV3Util aesUtil =new ApiV3Util(key);
? ? ? ? String decryptToString = aesUtil.decryptToString(resource.getString("associated_data").getBytes(StandardCharsets.UTF_8), resource.getString("nonce").getBytes("UTF-8"), resource.getString("ciphertext"));
? ? ? ? if (StringUtils.isEmpty(decryptToString)) {
logger.info("支付回調(diào)失敗清笨,參數(shù)解密錯(cuò)誤");
? ? ? ? }
logger.info("【支付分支付回調(diào)解密結(jié)果:】" + decryptToString);
? ? ? ? // 用戶確認(rèn)成功
? ? ? ? if ("PAYSCORE.USER_CONFIRM".equals(notifyIn.get("event_type"))) {
JSONObject json=JSONObject.parseObject(decryptToString);
? ? ? ? ? ? if("USER_CONFIRM".equals(json.getString("state_description"))){
logger.info("用戶確認(rèn)成功[【YES】],解密數(shù)據(jù){}",json);
? ? ? ? ? ? ? ? return payPointService.receiveBack(0,json);
? ? ? ? ? ? }
}
// 支付成功
? ? ? ? if ("PAYSCORE.USER_PAID".equals(notifyIn.get("event_type"))) {
JSONObject json=JSONObject.parseObject(decryptToString);
? ? ? ? ? ? if("MCH_COMPLETE".equals(json.getString("state_description"))){
logger.info("用戶支付成功[【YES】],解密數(shù)據(jù){}",json);
? ? ? ? ? ? ? ? return payPointService.receiveBack(1,json);
? ? ? ? ? ? }
}
}catch (Exception e) {
logger.error("微信支付回調(diào)處理異常器腋," + e.toString());
? ? ? ? e.printStackTrace();
? ? }
return null;
}
注意:此處的IPV3key是IPV3支付密鑰溪猿,從商戶獲取。
回調(diào)包含了用戶確認(rèn)支付分免押和支付回調(diào)纫塌,
用戶確認(rèn)即可執(zhí)行業(yè)務(wù)操作诊县,例如:使用免押充電寶的彈出,使用共享單車的開鎖等措左。
支付回調(diào)則需要根據(jù)扣款金額校驗(yàn)依痊,微信API都是以分為單位
使用傳輸時(shí)乘以100,使用BigDecimal.multiply(new BigDecimal(100)).setScale(0)怎披;
解密時(shí)除以100胸嘁,使用BigDecimal.divide(new BigDecimal(100));
小數(shù)點(diǎn)可以自己控制,如果使用int或double容易造成精度丟失凉逛,涉及金錢務(wù)必使用BigDecimal性宏;
另外如有扣費(fèi)需要存儲(chǔ)扣費(fèi)憑證(交易單號(hào),支付分API使用基礎(chǔ)的微信退款)状飞,包裹了很多層
json數(shù)據(jù)為解密后的支付訂單回調(diào)數(shù)據(jù)毫胜;
JSONObject collection = JSONObject.parseObject(JSONObject.toJSONString(json.get("collection")));
JSONArray details = JSONObject.parseArray(collection.getString("details"));
String finish_transaction_id =null;
if (details.size() ==1) {
for (Object de : details) {
JSONObject jsons = JSONObject.parseObject(JSONObject.toJSONString(de));
? ? ? ? finish_transaction_id = jsons.getString("transaction_id");
? ? }
}
再把finish_transaction_id存儲(chǔ)书斜;