1. 接口规则
为了在保证支付安全的前提下,带给商户简单、一致且易用的开发体验,我们推出了全新的微信支付APIv3接口。该版本API的具体规则请参考APIv3接口规则。
2. 开发准备
2.1. 搭建和配置开发环境
开发者应当依据自身的编程语言来构建并配置相应的开发环境。
3. 快速接入
3.1. 业务流程图
业务流程时序图
申请单状态变化如下:
重点步骤说明:
步骤1: 获取微信支付商户号:渠道商使用银行或者支付机构提供的API或者后台系统录入商家门店信息,获取商家每个门店在微信支付侧的商户号(上送给微信支付的“商户名称”字段必须与营业执照上商户名称一致,具体规则 点击查看 )。
步骤2: 查询微信支付商户号授权状态:渠道商使用《获取商户号开户意愿确认状态接口》查询微信支付商户号是否完成开户意愿确认。
步骤5: 提交商家资料给微信支付:渠道商根据商家类型(企业、个体户、小微、事业单位、其他组织等)准备好相关的商家资料,使用微信支付接口《提交开户意愿确认申请单》获取微信支付申请单编号。
步骤8: 查询申请单审核结果:渠道商提交商家资料后,建议每隔五分钟调用《查询申请单审核结果接口》查询申请单审核结果。
申请单正常情况下的状态转换如下
提交后申请单状态为“审核中”,微信支付后台会进行审核,审核通过后申请单状态变成“待联系人确认”,同时接口会提供“申请单小程序码” (小程序码的图片)。
联系人扫“申请单小程序码”后确认资料无误后,申请单状态变成“待账户验证”。
联系人将“法人确认二维码”在微信上发给法人确认后(或打款验证),申请单状态变成“审核通过”。
3.2. API接入(含示例代码)
文档展示了如何使用微信支付服务端 SDK 快速接入支付有礼,完成与微信支付对接的部分。
3.2.1. 【服务端】提交申请单
步骤说明: 服务商收集商户资料后,调用提交申请单接口,提交创建入驻申请单。
JAVA
1public void Applyment() throws Exception {
2
3 PrivateKey merchantPrivateKey = PemUtil
4 .loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes("utf-8")));
5
6
7 AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
8 new WechatPay2Credentials(mchId, new PrivateKeySigner(mchSerialNo, merchantPrivateKey)),apiV3Key.getBytes("utf-8"));
9
10 CloseableHttpClient httpClient = HttpClients.createDefault();
11
12 httpClient = WechatPayHttpClientBuilder.create()
13 .withMerchant(mchId, mchSerialNo, merchantPrivateKey)
14 .withValidator(new WechatPay2Validator(verifier)).build();
15
16
17 HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/apply4subject/applyment");
18
19 String reqdata = "{"
20 + "\"business_code\":\"1111111111\","
21 + "\"contact_info\": {"
22 + "\"name\":\"wRNIsXOvVuTYIhVxZJCD8uJIGmNPGozCe44Ph8rD+QAJEPxw==\","
23 + "\"mobile\":\"w+zPKEVNm7IDxPvK55P0OfNd5E5VXoWbRwyyGk37HiB6C/F2lUog==\","
24 + "\"id_card_number\":\"rjbq82xBwMixDGA5A4x6/hqZRAYmaeM+yyjn9BU8qUBZga+mKqQ==\""
25 + "},"
26 + "\"subject_info\": {"
27 + "\"subject_type\":\"SUBJECT_TYPE_ENTERPRISE\","
28 + "\"business_licence_info\": {"
29 + "\"licence_number\":\"914201123033363296\","
30 + "\"licence_copy\":\"0P3ng6KTIW4-Q_l2FjKLZuhHjBWoMAjmVtCz7ScmhEIThCaV4BBgVwtNkCHO_XXqK5dE5YdOmFJBZR9FwczhJehHhAZN6BKXQPcs-VvdSo\","
31 + "\"merchant_name\":\"李四网络有限公司\","
32 + "\"legal_person\":\"李四\","
33 + "\"company_address\":\"广东省深圳市南山区xx路xx号\","
34 + "\"licence_valid_date\":\"["1970-01-01","forever"]\""
35 + "},"
36 + "\"certificate_info\": {"
37 + "\"cert_type\":\"CERTIFICATE_TYPE_2388\","
38 + "\"cert_number\":\"111111111111\","
39 + "\"cert_copy\":\"0P3ng6KTIW4-Q_l2FjKLZuhHjBWoMAjmVtCz7ScmhEIThCaV4BBgVwtNkCHO_XXqK5dE5YdOmFJBZR9FwczhJehHhAZN6BKXQPcs-VvdSo\","
40 + "\"merchant_name\":\"xx公益团体\","
41 + "\"legal_person\":\"李四\","
42 + "\"company_address\":\"广东省深圳市南山区xx路xx号\","
43 + "\"cert_valid_date\":\"["1970-01-01","forever"]\""
44 + "},"
45 + "\"company_prove_copy\":\"0P3ng6KTIW4-Q_l2FjKLZuhHjBWoMAjmVtCz7ScmhEIThCaV4BBgVwtNkCHO_XXqK5dE5YdOmFJBZR9FwczhJehHhAZN6BKXQPcs-VvdSo\","
46 + "\"assist_prove_info\": {"
47 + "\"micro_biz_type\":\"MICRO_TYPE_STORE\","
48 + "\"store_name\":\"大郎烧饼\","
49 + "\"store_address_code\":\"440305\","
50 + "\"store_address\":\"广东省深圳市南山区xx大厦x层xxxx室\","
51 + "\"store_header_copy\":\"0P3ng6KTIW4-Q_l2FjKLZuhHjBWoMAjmVtCz7ScmhEIThCaV-4BBgVwtNkCHO_XXqK5dE5YdOmFJBZR9FwczhJehHhAZN6BKXQPcs-VvdSo\","
52 + "\"store_indoor_copy\":\"0P3ng6KTIW4-Q_l2FjKLZuhHjBWoMAjmVtCz7ScmhEIThCaV4BBgVwtNkCHO_XXqK5dE5YdOmFJBZR9FwczhJehHhAZN6BKXQPcs-VvdSo\""
53 + "}"
54 + "},"
55 + "\"identification_info\": {"
56 + "\"identification_type\":\"IDENTIFICATION_TYPE_IDCARD\","
57 + "\"identification_name\":\"MZnwEx6zotwIz6ctW2/iQL5z94odwP9sKiFRL8Aii3L4U74RPCPztcJOScaXsaGs82HJNU3K+46ndk7prENiPDw==\","
58 + "\"identification_number\":\"ZTnn5dKGCvP4csw4XTLug/+VLB+4R6nxSPQwqSpmPVZtXmye+/3s9O+y32w==\","
59 + "\"identification_valid_date\":\"["1970-01-01","forever"]\","
60 + "\"identification_front_copy\":\"0P3ng6KTIW4-Q_l2FjKLZuhHjBWoMAjmVtCz7ScmhEIThCaV-4BBgVwtNkCHO_XXqK5dE5YdOmFJBZR9FwczhJehHhAZN6BKXQPcs-VvdSo\","
61 + "\"identification_back_copy\":\"0P3ng6KTIW4-Q_l2FjKLZuhHjBWoMAjmVtCz7ScmhEIThCaV4BBgVwtNkCHO_XXqK5dE5YdOmFJBZR9FwczhJehHhAZN6BKXQPcs-VvdSo\""
62 + "},"
63 + "\"addition_info\": {"
64 + "\"confirm_mchid_list\": ["
65 + "\"20001113\","
66 + "\"20001112\""
67 + "]"
68 + "}"
69 + "}";
70 StringEntity entity = new StringEntity(reqdata,"utf-8");
71 entity.setContentType("application/json");
72 httpPost.setEntity(entity);
73 httpPost.setHeader("Accept", "application/json");
74
75
76 CloseableHttpResponse response = httpClient.execute(httpPost);
77
78 try {
79 int statusCode = response.getStatusLine().getStatusCode();
80 if (statusCode == 200) {
81 System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
82 } else if (statusCode == 204) {
83 System.out.println("success");
84 } else {
85 System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
86 throw new IOException("request failed");
87 }
88 } finally {
89 response.close();
90 }
91}
PHP
1try {
2 $resp = $client->request(
3 'POST',
4 'https://api.mch.weixin.qq.com/v3/apply4subject/applyment',
5 [
6
7 'json' => [
8 "business_code" => "1111111111",
9 "contact_info" => [
10 "name" => "wRNIsXOvVuTYIhVxZJCD8uJIGmNPGozCe44Ph8rD+QAJEPxw==",
11 "mobile" => "w+zPKEVNm7IDxPvK55P0OfNd5E5VXoWbRwyyGk37HiB6C/F2lUog==",
12 "id_card_number" => "rjbq82xBwMixDGA5A4x6/hqZRAYmaeM+yyjn9BU8qUBZga+mKqQ==",
13 ],
14 "subject_info" => [
15 "subject_type" => "SUBJECT_TYPE_ENTERPRISE",
16 "business_licence_info" => [
17 "licence_number" => "914201123033363296",
18 "licence_copy" => "0P3ng6KTIW4-Q_l2FjKLZuhHjBWoMAjmVtCz7ScmhEIThCaV4BBgVwtNkCHO_XXqK5dE5YdOmFJBZR9FwczhJehHhAZN6BKXQPcs-VvdSo",
19 "merchant_name" => "李四网络有限公司",
20 "legal_person" => "李四",
21 "company_address" => "广东省深圳市南山区xx路xx号",
22 "licence_valid_date" => "["1970-01-01","forever"]",
23 ],
24 "certificate_info" => [
25 "cert_type" => "CERTIFICATE_TYPE_2388",
26 "cert_number" => "111111111111",
27 "cert_copy" => "0P3ng6KTIW4-Q_l2FjKLZuhHjBWoMAjmVtCz7ScmhEIThCaV4BBgVwtNkCHO_XXqK5dE5YdOmFJBZR9FwczhJehHhAZN6BKXQPcs-VvdSo",
28 "merchant_name" => "xx公益团体",
29 "legal_person" => "李四",
30 "company_address" => "广东省深圳市南山区xx路xx号",
31 "cert_valid_date" => "["1970-01-01","forever"]",
32 ],
33 "company_prove_copy" => "0P3ng6KTIW4-Q_l2FjKLZuhHjBWoMAjmVtCz7ScmhEIThCaV4BBgVwtNkCHO_XXqK5dE5YdOmFJBZR9FwczhJehHhAZN6BKXQPcs-VvdSo",
34 "assist_prove_info" => [
35 "micro_biz_type" => "MICRO_TYPE_STORE",
36 "store_name" => "大郎烧饼",
37 "store_address_code" => "440305",
38 "store_address" => "广东省深圳市南山区xx大厦x层xxxx室",
39 "store_header_copy" => "0P3ng6KTIW4-Q_l2FjKLZuhHjBWoMAjmVtCz7ScmhEIThCaV-4BBgVwtNkCHO_XXqK5dE5YdOmFJBZR9FwczhJehHhAZN6BKXQPcs-VvdSo",
40 "store_indoor_copy" => "0P3ng6KTIW4-Q_l2FjKLZuhHjBWoMAjmVtCz7ScmhEIThCaV4BBgVwtNkCHO_XXqK5dE5YdOmFJBZR9FwczhJehHhAZN6BKXQPcs-VvdSo",
41 ],
42 ],
43 "identification_info" => [
44 "identification_type" => "IDENTIFICATION_TYPE_IDCARD",
45 "identification_name" => "MZnwEx6zotwIz6ctW2/iQL5z94odwP9sKiFRL8Aii3L4U74RPCPztcJOScaXsaGs82HJNU3K+46ndk7prENiPDw==",
46 "identification_number" => "ZTnn5dKGCvP4csw4XTLug/+VLB+4R6nxSPQwqSpmPVZtXmye+/3s9O+y32w==",
47 "identification_valid_date" => "["1970-01-01","forever"]",
48 "identification_front_copy" => "0P3ng6KTIW4-Q_l2FjKLZuhHjBWoMAjmVtCz7ScmhEIThCaV-4BBgVwtNkCHO_XXqK5dE5YdOmFJBZR9FwczhJehHhAZN6BKXQPcs-VvdSo",
49 "identification_back_copy" => "0P3ng6KTIW4-Q_l2FjKLZuhHjBWoMAjmVtCz7ScmhEIThCaV4BBgVwtNkCHO_XXqK5dE5YdOmFJBZR9FwczhJehHhAZN6BKXQPcs-VvdSo",
50 ],
51 "addition_info" => [
52 "confirm_mchid_list" => [
53 "0" => "20001113",
54 "1" => "20001112",
55 ],
56 ]
57 ],
58 'headers' => [ 'Accept' => 'application/json' ]
59 ]
60 );
61 $statusCode = $resp->getStatusCode();
62 if ($statusCode == 200) {
63 echo "success,return body = " . $resp->getBody()->getContents()."\n";
64 } else if ($statusCode == 204) {
65 echo "success";
66 }
67} catch (RequestException $e) {
68
69 echo $e->getMessage()."\n";
70 if ($e->hasResponse()) {
71 echo "failed,resp code = " . $e->getResponse()->getStatusCode() . " return body = " . $e->getResponse()->getBody() . "\n";
72 }
73 return;
74}
重要入参说明:
更多参数、响应详情及错误码请参见提交申请单接口文档。
3.2.2.【服务端】撤销申请单
步骤说明: 服务商提交申请单后需要修改信息时,或者申请单审核结果为“已驳回”时服务商要修改申请材料时,均需要先调用撤销申请单接口。
JAVA
1public void CancelApplyment() throws Exception{
2
3 PrivateKey merchantPrivateKey = PemUtil
4 .loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes("utf-8")));
5
6
7 AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
8 new WechatPay2Credentials(mchId, new PrivateKeySigner(mchSerialNo, merchantPrivateKey)),apiV3Key.getBytes("utf-8"));
9
10 CloseableHttpClient httpClient = HttpClients.createDefault();
11
12 httpClient = WechatPayHttpClientBuilder.create()
13 .withMerchant(mchId, mchSerialNo, merchantPrivateKey)
14 .withValidator(new WechatPay2Validator(verifier)).build();
15
16
17 HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/apply4subject/applyment/20000011111/cancel");
18 StringEntity entity = new StringEntity("");
19 entity.setContentType("application/json");
20 httpPost.setEntity(entity);
21 httpPost.setHeader("Accept", "application/json");
22
23
24 CloseableHttpResponse response = httpClient.execute(httpPost);
25
26 try {
27 int statusCode = response.getStatusLine().getStatusCode();
28 if (statusCode == 200) {
29 System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
30 } else if (statusCode == 204) {
31 System.out.println("success");
32 } else {
33 System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
34 throw new IOException("request failed");
35 }
36 } finally {
37 response.close();
38 }
39}
PHP
1try {
2 $resp = $client->request(
3 'POST',
4 'https://api.mch.weixin.qq.com/v3/apply4subject/applyment/123/cancel',
5 [
6 'headers' => [
7 'Accept' => 'application/json',
8 'Content-Type'=>'application/json'
9
10 ]
11 ]
12 );
13 $statusCode = $resp->getStatusCode();
14 if ($statusCode == 200) {
15 echo "success,return body = " . $resp->getBody()->getContents()."\n";
16 } else if ($statusCode == 204) {
17 echo "success";
18 }
19} catch (RequestException $e) {
20
21 echo $e->getMessage()."\n";
22 if ($e->hasResponse()) {
23 echo "failed,resp code = " . $e->getResponse()->getStatusCode() . " return body = " . $e->getResponse()->getBody() . "\n";
24 }
25 return;
26}
重要入参说明:
更多参数、响应详情及错误码请参见撤销申请单接口文档。
3.2.3. 【服务端】查询申请单审核结果
步骤说明: 查询申请单审核结果。
JAVA
1public void QueryApplyment() throws Exception{
2
3 PrivateKey merchantPrivateKey = PemUtil
4 .loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes("utf-8")));
5
6
7 AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
8 new WechatPay2Credentials(mchId, new PrivateKeySigner(mchSerialNo, merchantPrivateKey)),apiV3Key.getBytes("utf-8"));
9
10 CloseableHttpClient httpClient = HttpClients.createDefault();
11
12 httpClient = WechatPayHttpClientBuilder.create()
13 .withMerchant(mchId, mchSerialNo, merchantPrivateKey)
14 .withValidator(new WechatPay2Validator(verifier)).build();
15
16
17 HttpGet httpGet = new HttpGet("https://api.mch.weixin.qq.com/v3/apply4subject/applyment?applyment_id=20000011111");
18 httpGet.setHeader("Accept", "application/json");
19
20
21 CloseableHttpResponse response = httpClient.execute(httpGet);
22
23 try {
24 int statusCode = response.getStatusLine().getStatusCode();
25 if (statusCode == 200) {
26 System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
27 } else if (statusCode == 204) {
28 System.out.println("success");
29 } else {
30 System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
31 throw new IOException("request failed");
32 }
33 } finally {
34 response.close();
35 }
36}
PHP
1try {
2 $resp = $client->request(
3 'GET',
4 'https://api.mch.weixin.qq.com/v3/apply4subject/applyment?applyment_id=20000011111',
5 [
6 'headers' => [ 'Accept' => 'application/json']
7 ]
8 );
9 $statusCode = $resp->getStatusCode();
10 if ($statusCode == 200) {
11 echo "success,return body = " . $resp->getBody()->getContents()."\n";
12 } else if ($statusCode == 204) {
13 echo "success";
14 }
15} catch (RequestException $e) {
16
17 echo $e->getMessage()."\n";
18 if ($e->hasResponse()) {
19 echo "failed,resp code = " . $e->getResponse()->getStatusCode() . " return body = " . $e->getResponse()->getBody() . "\n";
20 }
21 return;
22}
重要入参说明:
更多参数、响应详情及错误码请参见撤销申请单接口文档。
3.2.4. 【服务端】获取商户开户意愿确认状态
步骤说明: 当服务商需要确认微信支付子商户号是否完成确认时,如果调用此接口提到“已授权”状态,则说明该商户号已完成开户意愿确认。
JAVA
1public void QueryMerchantsState() throws Exception{
2
3 PrivateKey merchantPrivateKey = PemUtil
4 .loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes("utf-8")));
5
6
7 AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
8 new WechatPay2Credentials(mchId, new PrivateKeySigner(mchSerialNo, merchantPrivateKey)),apiV3Key.getBytes("utf-8"));
9
10 CloseableHttpClient httpClient = HttpClients.createDefault();
11
12 httpClient = WechatPayHttpClientBuilder.create()
13 .withMerchant(mchId, mchSerialNo, merchantPrivateKey)
14 .withValidator(new WechatPay2Validator(verifier)).build();
15
16
17 HttpGet httpGet = new HttpGet("https://api.mch.weixin.qq.com/v3/apply4subject/applyment/merchants/20000011111/state");
18 httpGet.setHeader("Accept", "application/json");
19
20
21 CloseableHttpResponse response = httpClient.execute(httpGet);
22
23 try {
24 int statusCode = response.getStatusLine().getStatusCode();
25 if (statusCode == 200) {
26 System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
27 } else if (statusCode == 204) {
28 System.out.println("success");
29 } else {
30 System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
31 throw new IOException("request failed");
32 }
33 } finally {
34 response.close();
35 }
36}
PHP
1try {
2 $resp = $client->request(
3 'GET',
4 'https://api.mch.weixin.qq.com/v3/apply4subject/applyment/merchants/20000011111/state',
5 [
6 'headers' => [ 'Accept' => 'application/json']
7 ]
8 );
9 $statusCode = $resp->getStatusCode();
10 if ($statusCode == 200) {
11 echo "success,return body = " . $resp->getBody()->getContents()."\n";
12 } else if ($statusCode == 204) {
13 echo "success";
14 }
15} catch (RequestException $e) {
16
17 echo $e->getMessage()."\n";
18 if ($e->hasResponse()) {
19 echo "failed,resp code = " . $e->getResponse()->getStatusCode() . " return body = " . $e->getResponse()->getBody() . "\n";
20 }
21 return;
22}
重要入参说明:
更多参数、响应详情及错误码请参见获取商户开户意愿确认状态接口文档。
4. 常见问题
Q1:商户开户意愿调用“提交申请单”返回:暂未查询到该营业执照注册号,请检查营业执照注册号是否填写正确
A1:请求参数“营业执照注册号(licence_number)”填写错误,请填写营业执照上的注册号,若主体类型为个体工商户或企业,注册号格式须为15位数字或18位数字|大写字母。
Q2:商户开户意愿调用“提交申请单”返回:系统繁忙,请稍后重试
A2:请按照以下几点检查:
系统异常,请使用相同参数稍后重新调用;
请求参数错误,请确认参数的大小写、参数名、格式是否与接口文档一致;
请求头里面的参数mchid错误,也会报这个错误,请检查确认。
Q3:商户开户意愿调用“撤消申请单”返回:查询申请单不存在,请检查申请单号是否正确
A3:请求参数申请单编号(applyment_id)填写错误或没有填写,请填写微信支付分配的申请单号,申请单编号和业务申请编号至少传一个。
Q4:商户开户意愿调用“获取特约商户授权状态”返回:Authorization不合法
A4:请按照以下几点检查:
Authorization头认证类型或签名信息错误,请严格按照文档要求填写参数。
Authorization头参数存在换行,实际数据应在一行。
Q5:商户开户意愿调用“提交申请单”返回:商户未申请过证书,请到商户平台上申请证书授权机构颁发的证书
A5:请按照错误提示,到商户平台上申请下载API证书并正确使用,请参考以下几点:
证书获取指引
如何在程序中加载证书
Q6:商户开户意愿调用“撤销申请单”返回:无法将传入参数“申请单编号”转换为uint64类型
A6:请求参数类型填写错误,正确的参数类型是uint64。