參考阿里云文檔:https://docs.open.alipay.com/203/105285/
1.調(diào)用流程
手機(jī)網(wǎng)站支付產(chǎn)品包含兩類API:
- 頁面跳轉(zhuǎn)類:需要從前端頁面以Form表單的形式發(fā)起請求,瀏覽器會(huì)自動(dòng)跳轉(zhuǎn)至支付寶的相關(guān)頁面(一般是收銀臺或簽約頁面),用戶在該頁面完成相關(guān)業(yè)務(wù)操作后再回跳到商戶指定頁面。例如本產(chǎn)品中的手機(jī)網(wǎng)站支付接口alipay.trade.wap.pay。
- 系統(tǒng)調(diào)用類:直接從服務(wù)端發(fā)起HTTP請求,支付寶會(huì)同步返回請求結(jié)果。例如本產(chǎn)品中的交易查詢等配套API。
調(diào)用流程: - 如上圖所示,用戶在商戶的H5網(wǎng)站下單支付后,商戶系統(tǒng)按照手機(jī)網(wǎng)站支付接口alipay.trade.wap.payAPI的參數(shù)規(guī)范生成訂單數(shù)據(jù),然后在前端頁面通過Form表單的形式請求到支付寶。此時(shí)支付寶會(huì)自動(dòng)將頁面跳轉(zhuǎn)至支付寶H5收銀臺頁面,如果用戶手機(jī)上安裝了支付寶APP,則自動(dòng)喚起支付寶APP。開發(fā)者需要關(guān)注安裝了支付寶和未安裝支付寶的兩種測試場景,對于在手機(jī)瀏覽器喚起H5頁面的模式下,如果安裝了支付寶卻沒有喚起,大部分原因是當(dāng)前瀏覽器不在支付寶配置的白名單內(nèi)。
- 對于商戶app內(nèi)嵌webview中的支付場景,建議集成支付寶App支付產(chǎn)品?;蛘吣梢允褂檬謾C(jī)網(wǎng)站支付轉(zhuǎn)Native支付的方案,不建議在您的APP中直接接入手機(jī)網(wǎng)站支付。
- 用戶在支付寶APP或H5收銀臺完成支付后,會(huì)根據(jù)商戶在手機(jī)網(wǎng)站支付API中傳入的前臺回跳地址return_url自動(dòng)跳轉(zhuǎn)回商戶頁面,同時(shí)在URL請求中以Query String的形式附帶上支付結(jié)果參數(shù),詳細(xì)回跳參數(shù)見“手機(jī)網(wǎng)站支付接口alipay.trade.wap.pay”前臺回跳參數(shù)。
注意:在ios系統(tǒng)中,喚起支付寶App支付完成后,不會(huì)自動(dòng)回到瀏覽器或商戶APP。用戶可手工切回到瀏覽器或商戶APP;支付寶H5收銀臺會(huì)自動(dòng)跳轉(zhuǎn)回商戶return_url指定的頁面。
- 支付寶還會(huì)根據(jù)原始支付API中傳入的異步通知地址notify_url,通過POST請求的形式將支付結(jié)果作為參數(shù)通知到商戶系統(tǒng),詳情見支付結(jié)果異步通知。
- 除了正向支付流程外,支付寶也提供交易查詢、關(guān)閉、退款、退款查詢以及對賬等配套API。
特別注意:
- 由于前臺回跳的不可靠性,前臺回跳只能作為商戶支付結(jié)果頁的入口,最終支付結(jié)果必須以異步通知或查詢接口返回為準(zhǔn),不能依賴前臺回跳。
- 商戶系統(tǒng)接收到異步通知以后,必須通過驗(yàn)簽(驗(yàn)證通知中的sign參數(shù))來確保支付通知是由支付寶發(fā)送的。詳細(xì)驗(yàn)簽規(guī)則參考異步通知驗(yàn)簽。
- 接受到異步通知并驗(yàn)簽通過后,一定要檢查通知內(nèi)容,包括通知中的app_id, out_trade_no, total_amount是否與請求中的一致,并根據(jù)trade_status進(jìn)行后續(xù)業(yè)務(wù)處理
2.環(huán)境接入
2.1SDK包下載:
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.3.0.ALL</version>
</dependency>
2.2公私鑰文件配置
3.沙箱測試
沙箱環(huán)境提供測試賬戶:買家賬號,商戶賬戶??勺孕谐渲?/p>
3.1java后端發(fā)送支付請求:
@RequestMapping("/pay")
public void pay(HttpServletResponse response, String amount) {
String form = null;
try {
form = PayUtil.pay(amount);
} catch (AlipayApiException e) {
form = "pay error!";
e.printStackTrace();
}
response.setContentType("text/html;charset=" + "utf-8");
try {
response.getWriter().write(form);//直接將完整的表單html輸出到頁面
response.getWriter().flush();
response.getWriter().close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static String pay(String amount) throws AlipayApiException {
AlipayClient alipay_client = new DefaultAlipayClient(server_url, app_id, private_key, format, charset, alipay_pubic_key, sign_type);
AlipayTradeWapPayRequest alipay_request = new AlipayTradeWapPayRequest();
AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
model.setOutTradeNo(getOutOrderNo());
model.setSubject(subject);
model.setTotalAmount(amount);
model.setTimeoutExpress(timeout_express);
model.setProductCode(product_code);
alipay_request.setBizModel(model);
// 設(shè)置異步通知地址
alipay_request.setNotifyUrl(notify_url);
// 設(shè)置同步地址
alipay_request.setReturnUrl(return_url);
// 調(diào)用SDK生成表單
AlipayResponse alipay_response = alipay_client.pageExecute(alipay_request);
String form = alipay_response.getBody();
System.out.println(alipay_response.isSuccess() + ":" + form);
return form;
}
后端向支付寶發(fā)送支付請求,SDK將根據(jù)私鑰內(nèi)容對請求進(jìn)行簽名,支付寶根據(jù)提前配置的公鑰進(jìn)行驗(yàn)簽通過后響應(yīng)。返回的字符內(nèi)容前端以H5的形式展示,依據(jù)內(nèi)容來看form表單自動(dòng)提交至支付寶付款界面。登錄之前的沙箱買家賬戶進(jìn)行支付即可。
3.2支付回調(diào)接口和 結(jié)果頁面回調(diào)接口
@RequestMapping("/notify")
public void alipayNotify(HttpServletRequest request, HttpServletResponse response) throws IOException {
PrintWriter writer = response.getWriter();
//獲取支付寶POST過來反饋信息
Map<String, String> params = new HashMap<String, String>();
Map requestParams = request.getParameterMap();
for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
String name = (String) iter.next();
String[] values = (String[]) requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i]
: valueStr + values[i] + ",";
}
//亂碼解決,這段代碼在出現(xiàn)亂碼時(shí)使用。如果mysign和sign不相等也可以使用這段代碼轉(zhuǎn)化
//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
params.put(name, valueStr);
}
//獲取支付寶的通知返回參數(shù),可參考技術(shù)文檔中頁面跳轉(zhuǎn)同步通知參數(shù)列表(以下僅供參考)//
String out_trade_no = "";
String trade_no = "";
String trade_status = "";
try {
//商戶訂單號
out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
//支付寶交易號
trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");
//交易狀態(tài)
trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
//獲取支付寶的通知返回參數(shù),可參考技術(shù)文檔中頁面跳轉(zhuǎn)同步通知參數(shù)列表(以上僅供參考)//
//計(jì)算得出通知驗(yàn)證結(jié)果
//boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
boolean verify_result = false;
try {
verify_result = AlipaySignature.rsaCheckV1(params, PayUtil.alipay_pubic_key, PayUtil.charset, "RSA2");
} catch (AlipayApiException e) {
e.printStackTrace();
}
if (verify_result) {//驗(yàn)證成功
//////////////////////////////////////////////////////////////////////////////////////////
//請?jiān)谶@里加上商戶的業(yè)務(wù)邏輯程序代碼
System.out.println("商戶的業(yè)務(wù)邏輯程序代碼-notify:" + out_trade_no + " trade_status:" + trade_status);
//——請根據(jù)您的業(yè)務(wù)邏輯來編寫程序(以下代碼僅作參考)——
if (trade_status.equals("TRADE_FINISHED")) {
//判斷該筆訂單是否在商戶網(wǎng)站中已經(jīng)做過處理
//如果沒有做過處理,根據(jù)訂單號(out_trade_no)在商戶網(wǎng)站的訂單系統(tǒng)中查到該筆訂單的詳細(xì),并執(zhí)行商戶的業(yè)務(wù)程序
//請務(wù)必判斷請求時(shí)的total_fee、seller_id與通知時(shí)獲取的total_fee、seller_id為一致的
//如果有做過處理,不執(zhí)行商戶的業(yè)務(wù)程序
System.out.println("TRADE_FINISHED");
//注意:
//如果簽約的是可退款協(xié)議,退款日期超過可退款期限后(如三個(gè)月可退款),支付寶系統(tǒng)發(fā)送該交易狀態(tài)通知
//如果沒有簽約可退款協(xié)議,那么付款完成后,支付寶系統(tǒng)發(fā)送該交易狀態(tài)通知。
} else if (trade_status.equals("TRADE_SUCCESS")) {
//判斷該筆訂單是否在商戶網(wǎng)站中已經(jīng)做過處理
//如果沒有做過處理,根據(jù)訂單號(out_trade_no)在商戶網(wǎng)站的訂單系統(tǒng)中查到該筆訂單的詳細(xì),并執(zhí)行商戶的業(yè)務(wù)程序
//請務(wù)必判斷請求時(shí)的total_fee、seller_id與通知時(shí)獲取的total_fee、seller_id為一致的
//如果有做過處理,不執(zhí)行商戶的業(yè)務(wù)程序
System.out.println("TRADE_SUCCESS");
//注意:
//如果簽約的是可退款協(xié)議,那么付款完成后,支付寶系統(tǒng)發(fā)送該交易狀態(tài)通知。
}
//——請根據(jù)您的業(yè)務(wù)邏輯來編寫程序(以上代碼僅作參考)——
//writer.clear();
writer.println("success"); //請不要修改或刪除
//////////////////////////////////////////////////////////////////////////////////////////
} else {//驗(yàn)證失敗
writer.println("fail");
}
}
支付回調(diào)時(shí),首先進(jìn)行驗(yàn)簽操作,驗(yàn)證成功后根據(jù)提供的訂單號,支付狀態(tài)做相應(yīng)的業(yè)務(wù)處理。文章來源:http://www.zghlxwxcb.cn/news/detail-711220.html
@RequestMapping("/returnUrl")
public void alipayReturn(HttpServletRequest request, HttpServletResponse response) throws IOException {
PrintWriter writer = response.getWriter();
//獲取支付寶GET過來反饋信息
Map<String, String> params = new HashMap<String, String>();
Map requestParams = request.getParameterMap();
for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
String name = (String) iter.next();
String[] values = (String[]) requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i]
: valueStr + values[i] + ",";
}
//亂碼解決,這段代碼在出現(xiàn)亂碼時(shí)使用。如果mysign和sign不相等也可以使用這段代碼轉(zhuǎn)化
try {
valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
params.put(name, valueStr);
}
String out_trade_no = "";
String trade_no = "";
try {
//獲取支付寶的通知返回參數(shù),可參考技術(shù)文檔中頁面跳轉(zhuǎn)同步通知參數(shù)列表(以下僅供參考)//
//商戶訂單號
out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
//支付寶交易號
trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
System.out.println("商戶的業(yè)務(wù)邏輯程序代碼-return_url:" + out_trade_no);
//獲取支付寶的通知返回參數(shù),可參考技術(shù)文檔中頁面跳轉(zhuǎn)同步通知參數(shù)列表(以上僅供參考)//
//計(jì)算得出通知驗(yàn)證結(jié)果
//boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
boolean verify_result = false;
try {
verify_result = AlipaySignature.rsaCheckV1(params, PayUtil.alipay_pubic_key, PayUtil.charset, "RSA2");
} catch (AlipayApiException e) {
e.printStackTrace();
}
if (verify_result) {//驗(yàn)證成功
//////////////////////////////////////////////////////////////////////////////////////////
//請?jiān)谶@里加上商戶的業(yè)務(wù)邏輯程序代碼
//該頁面可做頁面美工編輯
//out.clear();
writer.println("check success<br />");
//——請根據(jù)您的業(yè)務(wù)邏輯來編寫程序(以上代碼僅作參考)——
//////////////////////////////////////////////////////////////////////////////////////////
} else {
//該頁面可做頁面美工編輯
//out.clear();
writer.println("check fail");
}
}
結(jié)果頁面回調(diào)時(shí),首先進(jìn)行驗(yàn)簽操作,驗(yàn)證成功后根據(jù)提供的訂單號,做相應(yīng)的業(yè)務(wù)處理,并可以控制跳轉(zhuǎn)的結(jié)果頁面。文章來源地址http://www.zghlxwxcb.cn/news/detail-711220.html
到了這里,關(guān)于支付寶手機(jī)網(wǎng)站支付接入(沙箱環(huán)境)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!