1. 接口规则
为了在保证支付安全的前提下,带给商户简单、一致且易用的开发体验,我们推出了全新的微信支付APIv3接口。该版本API的具体规则请参考APIv3接口规则。
2. 开发准备
2.1. 搭建和配置开发环境
开发者应当依据自身的编程语言来构建并配置相应的开发环境。
2.2. 业务开发配置
2.2.1. 服务商开通点金计划
操作路径:【登录微信服务商平台→ 服务商功能 → 点金计划】,点击申请开通即可。
2.2.2. 开通官方小票配置
若仅为特约商户开通点金计划,未开通商家小票功能,该商户JSAPI支付后会展示官方小票样式。
操作路径:【登录微信服务商平台→ 服务商功能 → 点金计划】,在“特约商户管理” 模块中,打开“点金计划”开关。
点击申请开通后进入开通流程,根据指引签署承诺函并填写业务联络人,即可提交申请并开通。
| 注意 服务商也可通过“默认开通”按钮为全量特约商户开通点金计划。如下图所示,在特约商户管理列表 右上角有“默认开通点金计划”开关,打开后,只要特约商户产生jsapi支付,微信支付将自动为其 开通点金计划,无需服务商操作开通。(注:打开该开关后,有jsapi支付的特约商户均会自动开通点金计划,不可单个关闭。若特约商户 无jsapi支付,则不会为其自动打开点金计划。其中,若某些特约商户需使用“商家小票”功能,服务商/渠道商需在点金计划管理页面上或通过API额外为其打开商家小票功能开关。)
微信支付侧提供“点金计划管理API”,供服务商为特约商户批量开通点金计划,具体请查看 点金计划管理API。(注:主动关闭点金计划后,需间隔24 小时方可再次开通)
|
|
2.2.3. 开通商家小票配置
若为特约商户开通点金计划时,已开通了商家小票功能且已按开发文档完成接入,该商户JSAPI支付后会展示商家小票样式。
服务商维度配置商家小票链接
配置路径:【登录微信支付服务商平台→ 服务商功能 → 点金计划】。在“商家小票链接配置” 模块中,点击“添加商家小票链接”:
特约商户维度配置独立商家小票链接
配置路径:【登录微信支付服务商平台→ 服务商功能 → 点金计划】。在“特约商户管理” 模块中,点击“更多”添加“配置特约商户商家小票链接”:
2.2.4. 使用“商家小票调试工具”进行调试
说明: 为了保证商家小票在点金计划页面展示的兼容性、完整性,平台还提供了便捷的商家小票调试工具供服务商进行调试。服务商可通过商家小票调试工具,使用所选链接和真实订单号对点金计划页面的数据交互流程、前端JSAPI 的使用进行调试。
商家小票调试工具路径: 【登录微信支付服务商平台→ 服务商功能 → 点金计划】在“商家小票链接配置” 模块右边,点击“商家小票调试工具”
3. 快速接入
3.1. 业务流程图
步骤11 商家小票页面需调用父页面“onIframeReady”事件的jsapi,请查看《商家小票开发指引》。
在商家小票页面渲染完成后,调用父页面的“onIframeReady”事件的JSAPI,并且从加载商家小票页面开始到调用“onIframeReady”事件的JSAPI之间的用时不可超过3s,否则会提示无法获取订单信息。
3.2. API接入(含示例代码)
文档展示了如何使用微信支付服务端 SDK 快速接入JSAPI支付产品,完成与微信支付对接的部分。
3.2.1. 【服务端】点金计划管理
步骤说明: 服务商使用此接口为特约商户开通或关闭点金计划。
JAVA

1public void GoldPlanStatus() throws Exception{
2
3 HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/goldplan/merchants/changegoldplanstatus");
4
5 String reqdata = "{"
6 + "\"sub_mchid\":\"1234567890\","
7 + "\"operation_type\":\"OPEN\""
8 + "}";
9 StringEntity entity = new StringEntity(reqdata,"utf-8");
10 entity.setContentType("application/json");
11 httpPost.setEntity(entity);
12 httpPost.setHeader("Accept", "application/json");
13
14
15 CloseableHttpResponse response = httpClient.execute(httpPost);
16
17 try {
18 int statusCode = response.getStatusLine().getStatusCode();
19 if (statusCode == 200) {
20 System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
21 } else if (statusCode == 204) {
22 System.out.println("success");
23 } else {
24 System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
25 throw new IOException("request failed");
26 }
27 } finally {
28 response.close();
29 }
30}

