為了在保證支付安全的前提下,帶給商戶簡單、一致且易用的開發(fā)體驗,我們推出了全新的微信支付APIv3接口。該版本API的具體規(guī)則請參考“APIv3接口規(guī)則”
為了幫助開發(fā)者調(diào)用開放接口,我們提供了JAVA、PHP、GO三種語言版本的開發(fā)庫,封裝了簽名生成、簽名驗證、敏感信息加/解密、媒體文件上傳等基礎(chǔ)功能(更多語言版本的開發(fā)庫將在近期陸續(xù)提供)
測試步驟:
1、根據(jù)自身開發(fā)語言,選擇對應的開發(fā)庫并構(gòu)建項目,具體配置請參考下面鏈接的詳細說明:
? wechatpay-java(推薦)wechatpay-apache-httpclient,適用于Java開發(fā)者。
? wechatpay-php(推薦)、wechatpay-guzzle-middleware,適用于PHP開發(fā)者
注:當前開發(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ā)者如果想詳細了解簽名生成、簽名驗證、敏感信息加/解密、媒體文件上傳等常用方法的具體代碼實現(xiàn),可閱讀下面的詳細說明:
1.簽名生成
2.簽名驗證
3.敏感信息加解密
? 如想更詳細的了解我們的接口規(guī)則,可查看我們的接口規(guī)則指引文檔
服務商可登錄【服務商平臺-合作工具箱】申請開通【連鎖品牌工具箱】。進行品牌申請、查看品牌申請進度、邀請品牌總部授權(quán)、品牌門店管理、品牌流量場景管理等日常管理。
連鎖工具箱開通后,品牌主在商戶平臺進入:“品牌專區(qū)-品牌交易-品牌供應鏈分賬-供應鏈分賬管理”中可進行分賬比例的調(diào)整。
步驟4 分賬前需調(diào)用《添加分賬接收方》接口添加分賬接收方。
步驟6 分賬訂單發(fā)起分賬需調(diào)用《請求分賬》接口進行分賬,微信支付將會把結(jié)算資金分給分賬接收方。
步驟8 分賬完成后,微信會通過《分賬動賬通知》接口,主動通知商戶。商戶也可以通過《查詢分賬結(jié)果》接口,主動查詢分賬結(jié)果。
步驟12分賬后若產(chǎn)生退款,則需先調(diào)用《請求分賬回退》接口,請求將已經(jīng)分給分賬方的資金回退,再處理退款。
步驟13分賬回退完成后,微信同樣會通過《分賬動賬通知》接口,主動通知商戶。商戶也可以通過《查詢分賬回退結(jié)果》接口,主動查詢分賬結(jié)果。
步驟17分賬結(jié)束后,商戶需調(diào)用《完結(jié)分賬》接口結(jié)束分賬訂單。
文檔展示了如何使用微信支付服務端 SDK 快速接入連鎖品牌分賬產(chǎn)品,完成與微信支付對接的部分。
注意:
步驟說明:微信訂單支付成功后,由服務商發(fā)起分賬請求,將結(jié)算后的資金分給分賬接收方。
示例代碼:
public void ProfitSharing() throws Exception{
//請求URL
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/brand/profitsharing/orders");
// 請求body參數(shù)
String reqdata = "{"
+ "\"brand_mchid\":\"1900000108\","
+ "\"sub_mchid\":\"1900000109\","
+ "\"appid\":\"wx8888888888888888\","
+ "\"sub_appid\":\"wx8888888888888889\","
+ "\"transaction_id\":\"4208450740201411110007820472\","
+ "\"out_order_no\":\"P20150806125346\","
+ "\"receivers\": ["
+ "{"
+ "\"type\":\"MERCHANT_ID\","
+ "\"account\":\"1900000110\","
+ "\"amount\":100,"
+ "\"description\":\"1900000109分給商戶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();
}
}
重要入?yún)⒄f明:
? brand_mchid:品牌主商戶號,填寫微信支付分配的商戶號。? coupon_code:券code,券的唯一標識。
? sub_mchid:子商戶號,訂單收款方商戶號,可以是品牌主商戶號,也可以是門店商戶號,填寫微信支付分配的商戶號。
? appid:公眾賬號ID,微信分配的公眾賬號ID,這里指服務商的appid
? out_order_no:商戶分賬單號,商戶系統(tǒng)內(nèi)部的分賬單號,在商戶系統(tǒng)內(nèi)部唯一(單次分賬、多次分賬、完結(jié)分賬應使用不同的商戶分賬單號),同一分賬單號多次請求等同一次,只能是數(shù)字、大小寫字母_-|*@。
注意:
更多參數(shù)、響應詳情及錯誤碼請參見請求分賬接口文檔
步驟說明:發(fā)起分賬請求后,可調(diào)用此接口查詢分賬結(jié)果 。發(fā)起分賬完結(jié)請求后,可調(diào)用此接口查詢分賬完結(jié)的結(jié)果。
示例代碼:
public void QueryProfitSharing() throws Exception{
//請求URL
HttpGet httpGet = new HttpGet("https://api.mch.weixin.qq.com/v3/brand/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();
}
}
重要入?yún)⒄f明:
? transaction_id:微信訂單號, 微信支付訂單號
? sub_mchid:子商戶號,訂單收款方商戶號,可以是品牌主商戶號,也可以是門店商戶號,填寫微信支付分配的商戶號。
? out_order_no:商戶分賬單號,商戶系統(tǒng)內(nèi)部的分賬單號,在商戶系統(tǒng)內(nèi)部唯一(單次分賬、多次分賬、完結(jié)分賬應使用不同的商戶分賬單號),同一分賬單號多次請求等同一次,只能是數(shù)字、大小寫字母_-|*@。
注意:
更多參數(shù)、響應詳情及錯誤碼請參見查詢分賬結(jié)果接口文檔
步驟說明:此功能僅針對分賬接收方,當分賬動賬金額發(fā)生變動時,微信會把相關(guān)變動結(jié)果發(fā)送給需要實時關(guān)注的分賬接收方
注意:
更多參數(shù)、響應詳情及錯誤碼請參見分賬動賬通知接口文檔
步驟說明:如果訂單已經(jīng)分賬,在退款時,可以先調(diào)此接口,將已分賬的資金從商戶類型的分賬接收方的賬戶回退給分賬方,再發(fā)起退款。
示例代碼:
public void ReturnProfitSharing() throws Exception{
//請求URL
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/brand/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();
}
}
重要入?yún)⒄f明:
? sub_mchid:子商戶號,訂單收款方商戶號,可以是品牌主商戶號,也可以是門店商戶號,填寫微信支付分配的商戶號。
? out_order_no:商戶分賬單號,商戶系統(tǒng)內(nèi)部的分賬單號,在商戶系統(tǒng)內(nèi)部唯一(單次分賬、多次分賬、完結(jié)分賬應使用不同的商戶分賬單號),同一分賬單號多次請求等同一次,只能是數(shù)字、大小寫字母_-|*@。
? out_return_no:商戶回退單號,此回退單號是商戶在自己后臺生成的一個新的回退單號,在商戶后臺唯一,只能是數(shù)字、大小寫字母_-|*@。
? return_mchid:回退商戶號,回退商戶號只能填寫原分賬請求中接收分賬的商戶號
注意:
更多參數(shù)、響應詳情及錯誤碼請參見請求分賬回退接口文檔
步驟說明:商戶需要核實回退結(jié)果,可調(diào)用此接口查詢回退結(jié)果。如果分賬回退接口返回狀態(tài)為處理中,可調(diào)用此接口查詢回退結(jié)果
示例代碼:
public void QueryReturnOrder() throws Exception{
//請求URL
HttpGet httpGet = new HttpGet("https://api.mch.weixin.qq.com/v3/brand/profitsharing/returnorders?sub_mchid=1900000109&out_return_no=R20190516001&order_id=4208450740201411110007820472");
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();
}
}
重要入?yún)⒄f明:
? sub_mchid:子商戶號,訂單收款方商戶號,可以是品牌主商戶號,也可以是門店商戶號,填寫微信支付分配的商戶號。
? out_order_no:商戶分賬單號,商戶系統(tǒng)內(nèi)部的分賬單號,在商戶系統(tǒng)內(nèi)部唯一(單次分賬、多次分賬、完結(jié)分賬應使用不同的商戶分賬單號),同一分賬單號多次請求等同一次,只能是數(shù)字、大小寫字母_-|*@。
? out_return_no:商戶回退單號,調(diào)用回退接口提供的商戶系統(tǒng)內(nèi)部的回退單號。
注意:
更多參數(shù)、響應詳情及錯誤碼請參見查詢分賬回退結(jié)果接口文檔
步驟說明:不需要進行分賬的訂單,可直接調(diào)用本接口將訂單的金額全部解凍給分賬方商戶
示例代碼:
public void FinishProfitSharing() throws Exception{
//請求URL
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/brand/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();
}
}
重要入?yún)⒄f明:
? transaction_id:微信訂單號, 微信支付訂單號
? sub_mchid:子商戶號,訂單收款方商戶號,可以是品牌主商戶號,也可以是門店商戶號,填寫微信支付分配的商戶號。
? out_order_no:商戶分賬單號,商戶系統(tǒng)內(nèi)部的分賬單號,在商戶系統(tǒng)內(nèi)部唯一(單次分賬、多次分賬、完結(jié)分賬應使用不同的商戶分賬單號),同一分賬單號多次請求等同一次,只能是數(shù)字、大小寫字母_-|*@。
注意:
更多參數(shù)、響應詳情及錯誤碼請參見完結(jié)分賬接口文檔
步驟說明:可調(diào)用此接口查詢訂單剩余待分金額
示例代碼:
public void QueryRemainAmounts() throws Exception{
//請求URL
HttpGet httpGet = new HttpGet("https://api.mch.weixin.qq.com/v3/brand/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();
}
}
重要入?yún)⒄f明:
? transaction_id:微信訂單號, 微信支付訂單號
注意:
更多參數(shù)、響應詳情及錯誤碼請參見查詢訂單剩余待分金額接口文檔
步驟說明:服務商可通過此接口添加分賬接收方,建立分賬接收方列表。連鎖加盟模式下,服務商添加的分賬接收方統(tǒng)一在品牌主商戶號維度進行管理。
示例代碼:
public void QueryBrandConfigs() throws Exception{
//請求URL
HttpGet httpGet = new HttpGet("https://api.mch.weixin.qq.com/v3/brand/profitsharing/brand-configs/1900000109");
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();
}
}
重要入?yún)⒄f明:
? brand_mchid:品牌主商戶號,通過微信支付認證的品牌主商戶號,填寫微信支付分配的商戶號
注意:
更多參數(shù)、響應詳情及錯誤碼請參見查詢最大分賬比例接口文檔
步驟說明:服務商可通過此接口添加分賬接收方,建立分賬接收方列表。連鎖加盟模式下,服務商添加的分賬接收方統(tǒng)一在品牌主商戶號維度進行管理。
示例代碼:
public void AddReceivers() throws Exception{
//請求URL
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/brand/profitsharing/receivers/add");
// 請求body參數(shù)
String reqdata = "{"
+ "\"brand_mchid\":\"1900000108\","
+ "\"appid\":\"wx8888888888888888\","
+ "\"sub_appid\":\"wx8888888888888889\","
+ "\"type\":\"MERCHANT_ID\","
+ "\"account\":\"1900000109\","
+ "\"name\":\"張三網(wǎng)絡公司\","
+ "\"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();
}
}
重要入?yún)⒄f明:
? brand_mchid:品牌主商戶號,通過微信支付認證的品牌主商戶號,填寫微信支付分配的商戶號
? appid:公眾賬號ID,微信分配的公眾賬號ID,這里指服務商的appid
? type:分賬接收方類型,枚舉值:
MERCHANT_ID:商戶號(mch_id或者sub_mch_id)
PERSONAL_OPENID:個人openid(由服務商的APPID轉(zhuǎn)換得到)
PERSONAL_SUB_OPENID:個人sub_openid(由品牌主的APPID轉(zhuǎn)換得到)
? account:分賬接收方賬號
分賬接收方類型為:MERCHANT_ID時,分賬接收方賬號為商戶號(mch_id或者sub_mch_id)
分賬接收方類型為:PERSONAL_OPENID時,分賬接收方賬號為個人openid
分賬接收方類型為:PESONAL_SUB_OPENID時,分賬接收方賬號為個人sub_openid
注意:
更多參數(shù)、響應詳情及錯誤碼請參見添加分賬接收方接口文檔
步驟說明:服務商發(fā)起刪除分賬接收方請求。刪除后,不再支持品牌主或門店分到該分賬接收方。
示例代碼:
public void DelReceivers() throws Exception{
//請求URL
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/brand/profitsharing/receivers/delete");
// 請求body參數(shù)
String reqdata = "{"
+ "\"brand_mchid\":\"1900000108\","
+ "\"appid\":\"wx8888888888888888\","
+ "\"sub_appid\":\"wx8888888888888889\","
+ "\"type\":\"MERCHANT_ID\","
+ "\"account\":\"1900000109\""
+ "}";
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();
}
}
重要入?yún)⒄f明:
? brand_mchid:品牌主商戶號,通過微信支付認證的品牌主商戶號,填寫微信支付分配的商戶號
? appid:公眾賬號ID,微信分配的公眾賬號ID,這里指服務商的appid
? type:分賬接收方類型,枚舉值:
MERCHANT_ID:商戶號(mch_id或者sub_mch_id)
PERSONAL_OPENID:個人openid(由服務商的APPID轉(zhuǎn)換得到)
PERSONAL_SUB_OPENID:個人sub_openid(由品牌主的APPID轉(zhuǎn)換得到)
? account:分賬接收方賬號
分賬接收方類型為:MERCHANT_ID時,分賬接收方賬號為商戶號(mch_id或者sub_mch_id)
分賬接收方類型為:PERSONAL_OPENID時,分賬接收方賬號為個人openid
分賬接收方類型為:PESONAL_SUB_OPENID時,分賬接收方賬號為個人sub_openid
注意:
更多參數(shù)、響應詳情及錯誤碼請參見刪除分賬接收方接口文檔
A:請按照以下幾點檢查:
1. 微信訂單號填寫錯誤
2. 下單的時候未傳分賬標識(profit_sharing)的訂單,是沒有分賬權(quán)限的
A:請按照以下幾點檢查:
1. 該訂單已全額退款,沒有資金可以分賬
2. 已經(jīng)調(diào)用過“請求單次分賬”,訂單剩余的待分賬金額已經(jīng)解凍,已無分賬資金
2. 超過訂單可分賬金額或者該訂單已無可分賬金額,請檢查確認
A:請按照以下幾點檢查:
1. 請在訂單支付成功1分鐘后再調(diào)用分賬接口
2. 未結(jié)算的訂單,請在結(jié)算后再調(diào)用分賬接口請求分賬
3. 老資金流商戶的訂單,不支持分賬
4. 商戶開通了收支分離但手續(xù)費賬戶余額不足(手續(xù)費賬戶最低余額要求是100元以上,在充值手續(xù)費賬戶1小時后,訂單會正常結(jié)算,即可正常調(diào)用分賬接口)
A:請按照以下幾點檢查:
1. 分賬接收商戶全稱填寫錯誤,請?zhí)顚懻_的商戶全稱
2. 接口需要使用UTF-8編碼
A:receiver中的參數(shù)account錯誤,參數(shù)account的規(guī)則如下:
1. 類型是MERCHANT_ID時,是商戶ID
2. 類型是PERSONAL_OPENID時,是個人openid
3. 類型是PERSONAL_SUB_OPENID時,是個人sub_openid
4. APPID與mchid不匹配也會報該錯誤,請檢查確認
5. 簽名類型錯誤,分賬接口簽名類型目前只支持HMAC-SHA256