开发指引

更新时间:2024.11.18

1. 接口规则

为了在保证支付安全的前提下,带给商户简单、一致且易用的开发体验,我们推出了全新的微信支付APIv3接口。该版本API的具体规则请参考APIv3接口规则

2. 开发准备

2.1. 搭建和配置开发环境

开发者应当依据自身的编程语言来构建并配置相应的开发环境。

2.2. 业务开发配置

1、微信支付分的相关配置参数在商户入驻的过程中都已经配置完成(前往查看配置相关内容),例如授权结果回调URL、service_notify_url、测试白名单、免确认订单模式的权限等。

2、如果发现配置信息有误,请主动联系微信支付分运营同学协助修改,或者点击右侧导航栏进入在线技术客服进行技术咨询。

3. 快速接入

3.1. 业务流程图

业务流程时序图

重点步骤说明:

步骤1 用户在商户侧下单,商户调用后台接口创建支付分订单,通过接口返回获得跳转微信支付分小程序进行订单确认的必填参数“package”

我们通过此接口来创建支付分订单:创建订单API (更换成间连链接)

  • 入参“need_user_confirm”,取值请选择 “true”;

  • 入参“risk_fund:name”,取值请选择【免密模式】中的枚举值。

步骤2 调用前端方法跳转至微信,让用户完成确认订单操作

我们通过以下前端方法可调起微信客户端(注意区分场景):

用户确认订单完成,商户系统将收到确认订单回调通知,此时可为用户提供服务;

我们通过以下接口将用户确认订单信息回调通知给商户系统:

在用户确认订单过程中可能出现长时间未收到回调、用户确认失败等情况,商户可先通过后台接口查询订单状态:

根据查询到的订单状态结果,商户可决定是否需要取消当前订单,后台接口为:

步骤3 用户服务结束,商户通过后台接口完结支付分订单;

步骤4 从业机构需要调用微信支付分系统登记扣款信息,之后再调用清算机构受理扣款

通过查询订单API接口主动查询扣款情况。

  • 如订单状态state=DONE,且收款状态collection.state=USER_PAID,代表扣款成功

  • 如订单状态state=DOING,state_description=MCH_COMPLETE,且收款状态collection.state=USER_PAYING,代表扣款进行中

如遇到网络、服务器等原因造成无法正常接收扣款成功通知,一般有两种解决方法:

  1. 主动查单,通过查询订单API 接口主动查询扣款情况

3.2. API接入(含示例代码)

文档展示了如何使用微信支付服务端 SDK 快速接入商家券产品,完成与微信支付对接的部分。

注意

  • 文档中的代码示例是用来阐述 API 基本使用方法,代码中的示例参数需替换成商户自己账号及请求参数才能跑通。

  • 以下接入步骤仅提供参考,请商户结合自身业务需求进行评估、修改。

3.2.1. 【服务端】创建订单

步骤说明: 完成用户授权后,即可创建支付分订单,为用户提供服务了。

示例代码
JAVA

1public void CreateServiceOrder() throws Exception{
2  
3    //请求URL
4    HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/payscore/acquiringbank/serviceorder");
5    // 请求body参数
6    String reqdata = "{"
7            + "\"out_order_no\":\"1234323JKHDFE1243252\","
8            + "\"appid\":\"wxd678efh567hg6787\","
9            + "\"service_id\":\"500001\","
10            + "\"sub_mchid\" : \"10000000\","
11            + "\"sub_appid\":\"wxd678efh567hg6788\","
12            + "\"channel_id\":\"12121212\","
13            + "\"service_introduction\":\"某某酒店\","
14            + "\"post_payments\": ["
15            + "{"
16            + "\"name\":\"就餐费用服务费\","
17            + "\"amount\":4000,"
18            + "\"description\":\"就餐人均100元服务费:100/小时\","
19            + "\"count\":1"
20            + "}"
21            + "],"
22            + "\"post_discounts\": ["
23            + "{"
24            + "\"name\":\"满20减1元\","
25            + "\"description\":\"不与其他优惠叠加\""
26            + "}"
27            + "],"
28            + "\"time_range\": {"
29            + "\"start_time\":\"20091225091010\","
30            + "\"end_time\":\"20091225121010\""
31            + "},"
32            + "\"location\": {"
33            + "\"start_location\":\"嗨客时尚主题展餐厅\","
34            + "\"end_location\":\"嗨客时尚主题展餐厅\""
35            + "},"
36            + "\"risk_fund\": {"
37            + "\"name\":\"ESTIMATE_ORDER_COST\","
38            + "\"amount\":10000,"
39            + "\"description\":\"就餐的预估费用\""
40            + "},"
41            + "\"attach\":\"Easdfowealsdkjfnlaksjdlfkwqoi&wl3l2sald\","
42            + "\"notify_url\":\"https://api.test.com\","
43            + "\"need_user_confirm\":true"
44            + "}";
45    StringEntity entity = new StringEntity(reqdata,"utf-8");
46    entity.setContentType("application/json");
47    httpPost.setEntity(entity);
48    httpPost.setHeader("Accept", "application/json");
49    
50    //完成签名并执行请求
51    CloseableHttpResponse response = httpClient.execute(httpPost);
52    
53    try {
54        int statusCode = response.getStatusLine().getStatusCode();
55        if (statusCode == 200) { //处理成功
56            System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
57        } else if (statusCode == 204) { //处理成功,无返回Body
58            System.out.println("success");
59        } else {
60            System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
61            throw new IOException("request failed");
62        }
63    } finally {
64        response.close();
65    }
66  }