1try {
2 $resp = $client->request(
3 'POST',
4 'https://api.mch.weixin.qq.com/v3/goldplan/merchants/changecustompagestatus',
5 [
6
7 'json' => [
8 "sub_mchid" => "1234567890",
9 "operation_type" => "OPEN",
10 ],
11 'headers' => [ 'Accept' => 'application/json' ]
12 ]
13 );
14 $statusCode = $resp->getStatusCode();
15 if ($statusCode == 200) {
16 echo "success,return body = " . $resp->getBody()->getContents()."\n";
17 } else if ($statusCode == 204) {
18 echo "success";
19 }
20} catch (RequestException $e) {
21
22 echo $e->getMessage()."\n";
23 if ($e->hasResponse()) {
24 echo "failed,resp code = " . $e->getResponse()->getStatusCode() . " return body = " . $e->getResponse()->getBody() . "\n";
25 }
26 return;
27}
3.2.2. 【服务端】商家小票管理
步骤说明: 服务商使用此接口为特约商户开通或关闭商家小票功能。
JAVA

1public void CustomPageStatus() throws Exception{
2
3 HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/goldplan/merchants/changecustompagestatus");
4
5 String reqdata = "{"
6 + "\"sub_mchid\":\"1234567890\","
7 + "\"operation_type\":\"OPEN\""
8 + "}";
9 StringEntity entity = new StringEntity(reqdata,"utf-8");
10 entity.setContentType("application/json");
11 httpPost.setEntity(entity);
12 httpPost.setHeader("Accept", "application/json");
13
14
15 CloseableHttpResponse response = httpClient.execute(httpPost);
16
17 try {
18 int statusCode = response.getStatusLine().getStatusCode();
19 if (statusCode == 200) {
20 System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
21 } else if (statusCode == 204) {
22 System.out.println("success");
23 } else {
24 System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
25 throw new IOException("request failed");
26 }
27 } finally {
28 response.close();
29 }
30}

1try {
2 $resp = $client->request(
3 'POST',
4 'https://api.mch.weixin.qq.com/v3/goldplan/merchants/changecustompagestatus',
5 [
6
7 'json' => [
8 "sub_mchid" => "1234567890",
9 "operation_type" => "OPEN",
10 ],
11 'headers' => [ 'Accept' => 'application/json' ]
12 ]
13 );
14 $statusCode = $resp->getStatusCode();
15 if ($statusCode == 200) {
16 echo "success,return body = " . $resp->getBody()->getContents()."\n";
17 } else if ($statusCode == 204) {
18 echo "success";
19 }
20} catch (RequestException $e) {
21
22 echo $e->getMessage()."\n";
23 if ($e->hasResponse()) {
24 echo "failed,resp code = " . $e->getResponse()->getStatusCode() . " return body = " . $e->getResponse()->getBody() . "\n";
25 }
26 return;
27}
重要入参说明:
3.2.3. 【服务端】同业过滤标签管理
步骤说明: 服务商使用此接口为特约商户配置同业过滤标签,防止特约商户支付后出现同行业的广告内容。
JAVA

1public void AdvertisingFilter() 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/goldplan/merchants/set-advertising-industry-filter");
18
19 String reqdata = "{"
20 + "\"sub_mchid\":\"1900000109\","
21 + "\"advertising_industry_filters\": ["
22 + "\"SOFTWARE\","
23 + "\"SECURITY\","
24 + "\"LOVE_MARRIAGE\""
25 + "]"
26 + "}";
27 StringEntity entity = new StringEntity(reqdata,"utf-8");
28 entity.setContentType("application/json");
29 httpPost.setEntity(entity);
30 httpPost.setHeader("Accept", "application/json");
31
32
33 CloseableHttpResponse response = httpClient.execute(httpPost);
34
35 try {
36 int statusCode = response.getStatusLine().getStatusCode();
37 if (statusCode == 200) {
38 System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
39 } else if (statusCode == 204) {
40 System.out.println("success");
41 } else {
42 System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
43 throw new IOException("request failed");
44 }
45 } finally {
46 response.close();
47 }
48}

1try {
2 $resp = $client->request(
3 'POST',
4 'https://api.mch.weixin.qq.com/v3/goldplan/merchants/set-advertising-industry-filter',
5 [
6
7 'json' => [
8 "sub_mchid" => "1900000109",
9 "advertising_industry_filters" => [
10 "0" => "SOFTWARE",
11 "1" => "SECURITY",
12 "2" => "LOVE_MARRIAGE",
13 ]
14 ],
15 'headers' => [ 'Accept' => 'application/json' ]
16 ]
17 );
18 $statusCode = $resp->getStatusCode();
19 if ($statusCode == 200) {
20 echo "success,return body = " . $resp->getBody()->getContents()."\n";
21 } else if ($statusCode == 204) {
22 echo "success";
23 }
24} catch (RequestException $e) {
25
26 echo $e->getMessage()."\n";
27 if ($e->hasResponse()) {
28 echo "failed,resp code = " . $e->getResponse()->getStatusCode() . " return body = " . $e->getResponse()->getBody() . "\n";
29 }
30 return;
31}
重要入参说明:
3.2.4. 【服务端】开通广告展示
步骤说明: 服务商使用此接口为特约商户开通或关闭点金计划。
JAVA

