為了在保證支付安全的前提下,帶給商戶簡(jiǎn)單、一致且易用的開發(fā)體驗(yàn),我們推出了全新的微信支付APIv3接口。該版本API的具體規(guī)則請(qǐng)參考“APIv3接口規(guī)則”
為了幫助開發(fā)者調(diào)用開放接口,我們提供了Java、PHP、GO語(yǔ)言版本的開發(fā)庫(kù),封裝了簽名生成、簽名驗(yàn)證、敏感信息加/解密、媒體文件上傳等基礎(chǔ)功能
文檔展示了如何使用微信支付服務(wù)端 SDK 快速接入掃碼支付產(chǎn)品,完成與微信支付對(duì)接的部分。
? 文檔中的代碼示例是用來(lái)闡述 API 基本使用方法,代碼中的示例參數(shù)需替換成商戶自己賬號(hào)及請(qǐng)求參數(shù)才能跑通。
? 以下接入步驟僅提供參考,請(qǐng)商戶結(jié)合自身業(yè)務(wù)需求進(jìn)行評(píng)估、修改。
步驟說(shuō)明:通過本接口提交微信支付H5支付訂單,獲取微信支付跳轉(zhuǎn)鏈接mweb_url。
代碼示例
@Test
//Call Unified Order API
public void unifiedOrderTest() throws IOException {
String unifiedOrderBody = String.join("\n" ,
"{" ,
"'sp_appid': 'wx2421b1c4370ec43b'," ,
"'sp_mchid': '10000100'," ,
"'sub_mchid': '20000100'," ,
"'out_trade_no': '20150806125346'," ,
"'merchant_category_code': '1011'," ,
"'notify_url': 'https://wxpay.wxutil.com/pub_v2/pay/notify.v2.php'," ,
"'trade_type': 'MWEB'," ,
"'amount': {" ,
"'total': 10000," ,
"'currency': 'HKD'" ,
"}," ,
"'attach': 'Payment test'," ,
"'description': 'In-APP Pay test'," ,
"'goods_tag': '," ,
"'detail': {" ,
"'cost_price': 10000," ,
"'receipt_id': '1234'," ,
"'goods_detail': [{" ,
"'goods_id': 'iphone6s_16G'," ,
"'wxpay_goods_id': '1001'," ,
"'goods_name': 'iPhone6s 16G'," ,
"'quantity': 1," ,
"'price': 528800" ,
"}]" ,
"}," ,
"'scene_info': {" ,
"'payer_client_ip': '14.23.150.211'," ,
"'device_ip': '59.37.125.32'," ,
"'device_id': '013467007045764'," ,
"'operator_id': 'P001'," ,
"'store_info': {" ,
"'id': 'SZTX001'" ,
"}" ,
"}" ,
"}").replace("'","\"");
HttpPost httpPost = new HttpPost("https://apihk.mch.weixin.qq.com/v3/global/transactions/mweb");
httpPost.addHeader("Accept", "application/json");
httpPost.addHeader("Content-type", "application/json; charset=utf-8");
httpPost.setEntity(new StringEntity(unifiedOrderBody));
CloseableHttpResponse response = httpClient.execute(httpPost);
//Process the response
}
重要參數(shù):
out_trade_no: 商戶系統(tǒng)內(nèi)部訂單號(hào)
notify_url: 接受異步支付結(jié)果回調(diào)通知的地址,通知url必須為外網(wǎng)可訪問的url,不能攜帶參數(shù)。請(qǐng)使用https協(xié)議鏈接
其他重要參數(shù)請(qǐng)前往H5支付下單API文檔頁(yè)面參考。
步驟說(shuō)明:商戶在用戶下單一定時(shí)間后,需主動(dòng)進(jìn)行查單以確認(rèn)訂單狀態(tài)。
代碼示例
@Test
//Call query order API
public void queryOrderTest() throws IOException {
HttpGet httpGet = new HttpGet("https://apihk.mch.weixin.qq.com/v3/global/transactions/id/" +
"4200123456789000?sub_mchid=100012321&sp_mchid=1900000000");
httpGet.addHeader("Accept", "application/json");
httpGet.addHeader("Content-type", "application/json; charset=utf-8");
CloseableHttpResponse response = httpClient.execute(httpGet);
//Process the response
}
重要參數(shù):
id: 微信支付訂單號(hào)
out_trade_no:商戶內(nèi)部訂單號(hào)
可以用上述任一訂單號(hào)進(jìn)行查詢。其他重要參數(shù)請(qǐng)前往查詢訂單API文檔頁(yè)面參考。
步驟說(shuō)明:支付完成支付狀態(tài)為SUCCESS后,可以調(diào)用該接口提交退款請(qǐng)求。
代碼示例
@Test
//Call Refund API
public void refundTest() throws IOException {
String refundBody = String.join("\n" ,
"{" ,
"'sp_appid': 'wx2421b1c4370ec43b', " ,
"'sp_mchid': '10000100'," ,
"'sub_mchid': '20000100'," ,
"'transaction_id': '1008450740201411110005820873'," ,
"'out_refund_no': 'R20150806125346'," ,
" 'amount' : {" ,
" 'refund': 5," ,
" 'total':10," ,
" 'currency':'HKD'" ,
" }," ,
" 'reason': 'The item has been sold out.'," ,
" 'source': 'REFUND_SOURCE_UNSETTLED_FUNDS'" ,
"}").replace("'","\"");
HttpPost httpPost = new HttpPost("https://apihk.mch.weixin.qq.com/v3/global/refunds");
httpPost.addHeader("Accept", "application/json");
httpPost.addHeader("Content-type", "application/json; charset=utf-8");
httpPost.setEntity(new StringEntity(refundBody));
CloseableHttpResponse response = httpClient.execute(httpPost);
//Process the response
}
重要參數(shù):
out_trade_no: 商戶內(nèi)部訂單號(hào)
transaction_id: 微信訂單號(hào)
out_refund_no: 商戶內(nèi)部退款單號(hào),應(yīng)與訂單號(hào)一一對(duì)應(yīng)
notify_url: 退款結(jié)果接收地址
其他重要參數(shù)請(qǐng)前往申請(qǐng)退款A(yù)PI文檔頁(yè)面參考。
步驟說(shuō)明:提交退款申請(qǐng)后,通過調(diào)用該接口查詢退款狀態(tài)。
代碼示例
@Test
//Call Query Refund API
public void querySingleRefundTest() throws IOException {
HttpGet httpGet = new HttpGet("https://apihk.mch.weixin.qq.com/v3/global/refunds/out-refund-no/RYX001?sub_mchid=100012321&sp_mchid=1900000000");
httpGet.addHeader("Accept", "application/json");
httpGet.addHeader("Content-type", "application/json; charset=utf-8");
CloseableHttpResponse response = httpClient.execute(httpGet);
//Process the response
}
重要參數(shù):
out_trade_no: 商戶內(nèi)部訂單號(hào)
refund_id:微信支付退款單號(hào)
其他重要參數(shù)請(qǐng)前往查詢單筆退款A(yù)PI文檔頁(yè)面參考。
步驟說(shuō)明:提交退款申請(qǐng)后,通過調(diào)用該接口查詢一筆訂單下對(duì)應(yīng)的全部退款信息。
代碼示例
@Test
//Call Query All Refund API
public void queryAllRefundTest() throws IOException {
HttpGet httpGet = new HttpGet("https://apihk.mch.weixin.qq.com/v3/global/refunds" +
"?out_trade_no=YX202111100020&count=10&offset=0&sp_mchid=1900000000&sub_mchid=100012321");
httpGet.addHeader("Accept", "application/json");
httpGet.addHeader("Content-type", "application/json; charset=utf-8");
CloseableHttpResponse response = httpClient.execute(httpGet);
//Process the response
}
重要參數(shù):
out_trade_no: 商戶內(nèi)部訂單號(hào)
transaction_id: 微信訂單號(hào)
offset: 分頁(yè)起始位置
count: 單頁(yè)返回的記錄數(shù),最大20條記錄.
其他重要參數(shù)請(qǐng)前往查詢所有退款A(yù)PI文檔頁(yè)面參考。
步驟說(shuō)明:商戶每天可以通過調(diào)用該接口可以下載歷史交易賬單,通過對(duì)帳單核對(duì)后可以校對(duì)更正支付信息。
代碼示例
@Test
//Downloading Reconciliation API
public void downloadReconTest() throws IOException {
HttpGet httpGet = new HttpGet("https://apihk.mch.weixin.qq.com/v3/global/statements?date=20220401&mchid=1900000000");
httpGet.addHeader("Accept", "application/json");
httpGet.addHeader("Content-type", "application/json; charset=utf-8");
CloseableHttpResponse response = httpClient.execute(httpGet);
//Process the response
}
重要參數(shù):
date: 賬單日期, 格式:20180103
其他重要參數(shù)請(qǐng)前往下載對(duì)賬單API文檔頁(yè)面參考。
步驟說(shuō)明:下單超過5分鐘后,可以調(diào)用該接口對(duì)下單未支付的訂單進(jìn)行關(guān)單操作,以便商戶更換訂單號(hào)重新下單發(fā)起支付或商戶系統(tǒng)退出不再受理后避免用戶繼續(xù)支付。
代碼示例
@Test
//Call close order API
public void closeOrderTest() throws IOException {
String closeBody = String.join("\n" ,
"{" ,
" 'sp_mchid': '10000100'," ,
" 'sub_mchid': '20000100'" ,
"}").replace("'","\"");
HttpPost httpPost = new HttpPost("https://apihk.mch.weixin.qq.com/v3/global/transactions/out-trade-no/YX001/close");
httpPost.addHeader("Accept", "application/json");
httpPost.addHeader("Content-type", "application/json; charset=utf-8");
httpPost.setEntity(new StringEntity(closeBody));
CloseableHttpResponse response = httpClient.execute(httpPost);
System.out.println(response.getStatusLine().getStatusCode());
}
重要參數(shù):
out_trade_no: 商戶內(nèi)部訂單號(hào)
transaction_id: 微信支付訂單號(hào)
可以用上述任一訂單號(hào)進(jìn)行查詢。其他重要參數(shù)請(qǐng)前往關(guān)閉訂單API文檔頁(yè)面參考。
步驟說(shuō)明:在調(diào)用其他接口之前,需要調(diào)用該接口下載平臺(tái)證書用于對(duì)返回消息進(jìn)行驗(yàn)簽和返回消息中的加密字段進(jìn)行解密。
代碼示例
@Test
//Call certificate downloading API
public void certDownloadingTest() throws IOException {
HttpGet httpGet = new HttpGet("https://apihk.mch.weixin.qq.com/v3/global/certificates");
httpGet.addHeader("Accept", "application/json");
httpGet.addHeader("Content-type", "application/json; charset=utf-8");
CloseableHttpResponse response = httpClient.execute(httpGet);
//Process the response
//Get the response body: EntityUtils.toString(response.getEntity());
//Get the response status code: response.getStatusLine().getStatusCode();
//Instead of calling the API to download platform certificate,
//We also recommend use the certificateMenager to get the valid certificate
verifier.getValidCertificate();
}
重要參數(shù):無(wú)
其他重要參數(shù)請(qǐng)前往下載平臺(tái)證書API文檔頁(yè)面參考。
步驟說(shuō)明:用戶完成支付后,微信支付會(huì)向下單時(shí)傳入的notify_url推送支付結(jié)果通知,商戶需要在接收到通知后返回對(duì)應(yīng)的信息。
? 同樣的通知可能會(huì)多次發(fā)送給商戶系統(tǒng)。商戶系統(tǒng)必須能夠正確處理重復(fù)的通知。 推薦的做法是,當(dāng)商戶系統(tǒng)收到通知進(jìn)行處理時(shí),先檢查對(duì)應(yīng)業(yè)務(wù)數(shù)據(jù)的狀態(tài),并判斷該通知是否已經(jīng)處理。如果未處理,則再進(jìn)行處理;如果已處理,則直接返回結(jié)果成功。在對(duì)業(yè)務(wù)數(shù)據(jù)進(jìn)行狀態(tài)檢查和處理之前,要采用數(shù)據(jù)鎖進(jìn)行并發(fā)控制,以避免函數(shù)重入造成的數(shù)據(jù)混亂。
? 如果在所有通知頻率(4小時(shí))后沒有收到微信側(cè)回調(diào),商戶應(yīng)調(diào)用查詢訂單接口確認(rèn)訂單狀態(tài)。
特別提醒:機(jī)構(gòu)系統(tǒng)對(duì)于支付結(jié)果通知的內(nèi)容一定要做簽名驗(yàn)證,并校驗(yàn)返回的訂單金額是否與商戶側(cè)的訂單金額一致,防止數(shù)據(jù)泄露導(dǎo)致出現(xiàn)“假通知”,造成資金損失。
用戶支付完成后,微信會(huì)把相關(guān)支付結(jié)果和用戶信息發(fā)送給商戶,商戶需要接收處理后返回應(yīng)答成功。只有支付成功才會(huì)通知。
對(duì)后臺(tái)通知交互時(shí),如果微信收到應(yīng)答不是成功或超時(shí),微信認(rèn)為通知失敗,微信會(huì)通過一定的策略定期重新發(fā)起通知,盡可能提高通知的成功率,但微信不保證通知最終能成功。 (通知頻率為15s/15s/30s/3m/10m/20m/30m/30m/30m/60m/3h/3h/3h/6h/6h - 總計(jì) 24h4m)
支付結(jié)果通知是以“POST”方法訪問商戶設(shè)置的通知url,通知的數(shù)據(jù)以“JSON”格式通過請(qǐng)求主體(BODY)傳輸。通知的數(shù)據(jù)包括了加密的支付結(jié)果詳情。
下面詳細(xì)描述證書解密的流程
1、從商戶平臺(tái)上獲取商戶的密鑰,記為“key”。
2、針對(duì)“algorithm”中描述的算法(目前為AEAD_AES_256_GCM),取得對(duì)應(yīng)的參數(shù)“nonce”和“associated_data”。
3、使用“key”、“nonce”和“associated_data”對(duì)數(shù)據(jù)密文“ciphertext”進(jìn)行解密(需要先對(duì)ciphertext做base64解碼,然后再解密),得到證書內(nèi)容
加密不能保證通知請(qǐng)求來(lái)自微信。微信會(huì)對(duì)發(fā)送給商戶的通知進(jìn)行簽名,并將簽名值放在通知的HTTP頭Wechatpay-Signature。商戶應(yīng)當(dāng)驗(yàn)證簽名,以確認(rèn)請(qǐng)求來(lái)自微信,而不是其他的第三方。簽名驗(yàn)證的算法請(qǐng)參考《微信支付API V3簽名驗(yàn)證》。
支付成功結(jié)果通知
{
"id":"EV-2018022511223320873",
"create_time":"20180225112233",
"resource_type":"encrypt-resource",
"event_type":"TRANSACTION.SUCCESS",
"resource" : {
"algorithm":"AEAD_AES_256_GCM",
"ciphertext": "...",
"nonce": "...",
"associated_data": ""
}
}
商戶對(duì)resource對(duì)象進(jìn)行解密后,得到的資源對(duì)象示例
{
"id": "1008450740201411110005820873",
"sp_appid": "wx2421b1c4370ec43b",
"sp_mchid": "10000100",
"sub_mchid": "20000100",
"out_trade_no": "20150806125346",
"payer": {
"sp_openid": "oUpF8uN95-Ptaags6E_roPHg7AG0"
},
"amount" : {
"total": 528800,
"currency": "HKD",
"payer_total": 518799,
"payer_currency": "CNY",
"exchange_rate" : {
"type": "SETTLEMENT_RATE",
"rate": 8000000
}
},
"trade_type": "MICROPAY",
"trade_state": "SUCCESS",
"trade_state_desc": "支付成功",
"bank_type": "CCB_DEBIT",
"attach": "支付測(cè)試",
"success_time": "2018-06-08T10:34:56+08:00",
"promotion_detail":[
{
"promotion_id":"109519",
"name":"單品惠-6",
"scope":"SINGLE",
"type":"DISCOUNT",
"amount":1,
"currency":"HKD",
"activity_id":"931386",
"wechatpay_contribute_amount":1,
"merchant_contribute_amount":0,
"other_contribute_amount":0,
"goods_detail":[
{
"goods_id":"iphone6s_16G",
"goods_remark":"商品備注",
"quantity":1,
"price":528800
}
]
}
]
}
支付通知http應(yīng)答碼為200或204才會(huì)當(dāng)作正常接收,當(dāng)回調(diào)處理異常時(shí),應(yīng)答的HTTP狀態(tài)碼應(yīng)為500,或者4xx。
其他重要參數(shù)請(qǐng)前往支付結(jié)果通知API文檔頁(yè)面參考。
步驟說(shuō)明:退款狀態(tài)改變后,微信會(huì)把相關(guān)退款結(jié)果發(fā)送給商戶。
? 同樣的通知可能會(huì)多次發(fā)送給商戶系統(tǒng)。商戶系統(tǒng)必須能夠正確處理重復(fù)的通知。 推薦的做法是,當(dāng)商戶系統(tǒng)收到通知進(jìn)行處理時(shí),先檢查對(duì)應(yīng)業(yè)務(wù)數(shù)據(jù)的狀態(tài),并判斷該通知是否已經(jīng)處理。如果未處理,則再進(jìn)行處理;如果已處理,則直接返回結(jié)果成功。在對(duì)業(yè)務(wù)數(shù)據(jù)進(jìn)行狀態(tài)檢查和處理之前,要采用數(shù)據(jù)鎖進(jìn)行并發(fā)控制,以避免函數(shù)重入造成的數(shù)據(jù)混亂。
? 如果在所有通知頻率(4小時(shí))后沒有收到微信側(cè)回調(diào),商戶應(yīng)調(diào)用查詢訂單接口確認(rèn)訂單狀態(tài)。
特別提醒:機(jī)構(gòu)系統(tǒng)對(duì)于支付結(jié)果通知的內(nèi)容一定要做簽名驗(yàn)證,并校驗(yàn)返回的訂單金額是否與商戶側(cè)的訂單金額一致,防止數(shù)據(jù)泄露導(dǎo)致出現(xiàn)“假通知”,造成資金損失。
退款狀態(tài)改變后,微信會(huì)把相關(guān)退款結(jié)果發(fā)送給商戶。
對(duì)后臺(tái)通知交互時(shí),如果微信收到應(yīng)答不是成功或超時(shí),微信認(rèn)為通知失敗,微信會(huì)通過一定的策略定期重新發(fā)起通知,盡可能提高通知的成功率,但微信不保證通知最終能成功。 (通知頻率為15s/15s/30s/3m/10m/20m/30m/30m/30m/60m/3h/3h/3h/6h/6h - 總計(jì) 24h4m)
退款結(jié)果通知是以“POST”方法訪問商戶設(shè)置的通知url,通知的數(shù)據(jù)以“JSON”格式通過請(qǐng)求主體(BODY)傳輸。通知的數(shù)據(jù)包括了加密的退款結(jié)果詳情。
下面詳細(xì)描述證書解密的流程
1、從商戶平臺(tái)上獲取商戶的密鑰,記為“key”。
2、針對(duì)“algorithm”中描述的算法(目前為AEAD_AES_256_GCM),取得對(duì)應(yīng)的參數(shù)“nonce”和“associated_data”。
3、使用“key”、“nonce”和“associated_data”對(duì)數(shù)據(jù)密文“ciphertext”進(jìn)行解密(需要先對(duì)ciphertext做base64解碼,然后再解密),得到證書內(nèi)容
加密不能保證通知請(qǐng)求來(lái)自微信。微信會(huì)對(duì)發(fā)送給商戶的通知進(jìn)行簽名,并將簽名值放在通知的HTTP頭Wechatpay-Signature。商戶應(yīng)當(dāng)驗(yàn)證簽名,以確認(rèn)請(qǐng)求來(lái)自微信,而不是其他的第三方。簽名驗(yàn)證的算法請(qǐng)參考《微信支付API V3簽名驗(yàn)證》。
退款通知
{
"id": "EV-2018022511223320873",
"create_time": "2018-06-08T10:34:56+08:00",
"resource_type": "encrypt-resource",
"event_type": "REFUND.SUCCESS",
"summary": "退款成功",
"resource": {
"original_type": "refund",
"algorithm": "AEAD_AES_256_GCM",
"ciphertext": "...",
"associated_data": "",
"nonce": "..."
}
}
商戶對(duì)resource對(duì)象進(jìn)行解密后,得到的資源對(duì)象示例
{
"sp_mchid": "1900000100",
"sub_mchid": "1900000109",
"transaction_id": "1008450740201411110005820873",
"out_trade_no": "20150806125346",
"refund_id": "50200207182018070300011301001",
"out_refund_no": "7752501201407033233368018",
"refund_status": "SUCCESS",
"success_time": "2018-06-08T10:34:56+08:00",
"recv_account": "招商銀行信用卡0403",
"fund_source": "REFUND_SOURCE_UNSETTLED_FUNDS",
"amount" : {
"total": 528800,
"currency": "HKD",
"refund": 528800,
"payer_total": 528800,
"payer_refund": 528800,
"payer_currency": "HKD",
"exchange_rate" : {
"type": "SETTLEMENT_RATE",
"rate": 100000000
}
}
}
退款通知http應(yīng)答碼為200或204才會(huì)當(dāng)作正常接收,當(dāng)回調(diào)處理異常時(shí),應(yīng)答的HTTP狀態(tài)碼應(yīng)為500,或者4xx。
其他重要參數(shù)請(qǐng)前往退款通知API文檔頁(yè)面參考。
步驟說(shuō)明:商戶在交易完結(jié)之后,可按結(jié)算日期查詢已結(jié)算資金明細(xì)(sette_state為SETTLED),也可以查詢未結(jié)算資金明細(xì)(sette_state為UNSETTLE)。
代碼示例
@Test
//Query Settlement API
public void querySettlementTest() throws IOException {
HttpGet httpGet = new HttpGet("https://apihk.mch.weixin.qq.com/v3/global/settle/settlements" +
"?sub_mchid=100012321&settle_state=SETTLED&settle_start_date=20221225" +
"&settle_end_date=20221226&offset=10&limit=5");
httpGet.addHeader("Accept", "application/json");
httpGet.addHeader("Content-type", "application/json; charset=utf-8");
CloseableHttpResponse response = httpClient.execute(httpGet);
//Process the response
}
重要參數(shù):
settle_state: 資金結(jié)算狀態(tài),枚舉值:
SETTLED:已結(jié)算
UNSETTLE:未結(jié)算
其他重要參數(shù)請(qǐng)前往查詢資金結(jié)算明細(xì)API文檔頁(yè)面參考。
H5支付要求商戶在統(tǒng)一下單接口中上傳用戶真實(shí)ip地址“spbill_create_ip”,為保證微信端獲取的用戶ip地址與商戶端獲取的一致,提供了以下獲取用戶ip的指引,希望對(duì)大家有所幫助。
在商戶的前端接入層沒有做代理的情況下獲取ip的方式比較簡(jiǎn)單,直接獲取'REMOTE_ADDR '即可。
在有代理的情況下,因?yàn)橐婵蛻舳巳ピL問服務(wù)器,所以,當(dāng)請(qǐng)求包經(jīng)過反向代理后,在代理服務(wù)器這里這個(gè)IP數(shù)據(jù)包的IP包頭做了修改,最終后端WEB服務(wù)器得到的數(shù)據(jù)包的頭部源IP地址是代理服務(wù)器的IP地址。這樣一來(lái),后端服務(wù)器的程序就無(wú)法獲取用戶的真實(shí)ip。
nginx有代理的情況:
在nginx中配置中加入
vi /usr/local/apache/conf/httpd.conf
Include conf/extra/httpd-remoteip.conf
vi /usr/local/apache/conf/extra/httpd-remoteip.conf
LoadModule remoteip_module modules/mod_remoteip.so
RemoteIPHeader X-Forwarded-For
RemoteIPinternalProxy 127.0.0.1
Apache有代理的情況:
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-Port $remote_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
代碼示例
string GetClientIp(CgiInput * poInput) {
string client_ip = "";
string strClientIPList;
GetHttpHeader("X-Forwarded-For", strClientIPList);
if (strClientIPList.empty()) {
GetHttpHeader("X-Real-IP", strClientIPList);
}
if (!strClientIPList.empty()) {
size_t iPos = strClientIPList.find(",");
if (iPos != std::string::npos) {
client_ip = strClientIPList.substr(iPos);
} else {
client_ip = strClientIPList;
}
}
if (client_ip.empty()) {
GetHttpHeader("PROXY_FORWARDED_FOR", strClientIPList);
// 做下兼容
if (strClientIPList.empty()) {
client_ip = getRemoteAddr();
} else {
size_t iPos = strClientIPList.find(",");
if (iPos != std::string::npos) {
client_ip = strClientIPList.substr(iPos);
} else {
client_ip = strClientIPList;
}
}
}
if (!MMPayCommFunc::IsIp(client_ip))
client_ip = getRemoteAddr();
return client_ip;
}
正常流程用戶支付完成后會(huì)返回至發(fā)起支付的頁(yè)面,如需返回至指定頁(yè)面,則可以在MWEB_URL后拼接上redirect_url參數(shù),來(lái)指定回調(diào)頁(yè)面。
如您希望用戶支付完成后跳轉(zhuǎn)至https://www.wechatpay.com.cn,則可以做如下處理:
假設(shè)您通過統(tǒng)一下單接口獲到的MWEB_URL= https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx20161110163838f231619da20804912345&package=1037687096
則拼接后的地址為MWEB_URL= https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx20161110163838f231619da20804912345&package=1037687096&redirect_url=https%3A%2F%2Fwww.wechatpay.com.cn
1、需對(duì)redirect_url進(jìn)行urlencode處理;
2、由于設(shè)置redirect_url后,回跳指定頁(yè)面的操作可能發(fā)生在:1,微信支付中間頁(yè)調(diào)起微信收銀臺(tái)后超過5秒 2,用戶點(diǎn)擊“取消支付“或支付完成后點(diǎn)“完成”按鈕。因此無(wú)法保證頁(yè)面回跳時(shí),支付流程已結(jié)束,所以商戶設(shè)置的redirect_url地址不能自動(dòng)執(zhí)行查單操作,應(yīng)讓用戶去點(diǎn)擊按鈕觸發(fā)查單操作。回跳頁(yè)面展示效果可參考下圖。
問題 | 問題說(shuō)明 | 解決方案 |
---|---|---|
網(wǎng)絡(luò)環(huán)境未能通過安全驗(yàn)證,請(qǐng)稍后再試 | 1. 商戶側(cè)統(tǒng)一下單傳的終端IP(spbill_create_ip)與用戶實(shí)際調(diào)起支付時(shí)微信側(cè)檢測(cè)到的終端IP不一致導(dǎo)致的,這個(gè)問題一般是商戶在統(tǒng)一下單時(shí)沒有傳遞正確的終端IP到spbill_create_ip導(dǎo)致,詳細(xì)可參見客戶端ip獲取指引 2. 統(tǒng)一下單與調(diào)起支付時(shí)的網(wǎng)絡(luò)有變動(dòng),如統(tǒng)一下單時(shí)是WIFI網(wǎng)絡(luò),下單成功后切換成4G網(wǎng)絡(luò)再調(diào)起支付,這樣可能會(huì)引發(fā)我們的正常攔截,請(qǐng)保持網(wǎng)絡(luò)環(huán)境一致的情況下重新發(fā)起支付流程 |
|
商家參數(shù)格式有誤,請(qǐng)聯(lián)系商家解決 | 1. 當(dāng)前調(diào)起H5支付的referer為空導(dǎo)致,一般是因?yàn)橹苯釉L問頁(yè)面調(diào)起H5支付,請(qǐng)按正常流程進(jìn)行頁(yè)面跳轉(zhuǎn)后發(fā)起支付,或自行抓包確認(rèn)referer值是否為空
2. 如果是APP里調(diào)起H5支付,需要在webview中手動(dòng)設(shè)置referer,如(
Map extraHeaders = new HashMap(); |
|
商家存在未配置的參數(shù),請(qǐng)聯(lián)系商家解決 | 1,當(dāng)前調(diào)起H5支付的域名(微信側(cè)從referer中獲取)與申請(qǐng)H5支付時(shí)提交的授權(quán)域名不一致,如需添加或修改授權(quán)域名,請(qǐng)登錄商戶號(hào)對(duì)應(yīng)的商戶平臺(tái),進(jìn)入Development Configuration菜單,在Payment Authorization Config區(qū)域?qū)uthorized Domain進(jìn)行配置。 2,如果設(shè)置了回跳地址redirect_url,請(qǐng)確認(rèn)設(shè)置的回跳地址的域名與申請(qǐng)H5支付時(shí)提交的授權(quán)域名是否一致 |
|
支付請(qǐng)求已失效,請(qǐng)重新發(fā)起支付 | 統(tǒng)一下單返回的MWEB_URL生成后,有效期為5分鐘,如超時(shí)請(qǐng)重新生成MWEB_URL后再發(fā)起支付 | |
請(qǐng)?jiān)谖⑿磐獯蜷_訂單,進(jìn)行支付 | H5支付不能直接在微信客戶端內(nèi)調(diào)起,請(qǐng)?jiān)谕獠繛g覽器調(diào)起 | |
IOS:簽名驗(yàn)證失敗 安卓:系統(tǒng)繁忙,請(qǐng)稍后再試 |
1,請(qǐng)確認(rèn)同一個(gè)MWEB_URL只被一個(gè)微信號(hào)調(diào)起,如果不同微信號(hào)調(diào)起請(qǐng)重新下單生成新的MWEB_URL
2,如MWEB_URL有添加redirect_url,請(qǐng)確認(rèn)參數(shù)拼接格式是否有誤,是否有對(duì)redirect_url的值做urlencode,可對(duì)比以下例子格式: https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx20161110163838f231619da20804912345&package=1037687096& |
Customer Service Tel
Business Development
9:00-18:00
Monday-Friday GMT+8
Technical Support
WeChat Pay Global
ICP證