重要入参说明:

  • 入参“need_user_confirm”,取值请选择 “true”;

  • 入参“risk_fund:name”,取值请选择【先免模式】中的枚举值。

更多参数、响应详情及错误码请参见创建支订单API接口文档

3.2.2. 【服务端】查询分订单

步骤说明: 一般在创建订单后、订单完结成功后等关键流程中,商户可能有知晓订单状态的需求,此时即可通过该接口查询订单状态。

示例代码

JAVA

1public void QueryServiceOrder() throws Exception{
2  
3    //请求URL
4    HttpPost httpGet = new HttpGet("https://api.mch.weixin.qq.com/v3/payscore/acquiringbank/serviceorder?service_id=2002000000000558128851361561536&sub_mchid=1900000109&channel_id=1230000109&out_order_no=1234323JKHDFE1243252&query_id=15646546545165651651");
5    httpGet.setHeader("Accept", "application/json");
6    
7    //完成签名并执行请求
8    CloseableHttpResponse response = httpClient.execute(httpGet);
9    
10    try {
11        int statusCode = response.getStatusLine().getStatusCode();
12        if (statusCode == 200) { //处理成功
13            System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
14        } else if (statusCode == 204) { //处理成功,无返回Body
15            System.out.println("success");
16        } else {
17            System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
18            throw new IOException("request failed");
19        }
20    } finally {
21        response.close();
22    }
23  }

更多参数、响应详情及错误码请参见 查询订单接口文档

3.2.3. 【服务端】取消订单

步骤说明: 订单为以下状态时可以取消订单:CREATED(已创单)、DOING(进行中)(包括商户完结支付分订单后,且支付分订单收款状态为待支付USER_PAYING)。

示例代码

JAVA

1public void CancelServiceOrder() throws Exception{
2  //请求URL
3  HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/payscore/acquiringbank/serviceorder/{out_order_no}/cancel");
4  // 请求body参数
5  String reqdata = "{"
6          + "\"sub_mchid\":\"10000000\","
7          + "\"channel_id\":\"10000000\","
8          + "\"service_id\":\"500001\","
9          + "\"reason\":\"用户投诉\""
10          + "}";
11  StringEntity entity = new StringEntity(reqdata,"utf-8");
12  entity.setContentType("application/json");
13  httpPost.setEntity(entity);
14  httpPost.setHeader("Accept", "application/json");
15  
16  //完成签名并执行请求
17  CloseableHttpResponse response = httpClient.execute(httpPost);
18  
19  try {
20      int statusCode = response.getStatusLine().getStatusCode();
21      if (statusCode == 200) { //处理成功
22          System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
23      } else if (statusCode == 204) { //处理成功,无返回Body
24          System.out.println("success");
25      } else {
26          System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
27          throw new IOException("request failed");
28      }
29  } finally {
30      response.close();
31  }
32}

更多参数、响应详情及错误码请参见 取消订单API接口文档

3.2.4. 【服务端】完结订单

步骤说明: 用户服务结束后,商户通过请求完结支付分订单接口,通过微信支付分进行用户扣款操作。

示例代码

JAVA

