支付宝异步通知 java_java 支付宝支付 手机网站支付结果异步通知
對于手機網站支付產生的交易,支付寶會根據原始支付API中傳入的異步通知地址notify_url,通過POST請求的形式將支付結果作為參數通知到商戶系統。
支付寶開發文檔:https://docs.open.alipay.com/203/105286/
這邊博客講的1.8后臺通知支付結果 notify_url
image.png
這個環節的業務邏輯處理為:收到支付寶的回調結果通知,先進行簽名校驗,如果簽名校驗結果是對的,然后進行自己的業務邏輯處理(比如輯比如更新訂單支付信息成功,保存交易流水,修改訂單狀態);
當然支付寶的官方文檔還推薦在驗簽通過之后還需要查詢這個支付單號在支付寶服務器的支付結果是否為成功,以這個結果為準;然后再進行支付成功后的業務邏輯處理。主要是為了防止數據篡改和數據的冪等性處理。
項目中的具體代碼實現:
controller層的處理:
/**
* @param request:
* @param response:
* @return java.lang.String
* @Description 支付寶回調
* @Author huangkeyuan
* @Date 16:24 2019-12-11
*/
@PostMapping("notify")
@ApiOperation("支付寶支付回調,修改訂單支付狀態")
public String aliPayCertNotify(HttpServletRequest request, HttpServletResponse response) throws IOException {
Map returnMap = new HashMap<>();
//獲取支付寶POST過來反饋信息轉換為Entry
Set> entries = request.getParameterMap().entrySet();
// 遍歷
for (Map.Entry entry : entries) {
String key = entry.getKey();
StringBuffer value = new StringBuffer("");
String[] val = entry.getValue();
if (null != val && val.length > 0) {
for (String v : val) {
value.append(v);
}
}
returnMap.put(key, value.toString());
}
log.info("支付寶支付回調,{}", returnMap.toString());
return paymentService.aliPayCertNotify(returnMap);
}
service層中的處理:
/**
* @param requestParams : 回調參數
* @return java.lang.String
* @Description 支付寶回調(公鑰證書方式)
* @Author huangkeyuan
* @Date 16:34 2019-12-09
*/
@PostMapping("alipay/notify")
@Override
public String aliPayCertNotify(@RequestParam Map requestParams) {
log.info(">>>支付寶回調參數:" + requestParams.toString());
Map logMap = new HashMap<>();
try {
// 獲取支付寶的支付key
boolean flag = aliPayService.checkSignature(requestParams);
if (flag) {
log.info(">>>支付寶回調簽名認證成功");
//商戶訂單號
String out_trade_no = requestParams.get("out_trade_no");
//交易狀態
String trade_status = requestParams.get("trade_status");
//交易金額
String amount = requestParams.get("total_amount");
//支付寶交易號
String trade_no = requestParams.get("trade_no");
if ("TRADE_SUCCESS".equals(trade_status) || "TRADE_FINISHED".equals(trade_status)) {
log.info("支付寶回調支付成功,trade_status:{}", trade_status);
/**
* 自己的業務處理
*/
// 執行支付成功后的商城業務邏輯比如更新訂單支付信息成功,保存交易流水,修改訂單狀態
mlogger.info(PaymentStatusCode.ALI_PAY_NOTIFY_SUCCESS_CODE, PaymentStatusCode.ALI_PAY_NOTIFY_SUCCESS_MESSAGE, logMap);
// 修改訂單狀態成功
log.info("支付寶支付回調修改訂單、支付狀態成功,結果碼:" + trade_status + ",支付單號:" + out_trade_no + "支付寶支付單號:" + trade_no);
} else {
log.error("沒有處理支付寶回調業務,支付寶交易狀態:{},params:{}", trade_status, requestParams);
mlogger.info(PaymentStatusCode.ALI_PAY_NOTIFY_SERVER_RESPONSE_VALIDATION_ERRORB_CODE,
PaymentStatusCode.ALI_PAY_NOTIFY_SERVER_RESPONSE_VALIDATION_ERRORB_MESSAGE, logMap);
}
} else {
log.info("支付寶回調簽名認證失敗,signVerified=false, params:{}", requestParams);
mlogger.info(PaymentStatusCode.ALI_PAY_NOTIFY_SERVER_INTERNAL_ERROR_CODE,
PaymentStatusCode.ALI_PAY_NOTIFY_SERVER_INTERNAL_ERROR_MESSAGE, logMap);
return "failure";
}
} catch (Exception e) {
log.error(e.getMessage(), e);
log.info("支付寶回調簽名認證失敗,signVerified=false, params:{}", requestParams);
mlogger.info(PaymentStatusCode.ALI_PAY_NOTIFY_SERVER_INTERNAL_ERROR_CODE,
PaymentStatusCode.ALI_PAY_NOTIFY_SERVER_INTERNAL_ERROR_MESSAGE, logMap, e);
return "failure";
}
return "success";//請不要修改或刪除
}
third-party-service中的處理
/**
* @param requestParams :
* @return boolean
* @Description 收到支付寶的成功回調之后驗證簽名是否正確
* @Author huangkeyuan
* @Date 17:01 2019-12-12
*/
@PostMapping("check/signature")
@Override
public boolean checkSignature(Map requestParams) {
try {
String alipaypublickey = this.getAlipayPublicKey(aliPayConfig.getALIPAY_CERT_PATH());
log.info("讀取服務器的支付寶公鑰證書,{}", alipaypublickey);
//切記alipaypublickey是支付寶的公鑰,請去open.alipay.com對應應用下查看。
boolean flag = AlipaySignature.rsaCheckV1(requestParams, alipaypublickey, aliPayConfig.getCHARSET(),
aliPayConfig.getSIGN_TYPE());
return flag;
} catch (Exception e) {
return false;
}
}
遇到的問題
直接打印支付寶返回的參數是這樣的:
支付寶回調參數:{gmt_create=[Ljava.lang.String;@362e073d, charset=[Ljava.lang.String;@1445a60e, seller_email=[Ljava.lang.String;@20f2aa67, subject=[Ljava.lang.String;@30c863fd, sign=[Ljava.lang.String;@76198d36, body=[Ljava.lang.String;@4fd5202d, buyer_id=[Ljava.lang.String;@7a410a22, invoice_amount=[Ljava.lang.String;@965491c, notify_id=[Ljava.lang.String;@33af053b, fund_bill_list=[Ljava.lang.String;@551d8f2b, notify_type=[Ljava.lang.String;@27ff9fb0, trade_status=[Ljava.lang.String;@4f11ffa, receipt_amount=[Ljava.lang.String;@4fbc4482, buyer_pay_amount=[Ljava.lang.String;@76e1ee89, app_id=[Ljava.lang.String;@2d38edfa, sign_type=[Ljava.lang.String;@21ba2968, seller_id=[Ljava.lang.String;@c0ff189, gmt_payment=[Ljava.lang.String;@7563d327, notify_time=[Ljava.lang.String;@1fdeb74c, version=[Ljava.lang.String;@6f5f3cb6, out_trade_no=[Ljava.lang.String;@1c2f1b6d, total_amount=[Ljava.lang.String;@77be0924, trade_no=[Ljava.lang.String;@1db0b448, auth_app_id=[Ljava.lang.String;@b1c81c4, buyer_logon_id=[Ljava.lang.String;@6f8c07b9, point_amount=[Ljava.lang.String;@68fcd445}
需要通過這樣數據處理才能轉換成我們常用的map結構,方便項目中數據分析和使用
Map returnMap = new HashMap<>();
//獲取支付寶POST過來反饋信息轉換為Entry
Set> entries = request.getParameterMap().entrySet();
// 遍歷
for (Map.Entry entry : entries) {
String key = entry.getKey();
StringBuffer value = new StringBuffer("");
String[] val = entry.getValue();
if (null != val && val.length > 0) {
for (String v : val) {
value.append(v);
}
}
returnMap.put(key, value.toString());
}
總結
以上是生活随笔為你收集整理的支付宝异步通知 java_java 支付宝支付 手机网站支付结果异步通知的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 字符设备驱动高级篇3——自动创建字符设备
- 下一篇: 秦时明月1架设用哪个java_秦时明月6