为了在保证支付安全的前提下,带给商户简单、一致且易用的开发体验,我们推出了全新的微信支付APIv3接口。该版本API的具体规则请参考“APIv3接口规则”
为了帮助开发者调用开放接口,我们提供了JAVA、PHP、GO三种语言版本的开发库,封装了签名生成、签名验证、敏感信息加/解密、媒体文件上传等基础功能(更多语言版本的开发库将在近期陆续提供)
测试步骤:
1、根据自身开发语言,选择对应的开发库并构建项目,具体配置请参考下面链接的详细说明:
• wechatpay-java(推荐)wechatpay-apache-httpclient,适用于Java开发者。
• wechatpay-php(推荐)、wechatpay-guzzle-middleware,适用于PHP开发者
注:当前开发指引接口PHP示例代码采用wechatpay-guzzle-middleware版本
• wechatpay-go,适用于Go开发者
更多资源可前往微信支付开发者社区搜索查看
2、创建加载商户私钥、加载平台证书、初始化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、基于接口的示例代码,替换请求参数后可发起测试
说明:
• 上面的开发库为微信支付官方开发库,其它没有审核或者控制下的第三方工具和库,微信支付不保证它们的安全性和可靠性
通过包管理工具引入SDK后,可根据下面每个接口的示例代码替换相关参数后进行快速测试
• 开发者如果想详细了解签名生成、签名验证、敏感信息加/解密、媒体文件上传等常用方法的具体代码实现,可阅读下面的详细说明:
1.签名生成
2.签名验证
3.敏感信息加解密
• 如想更详细的了解我们的接口规则,可查看我们的接口规则指引文档
需分账的订单,平台在下单时需预先打上分账标识“profit_sharing”,详细可查看各场景下单API(普通支付下单/合单支付下单API)。
重要步骤说明:
步骤一: 平台通过添加分账接收方API添加需要分账的分账对象(接收方)。
步骤二: 平台预先在合单支付/普通支付下单API接口中上传分账标识“profit_sharing”,待订单完成支付后即可调用请求分账API接口发起分账请求。
步骤三: 分账完成后,微信会通过分账动账通知API接口,主动通知商户。商户如有需要,可以通过查询分账结果API接口,主动查询分账结果。
步骤四: 分账后若产生退款,则需先调用请求分账回退API 接口,请求将已经分给分账方的资金回退,再处理退款。
步骤五: 分账回退完成后,微信同样会通过分账动账通知API接口,主动通知商户。商户也可以通过查询分账回退结果API接口,主动查询分账结果。
步骤六: 分账结束后,商户需调用完结分账API接口结束分账订单。
本文档展示了如何使用微信支付服务端 SDK 快速接入平台收付通产品,完成与微信支付对接的部分。
注意:
步骤说明:平台可通过此接口添加分账接收方,建立分账接收方列表。后续通过发起分账请求,将平台下的二级商户结算后的资金,分给分账接收方列表中具体的分账接收方
示例代码
public void AddProfitsharingReceivers() throws Exception{
//请求URL
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/ecommerce/profitsharing/receivers/add");
// 请求body参数
String reqdata = "{"
+ "\"appid\":\"wx8888888888888888\","
+ "\"type\":\"MERCHANT_ID\","
+ "\"account\":\"190001001\","
+ "\"name\":\"张三网络公司\","
+ "\"relation_type\":\"SUPPLIER\""
+ "}";
StringEntity entity = new StringEntity(reqdata,"utf-8");
entity.setContentType("application/json");
httpPost.setEntity(entity);
httpPost.setHeader("Accept", "application/json");
//完成签名并执行请求
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();
}
}
更多参数、响应详情及错误码请参见添加分账接收方API接口文档
步骤说明:平台如有订单需要进行分账,可通过此接口完成。
示例代码:
public void Profitsharing() throws Exception{
//请求URL
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/ecommerce/profitsharing/orders");
// 请求body参数
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");
//完成签名并执行请求
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();
}
}
更多参数、响应详情及错误码请参见请求分账API接口文档
步骤说明:此功能仅针对分账接收方,当分账动账金额发生变动时,微信会把相关变动结果发送给需要实时关注的分账接收方
注意:
更多参数、响应详情及错误码请参见分账动账通知API接口文档
步骤说明:平台可通过此接口实时关注订单的分账请求和分账完结情况。
示例代码:
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");
//完成签名并执行请求
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();
}
}
更多参数、响应详情及错误码请参见 查询分账结果API接口文档
步骤说明:订单已经分账,在退款时,可以先调此接口,将已分账的资金从分账接收方的账户回退给分账方,再发起退款。
示例代码:
public void Demo() throws Exception{
//请求URL
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/ecommerce/profitsharing/returnorders");
// 请求body参数
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");
//完成签名并执行请求
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();
}
}
更多参数、响应详情及错误码请参见请求分账回退API 接口文档
步骤说明:商户需要核实回退结果,可调用此接口查询回退结果;如果分账回退接口返回状态为处理中,可调用此接口查询回退结果。
示例代码:
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");
//完成签名并执行请求
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();
}
}
更多参数、响应详情及错误码请参见查询分账回退结果API 接口文档
步骤说明:不需要进行分账的订单,可直接调用本接口将订单的金额全部解冻给二级商户。
示例代码:
public void FinishProfitsharing() throws Exception{
//请求URL
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/ecommerce/profitsharing/finish-order");
// 请求body参数
String reqdata = "{"
+ "\"sub_mchid\":\"1900000109\","
+ "\"transaction_id\":\"4208450740201411110007820472\","
+ "\"out_order_no\":\"P20150806125346\","
+ "\"description\":\"分账完结\""
+ "}";
StringEntity entity = new StringEntity(reqdata,"utf-8");
entity.setContentType("application/json");
httpPost.setEntity(entity);
httpPost.setHeader("Accept", "application/json");
//完成签名并执行请求
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();
}
}
更多参数、响应详情及错误码请参见完结分账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");
//完成签名并执行请求
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();
}
}
更多参数、响应详情及错误码请参见查询订单剩余待分金额API接口文档
步骤说明:平台发起删除分账接收方请求。删除后,不支持将平台下二级商户结算后的资金,分到该分账接收方。
示例代码:
public void DeleteProfitsharingReceivers() throws Exception{
//请求URL
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/ecommerce/profitsharing/receivers/delete");
// 请求body参数
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");
//完成签名并执行请求
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();
}
}
更多参数、响应详情及错误码请参见 删除分账接收方API接口文档
A:“回退商户号”的账户可用余额不足,需充值后再原单重试才能回退成功
A:是正常的,逻辑就是这样的。这种情况,商户可以按照提示要求,提醒“回退商户号”充值后再原单重试即可回退成功
A:请参考以下几点:
1)网络抖动导致请求中断
2)商户账户资金转账频繁,导致回退在排队时超时
A:TIME_OUT_CLOSED是fail状态了,也就是处于最终态,是不需要重试的。状态是SUCCESS也同理,也是最终态,不需要重试。返回TIME_OUT_CLOSED时可更换一个回退单,重新分账回退一次即可
A:报这个错误,是因为支付的订单在基础下单里面传了参数“补差金额:subsidy_amount”,传这个参数后,需要调用“请求补差API”完成补差,然后再调用“请求分账接口”即可正常分账