1public void CompleteServiceOrder() throws Exception{
2  //请求URL
3  HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/payscore/acquiringbank/serviceorder/{out_order_no}/complete");
4  // 请求body参数
5  String reqdata = "{"
6          + "\"sub_mchid\":\"10000000\","
7          + "\"channel_id\":\"10000000\","
8          + "\"service_id\":\"500001\","
9          + "\"complete_time\":\"2019-11-11T16:24:05+08:00\","
10          + "\"post_payments\": ["
11          + "{"
12          + "\"name\":\"就餐费用服务费\","
13          + "\"amount\":4000,"
14          + "\"description\":\"就餐人均100元服务费:100/小时\","
15          + "\"count\":1"
16          + "}"
17          + "],"
18          + "\"post_discounts\": ["
19          + "{"
20          + "\"name\":\"满20减1元\","
21          + "\"description\":\"不与其他优惠叠加\","
22          + "\"amount\":4000"
23          + "}"
24          + "],"
25          + "\"total_amount\":3900,"
26          + "\"time_range\": {"
27          + "\"start_time\":\"20091225091010\","
28          + "\"end_time\":\"20091225121010\""
29          + "},"
30          + "\"location\": {"
31          + "\"end_location\":\"嗨客时尚主题展餐厅\""
32          + "}"
33          + "}";
34  StringEntity entity = new StringEntity(reqdata,"utf-8");
35  entity.setContentType("application/json");
36  httpPost.setEntity(entity);
37  httpPost.setHeader("Accept", "application/json");
38  
39  //完成签名并执行请求
40  CloseableHttpResponse response = httpClient.execute(httpPost);
41  
42  try {
43      int statusCode = response.getStatusLine().getStatusCode();
44      if (statusCode == 200) { //处理成功
45          System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
46      } else if (statusCode == 204) { //处理成功,无返回Body
47          System.out.println("success");
48      } else {
49          System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
50          throw new IOException("request failed");
51      }
52  } finally {
53      response.close();
54  }
55}

更多参数、响应详情及错误码请参见完结订单API接口文档

3.2.5. 【服务端】登记扣款信息

示例代码
JAVA

1public void RegisterDeductInfo() throws Exception{
2  //请求URL
3  HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/payscore/acquiringbank/serviceorder/{out_order_no}/registerdeductinfo");
4  // 请求body参数
5  String reqdata = "{"
6          + "\"sub_mchid\":\"10000000\","
7          + "\"channel_id\":\"10000000\","
8          + "\"service_id\":\"500001\","
9          + "\"appid\":\"wxd678efh567hg6787\","
10          + "\"out_trade_no\": \"1234323JKHDFE1243252\","
11          + "\"sub_appid\":wxd678efh567hg6999"
12        + "}";
13  StringEntity entity = new StringEntity(reqdata,"utf-8");
14  entity.setContentType("application/json");
15  httpPost.setEntity(entity);
16  httpPost.setHeader("Accept", "application/json");
17  
18  //完成签名并执行请求
19  CloseableHttpResponse response = httpClient.execute(httpPost);
20  
21  try {
22      int statusCode = response.getStatusLine().getStatusCode();
23      if (statusCode == 200) { //处理成功
24          System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
25      } else if (statusCode == 204) { //处理成功,无返回Body
26          System.out.println("success");
27      } else {
28          System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
29          throw new IOException("request failed");
30      }
31  } finally {
32      response.close();
33  }
34}

更多参数、响应详情及错误码请参见 登记扣款信息接口文档

3.2.6. 【服务端】查询扣款信息

示例代码
JAVA

1public void QueryDeduction() throws Exception{
2  
3    //请求URL
4    HttpPost httpGet = new HttpGet("https://api.mch.weixin.qq.com/v3/payscore/acquiringbank/serviceorder/deduction?service_id=2002000000000558128851361561536&appid=wxd678efh567hg6787&sub_mchid=1900000109&sub_appid=wxd678efh567hg6999&channel_id=1230000109&out_order_no=1234323JKHDFE1243252");
5    httpGet.setHeader("Accept", "application/json");
6    
7    //完成签名并执行请求
8    CloseableHttpResponse response = httpClient.execute(httpGet);
9    
10    try {
11        int statusCode = response.getStatusLine().getStatusCode();
12        if (statusCode == 200) { //处理成功
13            System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
14        } else if (statusCode == 204) { //处理成功,无返回Body
15            System.out.println("success");
16        } else {
17            System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
18            throw new IOException("request failed");
19        }
20    } finally {
21        response.close();
22    }
23  }

更多参数、响应详情及错误码请参见 查询扣款信息接口文档