1public void OpenAdvShow() throws Exception{
2
3 HttpPatch httpPatch = new HttpPatch("https://api.mch.weixin.qq.com/v3/goldplan/merchants/open-advertising-show");
4
5 String reqdata = "{"
6 + "\"sub_mchid\":\"1900000109\","
7 + "\"advertising_industry_filters\": ["
8 + "\"0\":\"SOFTWARE\","
9 + "\"1\":\"SECURITY\","
10 + "\"2\":\"LOVE_MARRIAGE\""
11 + "]"
12 + "}";
13 StringEntity entity = new StringEntity(reqdata,"utf-8");
14 entity.setContentType("application/json");
15 httpPatch.setEntity(entity);
16 httpPatch.setHeader("Accept", "application/json");
17
18
19 CloseableHttpResponse response = httpClient.execute(httpPatch);
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) {
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}

1try {
2 $resp = $client->request(
3 'PATCH',
4 'https://api.mch.weixin.qq.com/v3/goldplan/merchants/open-advertising-show',
5 [
6
7 'json' => [
8 "sub_mchid" => "1900000109",
9 "advertising_industry_filters" => [
10 "0" => "SOFTWARE",
11 "1" => "SECURITY",
12 "2" => "LOVE_MARRIAGE",
13 ]
14 ],
15 'headers' => [ 'Accept' => 'application/json' ]
16 ]
17 );
18 $statusCode = $resp->getStatusCode();
19 if ($statusCode == 200) {
20 echo "success,return body = " . $resp->getBody()->getContents()."\n";
21 } else if ($statusCode == 204) {
22 echo "success";
23 }
24} catch (RequestException $e) {
25
26 echo $e->getMessage()."\n";
27 if ($e->hasResponse()) {
28 echo "failed,resp code = " . $e->getResponse()->getStatusCode() . " return body = " . $e->getResponse()->getBody() . "\n";
29 }
30 return;
31}
重要入参说明:
3.2.5. 【服务端】关闭广告展示
步骤说明: 使用此接口为特约商户的点金计划页面关闭广告展示功能。
JAVA

1public void CloseAdvShow() throws Exception{
2
3 HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/goldplan/merchants/close-advertising-show");
4
5 String reqdata = "{"
6 + "\"sub_mchid\":\"1900000109\""
7 + "}";
8 StringEntity entity = new StringEntity(reqdata,"utf-8");
9 entity.setContentType("application/json");
10 httpPost.setEntity(entity);
11 httpPost.setHeader("Accept", "application/json");
12
13
14 CloseableHttpResponse response = httpClient.execute(httpPost);
15
16 try {
17 int statusCode = response.getStatusLine().getStatusCode();
18 if (statusCode == 200) {
19 System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
20 } else if (statusCode == 204) {
21 System.out.println("success");
22 } else {
23 System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity()));
24 throw new IOException("request failed");
25 }
26 } finally {
27 response.close();
28 }
29}

1try {
2 $resp = $client->request(
3 'POST',
4 'https://api.mch.weixin.qq.com/v3/goldplan/merchants/close-advertising-show',
5 [
6
7 'json' => [
8 "sub_mchid" => "1900000109",
9 ],
10 'headers' => [ 'Accept' => 'application/json' ]
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}
重要入参说明:
4. 常见问题
Q:为特约商户开通/关闭点金计划后,多久后会生效?
A:为特约商户开通后,5分钟内其支付回调页会替换为点金计划页面。
Q:为什么看不到“商家小票”开关?
A:需要在商家小票链接配置模块,添加商家小票链接,才会在特约商户管理模块出现“商家小票”开关。
Q:调试商家小票时出现“无法获取订单信息”页面,是什么原因导致的?
已打开特约商户的商家小票及点金计划开关;
商家小票页面需调用父页面“onIframeReady事件”的jsapi,具体请查看商家小票开发指引;
从加载商家小票到调用JSAPI之间的用时不可超过3s;
调试时,扫描二维码的微信号和支付该笔测试订单的微信号需为同一个;
商家小票页面可正常访问。
Q:服务商返佣具体怎么计算?10003”
A:返佣奖励(元)=eCPM(元)/1000 *支付后广告曝光量 。其中:
Q:特约商户开通了点金计划后,支付后页面的展示形式?
A:开通点金计划之后,用户在支付完成页点击“完成”后,只会展示点金计划页面,不会再展示服务商的支付回调页。无须担心业务内容被阻断,可通过点金计划页面的“商家小票”功能嵌入商家的服务性内容(例如取餐码、停车剩余时长等)。