為了在保證支付安全的前提下,帶給商戶簡單、一致且易用的開發(fā)體驗,我們推出了全新的微信支付APIv3接口。該版本API的具體規(guī)則請參考“APIv3接口規(guī)則”
為了幫助開發(fā)者調(diào)用開放接口,我們提供了JAVA、PHP、GO三種語言版本的開發(fā)庫,封裝了簽名生成、簽名驗證、敏感信息加/解密、媒體文件上傳等基礎(chǔ)功能(更多語言版本的開發(fā)庫將在近期陸續(xù)提供)
測試步驟:
1、根據(jù)自身開發(fā)語言,選擇對應(yīng)的開發(fā)庫并構(gòu)建項目,具體配置請參考下面鏈接的詳細(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ù)下面每個接口的示例代碼替換相關(guān)參數(shù)后進行快速測試
? 開發(fā)者如果想詳細(xì)了解簽名生成、簽名驗證、敏感信息加/解密、媒體文件上傳等常用方法的具體代碼實現(xiàn),可閱讀下面的詳細(xì)說明:
1.簽名生成
2.簽名驗證
3.敏感信息加解密
? 如想更詳細(xì)的了解我們的接口規(guī)則,可查看我們的接口規(guī)則指引文檔
需分賬的訂單,平臺在下單時需預(yù)先打上分賬標(biāo)識“profit_sharing”,詳細(xì)可查看各場景下單API(普通支付下單/合單支付下單API)。
重要步驟說明:
步驟一: 平臺通過添加分賬接收方API添加需要分賬的分賬對象(接收方)。
步驟二: 平臺預(yù)先在合單支付/普通支付下單API接口中上傳分賬標(biāo)識“profit_sharing”,待訂單完成支付后即可調(diào)用請求分賬API接口發(fā)起分賬請求。
步驟三: 分賬完成后,微信會通過分賬動賬通知API接口,主動通知商戶。商戶如有需要,可以通過查詢分賬結(jié)果API接口,主動查詢分賬結(jié)果。
步驟四: 分賬后若產(chǎn)生退款,則需先調(diào)用請求分賬回退API 接口,請求將已經(jīng)分給分賬方的資金回退,再處理退款。
步驟五: 分賬回退完成后,微信同樣會通過分賬動賬通知API接口,主動通知商戶。商戶也可以通過查詢分賬回退結(jié)果API接口,主動查詢分賬結(jié)果。
步驟六: 分賬結(jié)束后,商戶需調(diào)用完結(jié)分賬API接口結(jié)束分賬訂單。
本文檔展示了如何使用微信支付服務(wù)端 SDK 快速接入平臺收付通產(chǎn)品,完成與微信支付對接的部分。
注意:
步驟說明:平臺可通過此接口添加分賬接收方,建立分賬接收方列表。后續(xù)通過發(fā)起分賬請求,將平臺下的二級商戶結(jié)算后的資金,分給分賬接收方列表中具體的分賬接收方
示例代碼
public void AddProfitsharingReceivers() throws Exception{
//請求URL
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/ecommerce/profitsharing/receivers/add");
// 請求body參數(shù)
String reqdata = "{"
+ "\"appid\":\"wx8888888888888888\","
+ "\"type\":\"MERCHANT_ID\","
+ "\"account\":\"190001001\","
+ "\"name\":\"張三網(wǎng)絡(luò)公司\","
+ "\"relation_type\":\"SUPPLIER\""
+ "}";
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接口文檔
步驟說明:平臺如有訂單需要進行分賬,可通過此接口完成。
示例代碼:
public void Profitsharing() throws Exception{
//請求URL
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/ecommerce/profitsharing/orders");
// 請求body參數(shù)
String reqdata = "{"
+ "\"sub_mchid\":\"1900000109\","
+ "\"transaction_id\":\"4208450740201411110007820472\","
+ "\"out_order_no\":\"P20150806125346\","
+ "\"receivers\": ["
+ "{"
+ "\"type\":\"MERCHANT_ID\","
+ "\"receiver_account\":\"1900000110\","
+ "\"receiver_mchid\":\"1900000110\","
+ "\"amount\":100,"
+ "\"description\":\"分給商戶1900000110\""
+ "}"
+ "],"
+ "\"finish\":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īng)詳情及錯誤碼請參見請求分賬API接口文檔
步驟說明:此功能僅針對分賬接收方,當(dāng)分賬動賬金額發(fā)生變動時,微信會把相關(guān)變動結(jié)果發(fā)送給需要實時關(guān)注的分賬接收方
注意:
更多參數(shù)、響應(yīng)詳情及錯誤碼請參見分賬動賬通知API接口文檔
步驟說明:平臺可通過此接口實時關(guān)注訂單的分賬請求和分賬完結(jié)情況。
示例代碼:
public void QueryProfitsharing() throws Exception{
//請求URL
HttpGet httpGet = new HttpGet("https://api.mch.weixin.qq.com/v3/ecommerce/profitsharing/orders?sub_mchid=1900000109&transaction_id=4208450740201411110007820472&out_order_no=P20150806125346");
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();
}
}
更多參數(shù)、響應(yīng)詳情及錯誤碼請參見 查詢分賬結(jié)果API接口文檔
步驟說明:訂單已經(jīng)分賬,在退款時,可以先調(diào)此接口,將已分賬的資金從分賬接收方的賬戶回退給分賬方,再發(fā)起退款。
示例代碼:
public void Demo() throws Exception{
//請求URL
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/ecommerce/profitsharing/returnorders");
// 請求body參數(shù)
String reqdata = "{"
+ "\"sub_mchid\":\"1900000109\","
+ "\"order_id\":\"3008450740201411110007820472\","
+ "\"out_order_no\":\"P20150806125346\","
+ "\"out_return_no\":\"R20190516001\","
+ "\"return_mchid\":\"86693852\","
+ "\"amount\":10,"
+ "\"description\":\"分賬回退\""
+ "}";
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 接口文檔
步驟說明:商戶需要核實回退結(jié)果,可調(diào)用此接口查詢回退結(jié)果;如果分賬回退接口返回狀態(tài)為處理中,可調(diào)用此接口查詢回退結(jié)果。
示例代碼:
public void QueryFallbackProfitsharing() throws Exception{
//請求URL
HttpGet httpGet = new HttpGet("https://api.mch.weixin.qq.com/v3/ecommerce/profitsharing/returnorders?sub_mchid=1900000109&out_order_no=P20150806125346&out_return_no=R20190516001");
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();
}
}
更多參數(shù)、響應(yīng)詳情及錯誤碼請參見查詢分賬回退結(jié)果API 接口文檔
步驟說明:不需要進行分賬的訂單,可直接調(diào)用本接口將訂單的金額全部解凍給二級商戶。
示例代碼:
public void FinishProfitsharing() throws Exception{
//請求URL
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/ecommerce/profitsharing/finish-order");
// 請求body參數(shù)
String reqdata = "{"
+ "\"sub_mchid\":\"1900000109\","
+ "\"transaction_id\":\"4208450740201411110007820472\","
+ "\"out_order_no\":\"P20150806125346\","
+ "\"description\":\"分賬完結(jié)\""
+ "}";
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接口文檔
步驟說明:分賬接口支持對一筆訂單進行多次分賬,在這過程中,你可以使用該接口查詢訂單剩余的可進行分賬的金額。
示例代碼:
public void QueryProfitsharingAmounts() throws Exception{
//請求URL
HttpGet httpGet = new HttpGet("https://api.mch.weixin.qq.com/v3/ecommerce/profitsharing/orders/4208450740201411110007820472/amounts");
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();
}
}
更多參數(shù)、響應(yīng)詳情及錯誤碼請參見查詢訂單剩余待分金額API接口文檔
步驟說明:平臺發(fā)起刪除分賬接收方請求。刪除后,不支持將平臺下二級商戶結(jié)算后的資金,分到該分賬接收方。
示例代碼:
public void DeleteProfitsharingReceivers() throws Exception{
//請求URL
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/ecommerce/profitsharing/receivers/delete");
// 請求body參數(shù)
String reqdata = "{"
+ "\"appid\":\"wx8888888888888888\","
+ "\"type\":\"MERCHANT_ID\","
+ "\"account\":\"190001001\""
+ "}";
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接口文檔
A:“回退商戶號”的賬戶可用余額不足,需充值后再原單重試才能回退成功
A:是正常的,邏輯就是這樣的。這種情況,商戶可以按照提示要求,提醒“回退商戶號”充值后再原單重試即可回退成功
A:請參考以下幾點:
1)網(wǎng)絡(luò)抖動導(dǎo)致請求中斷
2)商戶賬戶資金轉(zhuǎn)賬頻繁,導(dǎo)致回退在排隊時超時
A:TIME_OUT_CLOSED是fail狀態(tài)了,也就是處于最終態(tài),是不需要重試的。狀態(tài)是SUCCESS也同理,也是最終態(tài),不需要重試。返回TIME_OUT_CLOSED時可更換一個回退單,重新分賬回退一次即可
A:報這個錯誤,是因為支付的訂單在基礎(chǔ)下單里面?zhèn)髁藚?shù)“補差金額:subsidy_amount”,傳這個參數(shù)后,需要調(diào)用“請求補差A(yù)PI”完成補差,然后再調(diào)用“請求分賬接口”即可正常分賬