為了在保證支付安全的前提下,帶給商戶簡單、一致且易用的開發(fā)體驗(yàn),我們推出了全新的微信支付APIv3接口。該版本API的具體規(guī)則請參考“APIv3接口規(guī)則”
備注:當(dāng)前接口用于微信國內(nèi)錢包
為了幫助開發(fā)者調(diào)用開放接口,我們提供了JAVA、PHP、GO三種語言版本的開發(fā)庫,封裝了簽名生成、簽名驗(yàn)證、敏感信息加/解密、媒體文件上傳等基礎(chǔ)功能(更多語言版本的開發(fā)庫將在近期陸續(xù)提供)
測試步驟:
1、根據(jù)自身開發(fā)語言,選擇對應(yīng)的開發(fā)庫并構(gòu)建項(xiàng)目,具體配置請參考下面鏈接的詳細(xì)說明:
? wechatpay-java(推薦)wechatpay-apache-httpclient,適用于Java開發(fā)者。
? wechatpay-php(推薦)、wechatpay-guzzle-middleware,適用于PHP開發(fā)者
注:當(dāng)前開發(fā)指引接口PHP示例代碼采用wechatpay-guzzle-middleware版本
? wechatpay-go,適用于Go開發(fā)者
更多資源可前往微信支付開發(fā)者社區(qū)搜索查看
2、創(chuàng)建加載商戶私鑰、加載平臺證書、初始化httpClient的通用方法
@Before
public void setup() throws IOException {
// 加載商戶私鑰(privateKey:私鑰字符串)
PrivateKey merchantPrivateKey = PemUtil
.loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes("utf-8")));
// 加載平臺證書(mchId:商戶號,mchSerialNo:商戶證書序列號,apiV3Key:V3密鑰)
AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
new WechatPay2Credentials(mchId, new PrivateKeySigner(mchSerialNo, merchantPrivateKey)),apiV3Key.getBytes("utf-8"));
// 初始化httpClient
httpClient = WechatPayHttpClientBuilder.create()
.withMerchant(mchId, mchSerialNo, merchantPrivateKey)
.withValidator(new WechatPay2Validator(verifier)).build();
}
@After
public void after() throws IOException {
httpClient.close();
}
3、基于接口的示例代碼,替換請求參數(shù)后可發(fā)起測試
說明:
? 上面的開發(fā)庫為微信支付官方開發(fā)庫,其它沒有審核或者控制下的第三方工具和庫,微信支付不保證它們的安全性和可靠性
通過包管理工具引入SDK后,可根據(jù)下面每個(gè)接口的示例代碼替換相關(guān)參數(shù)后進(jìn)行快速測試
? 開發(fā)者如果想詳細(xì)了解簽名生成、簽名驗(yàn)證、敏感信息加/解密、媒體文件上傳等常用方法的具體代碼實(shí)現(xiàn),可閱讀下面的詳細(xì)說明:
1.簽名生成
3.敏感信息加解密
? 如想更詳細(xì)的了解我們的接口規(guī)則,可查看我們的接口規(guī)則指引文檔
1、微信支付分的相關(guān)配置參數(shù)在商戶入駐的過程中都已經(jīng)配置完成(前往查看配置相關(guān)內(nèi)容),例如授權(quán)結(jié)果回調(diào)url、service_notify_url、測試白名單、免確認(rèn)訂單模式的權(quán)限等。
2、如果發(fā)現(xiàn)配置信息有誤,請主動聯(lián)系微信支付分運(yùn)營同學(xué)協(xié)助修改,或者點(diǎn)擊右側(cè)導(dǎo)航欄進(jìn)入在線技術(shù)客服進(jìn)行技術(shù)咨詢。
重點(diǎn)步驟說明:
步驟1 用戶在商戶側(cè)下單,商戶調(diào)用后臺接口創(chuàng)建支付分訂單,通過接口返回獲得跳轉(zhuǎn)微信支付分小程序進(jìn)行訂單確認(rèn)的必填參數(shù)“package”
我們通過此接口來創(chuàng)建支付分訂單:創(chuàng)建支付分訂單API
步驟2 調(diào)用前端方法跳轉(zhuǎn)至微信,讓用戶完成確認(rèn)訂單操作
我們通過以下前端方法可調(diào)起微信客戶端(注意區(qū)分場景):
步驟3 用戶確認(rèn)訂單完成,商戶系統(tǒng)將收到確認(rèn)訂單回調(diào)通知,此時(shí)可為用戶提供服務(wù);
我們通過以下接口將用戶確認(rèn)訂單信息回調(diào)通知給商戶系統(tǒng):
在用戶確認(rèn)訂單過程中可能出現(xiàn)長時(shí)間未收到回調(diào)、用戶確認(rèn)失敗等情況,商戶可先通過后臺接口查詢訂單狀態(tài):
根據(jù)查詢到的訂單狀態(tài)結(jié)果,商戶可決定是否需要取消當(dāng)前訂單,后臺接口為:
步驟4 用戶服務(wù)結(jié)束,商戶通過后臺接口完結(jié)支付分訂單;
調(diào)用完結(jié)支付分訂單API接口后,微信支付分就會發(fā)起對用戶的扣款,但是在用戶扣款過程中可能會出現(xiàn)一些特殊情況,下面列舉了幾種特殊情況以及對應(yīng)的處理方法,供大家參考:
請求:
? 情況一:扣款過程中,發(fā)現(xiàn)扣款金額有誤(注意:此時(shí)需要訂單為“待支付”狀態(tài))
? 情況二:扣款過程中,用戶通過其它方式完成了支付,希望微信支付分停止繼續(xù)扣款
處理方法:商戶調(diào)用同步服務(wù)訂單信息接口將訂單支付成功狀態(tài)同步給微信支付分,微信支付分將停止繼續(xù)扣款的操作
步驟5 收到用戶扣款成功通知,業(yè)務(wù)流程結(jié)束
通過支付成功回調(diào)通知API接口可以獲取到用戶扣款成功的通知,同時(shí),商戶也可以根據(jù)情況通過查詢支付分訂單API接口主動查詢扣款情況。
如遇到網(wǎng)絡(luò)、服務(wù)器等原因造成無法正常接收扣款成功通知,一般有兩種解決方法:
1.主動查單,通過查詢支付分訂單API 接口主動查詢扣款情況
本文檔展示了如何使用微信支付服務(wù)端 SDK 快速接入微信支付分產(chǎn)品,完成與微信支付對接的部分。
注意:
步驟說明:完成用戶授權(quán)后,即可創(chuàng)建支付分訂單,為用戶提供服務(wù)了。
示例代碼
public void CreateServiceOrder() throws Exception{
//請求URL
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/payscore/serviceorder");
// 請求body參數(shù)
String reqdata = "{"
+ "\"out_order_no\":\"1234323JKHDFE1243252\","
+ "\"appid\":\"wxd678efh567hg6787\","
+ "\"service_id\":\"500001\","
+ "\"service_introduction\":\"某某酒店\","
+ "\"post_payments\": ["
+ "{"
+ "\"name\":\"就餐費(fèi)用服務(wù)費(fèi)\","
+ "\"amount\":4000,"
+ "\"description\":\"就餐人均100元服務(wù)費(fèi):100/小時(shí)\","
+ "\"count\":1"
+ "}"
+ "],"
+ "\"post_discounts\": ["
+ "{"
+ "\"name\":\"滿20減1元\","
+ "\"description\":\"不與其他優(yōu)惠疊加\""
+ "}"
+ "],"
+ "\"time_range\": {"
+ "\"start_time\":\"20091225091010\","
+ "\"end_time\":\"20091225121010\""
+ "},"
+ "\"location\": {"
+ "\"start_location\":\"嗨客時(shí)尚主題展餐廳\","
+ "\"end_location\":\"嗨客時(shí)尚主題展餐廳\""
+ "},"
+ "\"risk_fund\": {"
+ "\"name\":\"ESTIMATE_ORDER_COST\","
+ "\"amount\":10000,"
+ "\"description\":\"就餐的預(yù)估費(fèi)用\""
+ "},"
+ "\"attach\":\"Easdfowealsdkjfnlaksjdlfkwqoi&wl3l2sald\","
+ "\"notify_url\":\"https://api.test.com\","
+ "\"openid\":\"oUpF8uMuAJO_M2pxb1Q9zNjWeS6o\","
+ "\"need_user_confirm\":true"
+ "}";
StringEntity entity = new StringEntity(reqdata,"utf-8");
entity.setContentType("application/json");
httpPost.setEntity(entity);
httpPost.setHeader("Accept", "application/json");
//完成簽名并執(zhí)行請求
CloseableHttpResponse response = httpClient.execute(httpPost);
try {
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) { //處理成功
System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
} else if (statusCode == 204) { //處理成功,無返回Body
System.out.println("success");
} else {
System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
throw new IOException("request failed");
}
} finally {
response.close();
}
}
重要參數(shù)說明:
? 入?yún)ⅰ皀eed_user_confirm”,取值請選擇 “true”;
? 入?yún)ⅰ皉isk_fund:name”,取值請選擇【先免模式】中的枚舉值。
更多參數(shù)、響應(yīng)詳情及錯誤碼請參見創(chuàng)建支付分訂單API接口文檔
微信支付根據(jù)用戶不同的使用場景(APP、小程序、微信內(nèi)H5)分別提供了對應(yīng)跳轉(zhuǎn)確認(rèn)訂單頁的方法,請根據(jù)場景進(jìn)行選擇,詳見跳轉(zhuǎn)確認(rèn)訂單頁API文檔
步驟說明:當(dāng)用戶確認(rèn)訂單時(shí),微信會把相關(guān)信息異步回調(diào)的方式通知商戶,商戶需要接收處理,并按文檔規(guī)范返回應(yīng)答
注意:更多參數(shù)、響應(yīng)詳情及錯誤碼請參見確認(rèn)訂單回調(diào)通知API接口文檔
步驟說明:一般在創(chuàng)建訂單后、訂單完結(jié)成功后等關(guān)鍵流程中,商戶可能有知曉訂單狀態(tài)的需求,此時(shí)即可通過該接口查詢訂單狀態(tài)。
示例代碼:public void GetServiceOrder() throws Exception{
//請求URL
HttpGet httpGet = new HttpGet("https://api.mch.weixin.qq.com/v3/payscore/serviceorder?service_id=500001&out_order_no=8416518464133&appid=wxd678efh567hg6787");
httpGet.setHeader("Accept", "application/json");
//完成簽名并執(zhí)行請求
CloseableHttpResponse response = httpClient.execute(httpGet);
try {
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) { //處理成功
System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
} else if (statusCode == 204) { //處理成功,無返回Body
System.out.println("success");
} else {
System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
throw new IOException("request failed");
}
} finally {
response.close();
}
}
步驟說明:訂單為以下狀態(tài)時(shí)可以取消訂單:CREATED(已創(chuàng)單)、DOING(進(jìn)行中)(包括商戶完結(jié)支付分訂單后,且支付分訂單收款狀態(tài)為待支付USER_PAYING)。
示例代碼:
public void CancelServiceOrder() throws Exception{
//請求URL
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/payscore/serviceorder/{out_order_no}/cancel");
// 請求body參數(shù)
String reqdata = "{"
+ "\"appid\":\"wxd678efh567hg6787\","
+ "\"service_id\":\"500001\","
+ "\"reason\":\"用戶投訴\""
+ "}";
StringEntity entity = new StringEntity(reqdata,"utf-8");
entity.setContentType("application/json");
httpPost.setEntity(entity);
httpPost.setHeader("Accept", "application/json");
//完成簽名并執(zhí)行請求
CloseableHttpResponse response = httpClient.execute(httpPost);
try {
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) { //處理成功
System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
} else if (statusCode == 204) { //處理成功,無返回Body
System.out.println("success");
} else {
System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
throw new IOException("request failed");
}
} finally {
response.close();
}
}
更多參數(shù)、響應(yīng)詳情及錯誤碼請參見 取消支付分訂單API接口文檔
步驟說明:用戶服務(wù)結(jié)束后,商戶通過請求完結(jié)支付分訂單接口,通過微信支付分進(jìn)行用戶扣款操作。
注意:
public void CompleteServiceOrder() throws Exception{
//請求URL
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/payscore/serviceorder/{out_order_no}/complete");
// 請求body參數(shù)
String reqdata = "{"
+ "\"appid\":\"wxd678efh567hg6787\","
+ "\"service_id\":\"500001\","
+ "\"post_payments\": ["
+ "{"
+ "\"name\":\"就餐費(fèi)用服務(wù)費(fèi)\","
+ "\"amount\":4000,"
+ "\"description\":\"就餐人均100元服務(wù)費(fèi):100/小時(shí)\","
+ "\"count\":1"
+ "}"
+ "],"
+ "\"post_discounts\": ["
+ "{"
+ "\"name\":\"滿20減1元\","
+ "\"description\":\"不與其他優(yōu)惠疊加\","
+ "\"amount\":4000"
+ "}"
+ "],"
+ "\"total_amount\":3900,"
+ "\"time_range\": {"
+ "\"start_time\":\"20091225091010\","
+ "\"end_time\":\"20091225121010\""
+ "},"
+ "\"location\": {"
+ "\"end_location\":\"嗨客時(shí)尚主題展餐廳\""
+ "},"
+ "\"profit_sharing\":false"
+ "}";
StringEntity entity = new StringEntity(reqdata,"utf-8");
entity.setContentType("application/json");
httpPost.setEntity(entity);
httpPost.setHeader("Accept", "application/json");
//完成簽名并執(zhí)行請求
CloseableHttpResponse response = httpClient.execute(httpPost);
try {
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) { //處理成功
System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
} else if (statusCode == 204) { //處理成功,無返回Body
System.out.println("success");
} else {
System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
throw new IOException("request failed");
}
} finally {
response.close();
}
}
更多參數(shù)、響應(yīng)詳情及錯誤碼請參見完結(jié)支付分訂單API接口文檔
步驟說明:在用戶扣款成功前、完結(jié)訂單后(即訂單狀態(tài)為“待支付”),如需修改訂單支付金額,可通過此接口進(jìn)行訂單金額修改。修改成功后,微信支付將按照修改后的金額進(jìn)行用戶扣款。
示例代碼:
public void ModifyServiceOrder() throws Exception{
//請求URL
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/payscore/serviceorder/{out_order_no}/modify");
// 請求body參數(shù)
String reqdata = "{"
+ "\"appid\":\"wxd678efh567hg6787\","
+ "\"service_id\":\"500001\","
+ "\"post_payments\": ["
+ "{"
+ "\"name\":\"就餐費(fèi)用服務(wù)費(fèi)\","
+ "\"amount\":4000,"
+ "\"description\":\"就餐人均100元服務(wù)費(fèi):100/小時(shí)\","
+ "\"count\":1"
+ "}"
+ "],"
+ "\"post_discounts\": ["
+ "{"
+ "\"name\":\"滿20減1元\","
+ "\"description\":\"不與其他優(yōu)惠疊加\","
+ "\"amount\":100"
+ "}"
+ "],"
+ "\"total_amount\":2000,"
+ "\"reason\":\"用戶投訴\""
+ "}";
StringEntity entity = new StringEntity(reqdata,"utf-8");
entity.setContentType("application/json");
httpPost.setEntity(entity);
httpPost.setHeader("Accept", "application/json");
//完成簽名并執(zhí)行請求
CloseableHttpResponse response = httpClient.execute(httpPost);
try {
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) { //處理成功
System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
} else if (statusCode == 204) { //處理成功,無返回Body
System.out.println("success");
} else {
System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
throw new IOException("request failed");
}
} finally {
response.close();
}
}
更多參數(shù)、響應(yīng)詳情及錯誤碼請參見修改訂單金額API接口文檔
步驟說明:由于一些原因,用戶與商戶達(dá)成線下支付或者其他支付方式支付的協(xié)議,商戶可通過此接口告知微信支付該筆訂單無需繼續(xù)扣款,微信支付在接到此信息后將不再發(fā)起用戶扣款。
示例代碼:
public void SyncServiceOrder() throws Exception{
//請求URL
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/payscore/serviceorder/{out_order_no}/sync");
// 請求body參數(shù)
String reqdata = "{"
+ "\"appid\":\"wxd678efh567hg6787\","
+ "\"service_id\":\"500001\","
+ "\"type\":\"Order_Paid\","
+ "\"detail\": {"
+ "\"paid_time\":\"20091225091210\""
+ "}"
+ "}";
StringEntity entity = new StringEntity(reqdata,"utf-8");
entity.setContentType("application/json");
httpPost.setEntity(entity);
httpPost.setHeader("Accept", "application/json");
//完成簽名并執(zhí)行請求
CloseableHttpResponse response = httpClient.execute(httpPost);
try {
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) { //處理成功
System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
} else if (statusCode == 204) { //處理成功,無返回Body
System.out.println("success");
} else {
System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
throw new IOException("request failed");
}
} finally {
response.close();
}
}
更多參數(shù)、響應(yīng)詳情及錯誤碼請參見 同步服務(wù)訂單信息API接口文檔
步驟說明:微信支付按天提供交易賬單文件,商戶可以通過該接口獲取賬單文件的下載地址
示例代碼:
public void TradeBill() throws Exception {
//請求URL
URIBuilder uriBuilder = new URIBuilder("https://api.mch.weixin.qq.com/v3/bill/tradebill");
uriBuilder.setParameter("bill_date", "2020-11-09");
uriBuilder.setParameter("bill_type", "ALL");
//完成簽名并執(zhí)行請求
HttpGet httpGet = new HttpGet(uriBuilder.build());
httpGet.addHeader("Accept", "application/json");
CloseableHttpResponse response = httpClient.execute(httpGet);
try {
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) {
System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
} else if (statusCode == 204) {
System.out.println("success");
} else {
System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
throw new IOException("request failed");
}
} finally {
response.close();
}
}
更多參數(shù)、響應(yīng)詳情及錯誤碼請參見 申請交易賬單API接口文檔
步驟說明:通過申請交易賬單接口獲取到賬單下載地址(download_url)后,再通過該接口獲取到對應(yīng)的賬單文件,文件內(nèi)包含交易相關(guān)的金額、時(shí)間、營銷等信息,供商戶核對訂單、退款、銀行到賬等情況
示例代碼:
public void DownloadUrl(String download_url) throws Exception{
PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes("utf-8")));
//初始化httpClient
//該接口無需進(jìn)行簽名驗(yàn)證、通過withValidator((response) -> true)實(shí)現(xiàn)
httpClient = WechatPayHttpClientBuilder.create().withMerchant(mchId, mchSerialNo, merchantPrivateKey).withValidator((response) -> true).build();
//請求URL
//賬單文件的下載地址的有效時(shí)間為30s
URIBuilder uriBuilder = new URIBuilder(download_url);
HttpGet httpGet = new HttpGet(uriBuilder.build());
httpGet.addHeader("Accept", "application/json");
//執(zhí)行請求
CloseableHttpResponse response = httpClient.execute(httpGet);
try {
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) {
System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
} else if (statusCode == 204) {
System.out.println("success");
} else {
System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
throw new IOException("request failed");
}
} finally {
response.close();
}
}
注意:
更多參數(shù)、響應(yīng)詳情及錯誤碼請參見 下載賬單API接口文檔
步驟說明:當(dāng)用戶完成支付,微信會把相關(guān)支付結(jié)果將通過異步回調(diào)的方式通知商戶,商戶需要接收處理,并按文檔規(guī)范返回應(yīng)答。
注意:
更多參數(shù)、響應(yīng)詳情及錯誤碼請參見 支付成功回調(diào)通知API接口文檔
微信支付根據(jù)用戶不同的使用場景(APP、小程序、微信內(nèi)H5)分別提供了對應(yīng)跳轉(zhuǎn)訂單詳情頁的方法,請根據(jù)場景進(jìn)行選擇,詳見跳轉(zhuǎn)訂單詳情頁API文檔
A:同一個(gè)用戶可以確認(rèn)免押訂單進(jìn)行中的筆數(shù)是3筆(未完結(jié)&未支付的訂單筆數(shù),產(chǎn)品策略,可能會調(diào)整);如果用戶進(jìn)行中的訂單超過3筆,則需要進(jìn)行押金支付,如果有任何1筆待支付的訂單,都是需要去支付押金的。
A:檢查測試微信是否開通白名單,提供服務(wù)id和微信號聯(lián)系運(yùn)營開通白名單
A:① 檢查商戶號和appid是否配置了通用化接口權(quán)限,可以聯(lián)系微信側(cè)運(yùn)營確認(rèn)和配置通用化接口權(quán)限
② 如果商戶開通的是免確認(rèn)訂單權(quán)限,創(chuàng)建訂單時(shí)need_user_confirm只能傳false,如果商戶開通的是含確認(rèn)訂單權(quán)限,創(chuàng)建訂單時(shí)need_user_confirm只能傳true
A:檢查商戶號開通的是哪種模式的權(quán)限,需確認(rèn)模式只能使用先免模式,免確認(rèn)模式只能使用先享模式模式
A:請商戶自行檢查mch_id和appid是否有對應(yīng)的綁定關(guān)系。綁定步驟參考“商家商戶號與AppID賬號關(guān)聯(lián)管理”。