支付即服務(wù)開發(fā)指引
1. 接口規(guī)則
為了在保證支付安全的前提下,帶給商戶簡單、一致且易用的開發(fā)體驗(yàn),我們推出了全新的微信支付APIv3接口。該版本API的具體規(guī)則請參考“APIv3接口規(guī)則”
備注:當(dāng)前接口用于微信國內(nèi)錢包
2. 開發(fā)準(zhǔn)備
2.1. 搭建和配置開發(fā)環(huán)境
為了幫助開發(fā)者調(diào)用開放接口,我們提供了JAVA、PHP、GO三種語言版本的開發(fā)庫,封裝了簽名生成、簽名驗(yàn)證、敏感信息加/解密、媒體文件上傳等基礎(chǔ)功能(更多語言版本的開發(fā)庫將在近期陸續(xù)提供)
測試步驟:
1、根據(jù)自身開發(fā)語言,選擇對應(yīng)的開發(fā)庫并構(gòu)建項(xiàng)目,具體配置請參考下面鏈接的詳細(xì)說明:
? wechatpay-java(推薦)wechatpay-apache-httpclient,適用于Java開發(fā)者。
? wechatpay-php(推薦)、wechatpay-guzzle-middleware,適用于PHP開發(fā)者
注:當(dāng)前開發(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();
}
use GuzzleHttp\Exception\RequestException;
use WechatPay\GuzzleMiddleware\WechatPayMiddleware;
use WechatPay\GuzzleMiddleware\Util\PemUtil;
use GuzzleHttp\HandlerStack;
// 商戶相關(guān)配置,
$merchantId = '1000100'; // 商戶號
$merchantSerialNumber = 'XXXXXXXXXX'; // 商戶API證書序列號
$merchantPrivateKey = PemUtil::loadPrivateKey('./path/to/mch/private/key.pem'); // 商戶私鑰文件路徑
// 微信支付平臺配置
$wechatpayCertificate = PemUtil::loadCertificate('./path/to/wechatpay/cert.pem'); // 微信支付平臺證書文件路徑
// 構(gòu)造一個(gè)WechatPayMiddleware
$wechatpayMiddleware = WechatPayMiddleware::builder()
->withMerchant($merchantId, $merchantSerialNumber, $merchantPrivateKey) // 傳入商戶相關(guān)配置
->withWechatPay([ $wechatpayCertificate ]) // 可傳入多個(gè)微信支付平臺證書,參數(shù)類型為array
->build();
// 將WechatPayMiddleware添加到Guzzle的HandlerStack中
$stack = GuzzleHttp\HandlerStack::create();
$stack->push($wechatpayMiddleware, 'wechatpay');
// 創(chuàng)建Guzzle HTTP Client時(shí),將HandlerStack傳入,接下來,正常使用Guzzle發(fā)起API請求,WechatPayMiddleware會自動地處理簽名和驗(yàn)簽
$client = new GuzzleHttp\Client(['handler' => $stack]);
/*
Package core 微信支付api v3 go http-client 基礎(chǔ)庫,你可以使用它來創(chuàng)建一個(gè)client,并向微信支付發(fā)送http請求
只需要你在初始化客戶端的時(shí)候,傳遞credential以及validator
credential用來生成http header中的authorization信息
validator則用來校驗(yàn)回包是否被篡改
如果http請求返回的err為nil,一般response.Body 都不為空,你可以嘗試對其進(jìn)行序列化
請注意及時(shí)關(guān)閉response.Body
注意:使用微信支付apiv3 go庫需要引入相關(guān)的包,該示例代碼必須引入的包名有以下信息
"context"
"crypto/x509"
"fmt"
"io/ioutil"
"log"
"github.com/wechatpay-apiv3/wechatpay-go/core"
"github.com/wechatpay-apiv3/wechatpay-go/core/option"
"github.com/wechatpay-apiv3/wechatpay-go/utils"
*/
func SetUp() (opt []option.ClientOption, err error) {
//商戶號
mchID := ""
//商戶證書序列號
mchCertSerialNumber := ""
//商戶私鑰文件路徑
privateKeyPath := ""
//平臺證書文件路徑
wechatCertificatePath := ""
// 加載商戶私鑰
privateKey, err := utils.LoadPrivateKeyWithPath(privateKeyPath)
if err != nil {
log.Printf("load private err:%s", err.Error())
return nil, err
}
// 加載微信支付平臺證書
wechatPayCertificate, err := utils.LoadCertificateWithPath(wechatCertificatePath)
if err != nil {
log.Printf("load certificate err:%s",err)
return nil, err
}
//設(shè)置header頭中authorization信息
opts := []option.ClientOption{
option.WithMerchant(mchID, mchCertSerialNumber, privateKey), // 設(shè)置商戶相關(guān)配置
option.WithWechatPay([]*x509.Certificate{wechatPayCertificate}), // 設(shè)置微信支付平臺證書,用于校驗(yàn)回包信息用
}
return opts, nil
}
3、基于接口的示例代碼,替換請求參數(shù)后可發(fā)起測試
說明:
? 上面的開發(fā)庫為微信支付官方開發(fā)庫,其它沒有審核或者控制下的第三方工具和庫,微信支付不保證它們的安全性和可靠性
通過包管理工具引入SDK后,可根據(jù)下面每個(gè)接口的示例代碼替換相關(guān)參數(shù)后進(jìn)行快速測試
? 開發(fā)者如果想詳細(xì)了解簽名生成、簽名驗(yàn)證、敏感信息加/解密、媒體文件上傳等常用方法的具體代碼實(shí)現(xiàn),可閱讀下面的詳細(xì)說明:
1.簽名生成
2.簽名驗(yàn)證
3.敏感信息加解密
4.merchantPrivateKey(私鑰)
5.wechatpayCertificates(平臺證書)
6.APIV3Key(V3 key)
? 如想更詳細(xì)的了解我們的接口規(guī)則,可查看我們的接口規(guī)則指引文檔
2.2. 業(yè)務(wù)開發(fā)配置
1、登錄【微信支付商戶平臺】后,通過路徑【產(chǎn)品中心—>我的產(chǎn)品—>支付即服務(wù)—>產(chǎn)品設(shè)置】,即可開通支付即服務(wù),開通后完成產(chǎn)品設(shè)置。
2、【產(chǎn)品設(shè)置】頁面如下圖所示,具體內(nèi)容包括上傳商家logo、選擇服務(wù)人員名稱及選擇名片功能模塊。
3. 快速接入
3.1. 業(yè)務(wù)流程圖
重點(diǎn)步驟說明:
步驟6 使用企業(yè)微信的商戶,通過《服務(wù)人員注冊API》接口傳入服務(wù)人員信息進(jìn)行注冊,微信支付返回服務(wù)人員ID給到商戶,商戶需將服務(wù)人員注冊信息和對應(yīng)的服務(wù)人員ID進(jìn)行妥善保存。
步驟11 商戶在下單時(shí)生成商戶訂單號,接著調(diào)用《服務(wù)人員分配API》傳入“商戶訂單號+服務(wù)人員ID”,隨后按照原有流程和支付接口完成支付即可。
3.2. API接入(含示例代碼)
文檔展示了如何使用微信支付服務(wù)端 SDK 快速接入支付即服務(wù)產(chǎn)品,完成與微信支付對接的部分。
注意:
- 文檔中的代碼示例是用來闡述 API 基本使用方法,代碼中的示例參數(shù)需替換成商戶自己賬號及請求參數(shù)才能跑通。
- 以下接入步驟僅提供參考,請商戶結(jié)合自身業(yè)務(wù)需求進(jìn)行評估、修改。
3.2.1. 【服務(wù)端】服務(wù)人員注冊
步驟說明:服務(wù)人員注冊接口用于商戶開發(fā)者為商戶注冊服務(wù)人員使用。
注意:
- 調(diào)用接口前商家需完成支付即服務(wù)產(chǎn)品的開通和設(shè)置。若服務(wù)商為特約商戶調(diào)用接口,需在特約商戶開通并完成產(chǎn)品設(shè)置后,與特約商戶建立產(chǎn)品授權(quán)關(guān)系。
示例代碼
public void RegSmartGuide() throws Exception{
//請求URL
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/smartguide/guides");
// 請求body參數(shù)
String reqdata = "{"
+ "\"store_id\":1234,"
+ "\"corpid\":\"1234567890\","
+ "\"name\":\"pVd1HJ6v/69bDnuC4EL5Kz4jBHLiCa8MRtelw/wDa4SzfeespQO/0kjiwfqdfg==\","
+ "\"mobile\":\"pVd1HJ6v/69bDnuC4EL5Kz4jBHLiCa8MRtelw/wDa4SzfeespQO/0kjiwfqdfg==\","
+ "\"qr_code\":\"https://open.work.weixin.qq.com/wwopen/userQRCode?vcode=xxx\","
+ "\"avatar\":\"https://wx.qlogo.cn/mmopen/ajNVdqHZLLA3WJ6DSZUfiakYe37PKnQhBIeOQBO4czqrnZDS79FH5Wm5m4X69TBicnHFlhiafvDwklOpZeXYQQ2icg/0\","
+ "\"group_qrcode\":\"https://p.qpic.cn/wwhead/nMl9ssowtibVGyrmvBiaibzDtp/0\","
+ "\"userid\":\"robert\""
+ "}";
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();
}
}
try {
$resp = $client->request(
'POST',
'https://api.mch.weixin.qq.com/v3/smartguide/guides', //請求URL
[
// JSON請求體
'json' => [
"store_id" => 1234,
"corpid" => "1234567890",
"name" => "pVd1HJ6v/69bDnuC4EL5Kz4jBHLiCa8MRtelw/wDa4SzfeespQO/0kjiwfqdfg==",
"mobile" => "pVd1HJ6v/69bDnuC4EL5Kz4jBHLiCa8MRtelw/wDa4SzfeespQO/0kjiwfqdfg==",
"qr_code" => "https://open.work.weixin.qq.com/wwopen/userQRCode?vcode=xxx",
"avatar" => "https://wx.qlogo.cn/mmopen/ajNVdqHZLLA3WJ6DSZUfiakYe37PKnQhBIeOQBO4czqrnZDS79FH5Wm5m4X69TBicnHFlhiafvDwklOpZeXYQQ2icg/0",
"group_qrcode" => "https://p.qpic.cn/wwhead/nMl9ssowtibVGyrmvBiaibzDtp/0",
"userid" => "robert",
],
'headers' => [ 'Accept' => 'application/json' ]
]
);
$statusCode = $resp->getStatusCode();
if ($statusCode == 200) { //處理成功
echo "success,return body = " . $resp->getBody()->getContents()."\n";
} else if ($statusCode == 204) { //處理成功,無返回Body
echo "success";
}
} catch (RequestException $e) {
// 進(jìn)行錯(cuò)誤處理
echo $e->getMessage()."\n";
if ($e->hasResponse()) {
echo "failed,resp code = " . $e->getResponse()->getStatusCode() . " return body = " . $e->getResponse()->getBody() . "\n";
}
return;
}
//此處請求頭需增加序列號
func RegSmartGuide() {
// 初始化客戶端
ctx := context.TODO()
opts, err := SetUp()
if err != nil {
return
}
client, err := core.NewClient(ctx, opts...,)
if err != nil{
log.Printf("init client err:%s",err)
return
}
//設(shè)置請求地址
URL := "https://api.mch.weixin.qq.com/v3/smartguide/guides"
//設(shè)置請求信息,此處也可以使用結(jié)構(gòu)體來進(jìn)行請求
mapInfo := map[string]interface{}{
"store_id": 1234,
"corpid": "1234567890",
"name": "pVd1HJ6v/69bDnuC4EL5Kz4jBHLiCa8MRtelw/wDa4SzfeespQO/0kjiwfqdfg==",
"mobile": "pVd1HJ6v/69bDnuC4EL5Kz4jBHLiCa8MRtelw/wDa4SzfeespQO/0kjiwfqdfg==",
"qr_code": "https://open.work.weixin.qq.com/wwopen/userQRCode?vcode=xxx",
"avatar": "https://wx.qlogo.cn/mmopen/ajNVdqHZLLA3WJ6DSZUfiakYe37PKnQhBIeOQBO4czqrnZDS79FH5Wm5m4X69TBicnHFlhiafvDwklOpZeXYQQ2icg/0",
"group_qrcode": "https://p.qpic.cn/wwhead/nMl9ssowtibVGyrmvBiaibzDtp/0",
"userid": "robert",
}
// 發(fā)起請求
response, err := client.Post(ctx, URL, mapInfo)
if err != nil{
log.Printf("client post err:%s",err)
return
}
// 校驗(yàn)回包內(nèi)容是否有邏輯錯(cuò)誤
err = core.CheckResponse(response)
if err != nil{
log.Printf("check response err:%s",err)
return
}
// 讀取回包信息
body, err := ioutil.ReadAll(response.Body)
if err != nil{
log.Printf("read response body err:%s",err)
return
}
fmt.Println(string(body))
}
重要入?yún)⒄f明:
? store_id:門店在微信支付商戶平臺的唯一標(biāo)識(查找路徑:登錄商戶平臺—>營銷中心—>門店管理,若無門店則需先創(chuàng)建門店)
? name:員工在商戶企業(yè)微信通訊錄上的姓名,需使用微信支付平臺公鑰加密該字段需進(jìn)行加密處理,加密方法詳見敏感信息加密說明。特殊規(guī)則:加密前字段長度限制為64個(gè)字節(jié)
更多參數(shù)、響應(yīng)詳情及錯(cuò)誤碼請參見服務(wù)人員注冊API接口文檔
3.2.2.【服務(wù)端】服務(wù)人員分配
步驟說明:服務(wù)人員分配接口用于商戶開發(fā)者在顧客下單后為顧客分配服務(wù)人員使用。
注意:
調(diào)用服務(wù)人員分配接口需在完成支付之前,若分配服務(wù)人員晚于支付完成,則將無法在支付憑證上出現(xiàn)服務(wù)人員名片入口。
示例代碼:
public void AssignGuide() throws Exception{
//請求URL
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/smartguide/guides/LLA3WJ6DSZUfiaZDS79FH5Wm5m4X69TBic/assign");
// 請求body參數(shù)
String reqdata = "{"
+ "\"out_trade_no\":\"20150806125346\""
+ "}";
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();
}
}
try {
$resp = $client->request(
'POST',
'https://api.mch.weixin.qq.com/v3/smartguide/guides/LLA3WJ6DSZUfiaZDS79FH5Wm5m4X69TBic/assign', //請求URL
[
// JSON請求體
'json' => [
"out_trade_no" => "20150806125346",
],
'headers' => [ 'Accept' => 'application/json' ]
]
);
$statusCode = $resp->getStatusCode();
if ($statusCode == 200) { //處理成功
echo "success,return body = " . $resp->getBody()->getContents()."\n";
} else if ($statusCode == 204) { //處理成功,無返回Body
echo "success";
}
} catch (RequestException $e) {
// 進(jìn)行錯(cuò)誤處理
echo $e->getMessage()."\n";
if ($e->hasResponse()) {
echo "failed,resp code = " . $e->getResponse()->getStatusCode() . " return body = " . $e->getResponse()->getBody() . "\n";
}
return;
}
func AssignGuide() {
// 初始化客戶端
ctx := context.TODO()
opts, err := SetUp()
if err != nil {
return
}
client, err := core.NewClient(ctx, opts...,)
if err != nil{
log.Printf("init client err:%s",err)
return
}
//設(shè)置請求地址
URL := "https://api.mch.weixin.qq.com/v3/smartguide/guides/LLA3WJ6DSZUfiaZDS79FH5Wm5m4X69TBic/assign"
//設(shè)置請求信息,此處也可以使用結(jié)構(gòu)體來進(jìn)行請求
mapInfo := map[string]interface{}{
"out_trade_no": "20150806125346",
}
// 發(fā)起請求
response, err := client.Post(ctx, URL, mapInfo)
if err != nil{
log.Printf("client post err:%s",err)
return
}
// 校驗(yàn)回包內(nèi)容是否有邏輯錯(cuò)誤
err = core.CheckResponse(response)
if err != nil{
log.Printf("check response err:%s",err)
return
}
// 讀取回包信息
body, err := ioutil.ReadAll(response.Body)
if err != nil{
log.Printf("read response body err:%s",err)
return
}
fmt.Println(string(body))
}
重要入?yún)⒄f明:
? out_trade_no:商戶系統(tǒng)內(nèi)部訂單號,要求32個(gè)字符內(nèi),僅支持使用字母、數(shù)字、中劃線-、下劃線_、豎線|、星號*這些英文半角字符的組合,請勿使用漢字或全角等特殊字符,且在同一個(gè)商戶號下唯一。
更多參數(shù)、響應(yīng)詳情及錯(cuò)誤碼請參見服務(wù)人員分配API接口文檔
3.2.3.【服務(wù)端】服務(wù)人員查詢
步驟說明:服務(wù)人員查詢接口用于商戶開發(fā)者查詢已注冊的服務(wù)人員ID等信息。
注意:
個(gè)人微信商家
傳入門店ID,查詢該門店下的所有已注冊服務(wù)人員的信息(每次查詢不可超過10條)
傳入服務(wù)人員的工號(服務(wù)人員注冊時(shí)填寫)或手機(jī)號,查詢單個(gè)服務(wù)人員的信息。
企業(yè)微信商家
傳入門店ID,查詢該門店下的所有已注冊服務(wù)人員的信息(每次查詢不可超過10條)
傳入服務(wù)人員的企業(yè)微信員工ID或手機(jī)號,查詢單個(gè)服務(wù)人員的信息。
服務(wù)人員注冊API和查詢API請求URL相同,區(qū)別主要是在body和query,請注意區(qū)分。
示例代碼:
public void QueryGuide() throws Exception{
//請求URL
HttpGet httpGet = new HttpGet("https://api.mch.weixin.qq.com/v3/smartguide/guides?store_id=1234");
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();
}
}
try {
$resp = $client->request(
'GET',
'https://api.mch.weixin.qq.com/v3/smartguide/guides?store_id=1234', //請求URL
[
'headers' => [ 'Accept' => 'application/json']
]
);
$statusCode = $resp->getStatusCode();
if ($statusCode == 200) { //處理成功
echo "success,return body = " . $resp->getBody()->getContents()."\n";
} else if ($statusCode == 204) { //處理成功,無返回Body
echo "success";
}
} catch (RequestException $e) {
// 進(jìn)行錯(cuò)誤處理
echo $e->getMessage()."\n";
if ($e->hasResponse()) {
echo "failed,resp code = " . $e->getResponse()->getStatusCode() . " return body = " . $e->getResponse()->getBody() . "\n";
}
return;
}
func QueryGuide() {
// 初始化客戶端
ctx := context.TODO()
opts, err := SetUp()
if err != nil {
return
}
client, err := core.NewClient(ctx, opts...,)
if err != nil{
log.Printf("init client err:%s",err)
return
}
//設(shè)置請求地址
URL := "https://api.mch.weixin.qq.com/v3/smartguide/guides?store_id=1234"
// 發(fā)起請求
response, err := client.Get(ctx, URL)
if err != nil{
log.Printf("client get err:%s",err)
return
}
// 校驗(yàn)回包內(nèi)容是否有邏輯錯(cuò)誤
err = core.CheckResponse(response)
if err != nil{
log.Printf("check response err:%s",err)
return
}
// 讀取回包信息
body, err := ioutil.ReadAll(response.Body)
if err != nil{
log.Printf("read response body err:%s",err)
return
}
fmt.Println(string(body))
}
重要入?yún)⒄f明:
? userid:員工在商戶企業(yè)微信通訊錄使用的唯一標(biāo)識,企業(yè)微信商家可傳入該字段查詢單個(gè)服務(wù)人員信息;不傳則查詢整個(gè)門店下的服務(wù)人員信息。
更多參數(shù)、響應(yīng)詳情及錯(cuò)誤碼請參見服務(wù)人員查詢API接口文檔
3.2.4.【服務(wù)端】服務(wù)人員信息更新
步驟說明:服務(wù)人員信息更新接口用于商戶開發(fā)者為商戶更新門店服務(wù)人員的姓名、頭像等信息。
注意:
個(gè)人微信商家、企業(yè)微信商家均支持服務(wù)人員信息更新
示例代碼:
public void UpdateGuide() throws Exception{
//請求URL
HttpPatch httpPatch = new HttpPatch("https://api.mch.weixin.qq.com/v3/smartguide/guides/LLA3WJ6DSZUfiaZDS79FH5Wm5m4X69TBic");
// 請求body參數(shù)
String reqdata = "{"
+ "\"name\":\"pVd1HJ6v/69bDnuC4EL5Kz4jBHLiCa8MRtelw/wDa4SzfeespQO/0kjiwfqdfg==\","
+ "\"mobile\":\"pVd1HJ6v/69bDnuC4EL5Kz4jBHLiCa8MRtelw/wDa4SzfeespQO/0kjiwfqdfg==\","
+ "\"qr_code\":\"https://open.work.weixin.qq.com/wwopen/userQRCode?vcode=xxx\","
+ "\"avatar\":\"https://wx.qlogo.cn/mmopen/ajNVdqHZLLA3WJ6DSZUfiakYe37PKnQhBIeOQBO4czqrnZDS79FH5Wm5m4X69TBicnHFlhiafvDwklOpZeXYQQ2icg/0\","
+ "\"group_qrcode\":\"https://p.qpic.cn/wwhead/nMl9ssowtibVGyrmvBiaibzDtp/0\""
+ "}";
StringEntity entity = new StringEntity(reqdata,"utf-8");
entity.setContentType("application/json");
httpPatch.setEntity(entity);
httpPatch.setHeader("Accept", "application/json");
//完成簽名并執(zhí)行請求
CloseableHttpResponse response = httpClient.execute(httpPatch);
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();
}
}
try {
$resp = $client->request(
'PATCH',
'https://api.mch.weixin.qq.com/v3/smartguide/guides/LLA3WJ6DSZUfiaZDS79FH5Wm5m4X69TBic', //請求URL
[
// JSON請求體
'json' => [
"name" => "pVd1HJ6v/69bDnuC4EL5Kz4jBHLiCa8MRtelw/wDa4SzfeespQO/0kjiwfqdfg==",
"mobile" => "pVd1HJ6v/69bDnuC4EL5Kz4jBHLiCa8MRtelw/wDa4SzfeespQO/0kjiwfqdfg==",
"qr_code" => "https://open.work.weixin.qq.com/wwopen/userQRCode?vcode=xxx",
"avatar" => "https://wx.qlogo.cn/mmopen/ajNVdqHZLLA3WJ6DSZUfiakYe37PKnQhBIeOQBO4czqrnZDS79FH5Wm5m4X69TBicnHFlhiafvDwklOpZeXYQQ2icg/0",
"group_qrcode" => "https://p.qpic.cn/wwhead/nMl9ssowtibVGyrmvBiaibzDtp/0",
],
'headers' => [ 'Accept' => 'application/json' ]
]
);
$statusCode = $resp->getStatusCode();
if ($statusCode == 200) { //處理成功
echo "success,return body = " . $resp->getBody()->getContents()."\n";
} else if ($statusCode == 204) { //處理成功,無返回Body
echo "success";
}
} catch (RequestException $e) {
// 進(jìn)行錯(cuò)誤處理
echo $e->getMessage()."\n";
if ($e->hasResponse()) {
echo "failed,resp code = " . $e->getResponse()->getStatusCode() . " return body = " . $e->getResponse()->getBody() . "\n";
}
return;
}
//此處請求頭需增加序列號
func UpdateGuide() {
// 初始化客戶端
ctx := context.TODO()
opts, err := SetUp()
if err != nil {
return
}
client, err := core.NewClient(ctx, opts...,)
if err != nil{
log.Printf("init client err:%s",err)
return
}
//設(shè)置請求地址
URL := "https://api.mch.weixin.qq.com/v3/smartguide/guides/LLA3WJ6DSZUfiaZDS79FH5Wm5m4X69TBic"
//設(shè)置請求信息,此處也可以使用結(jié)構(gòu)體來進(jìn)行請求
mapInfo := map[string]interface{}{
"name": "pVd1HJ6v/69bDnuC4EL5Kz4jBHLiCa8MRtelw/wDa4SzfeespQO/0kjiwfqdfg==",
"mobile": "pVd1HJ6v/69bDnuC4EL5Kz4jBHLiCa8MRtelw/wDa4SzfeespQO/0kjiwfqdfg==",
"qr_code": "https://open.work.weixin.qq.com/wwopen/userQRCode?vcode=xxx",
"avatar": "https://wx.qlogo.cn/mmopen/ajNVdqHZLLA3WJ6DSZUfiakYe37PKnQhBIeOQBO4czqrnZDS79FH5Wm5m4X69TBicnHFlhiafvDwklOpZeXYQQ2icg/0",
"group_qrcode": "https://p.qpic.cn/wwhead/nMl9ssowtibVGyrmvBiaibzDtp/0",
}
// 發(fā)起請求
response, err := client.Patch(ctx, URL, mapInfo)
if err != nil{
log.Printf("client patch err:%s",err)
return
}
// 校驗(yàn)回包內(nèi)容是否有邏輯錯(cuò)誤
err = core.CheckResponse(response)
if err != nil{
log.Printf("check response err:%s",err)
return
}
// 讀取回包信息
body, err := ioutil.ReadAll(response.Body)
if err != nil{
log.Printf("read response body err:%s",err)
return
}
fmt.Println(string(body))
}
重要入?yún)⒄f明:
? guide_id:服務(wù)人員在支付即服務(wù)系統(tǒng)中的唯一標(biāo)識。
更多參數(shù)、響應(yīng)詳情及錯(cuò)誤碼請參見服務(wù)人員信息更新API接口文檔
4. 常見問題
Q:企業(yè)微信的corpid如何獲取?
A:獲取corpid可進(jìn)入企業(yè)微信的管理后臺,查找路徑:【我的企業(yè)->企業(yè)信息→查看“企業(yè)ID”】(需要有管理員權(quán)限)
Q:注冊服務(wù)人員時(shí)必須傳入門店ID嗎?在哪里找這個(gè)門店ID
A:是的,注冊時(shí)必須傳入門店ID。該門店ID是微信支付門店系統(tǒng)的編碼,查找路徑:【登錄商戶平臺->營銷中心→門店管理】,門店管理頁面下的門店編號即為需要填寫的門店ID(該門店信息與企業(yè)微信的門店系統(tǒng)無關(guān))。
若未創(chuàng)建門店,則需創(chuàng)建門店并通過騰訊地圖審核后,方可使用門店ID進(jìn)行注冊。
Q:調(diào)用服務(wù)人員分配接口是在支付前還是支付后?
A:支付前。建議當(dāng)商家生成當(dāng)前交易的“商戶訂單號”時(shí),通過“服務(wù)人員分配API”將“服務(wù)人員ID+商戶訂單號”傳給微信支付,并按照原有流程引導(dǎo)用戶完成支付即可。若分配服務(wù)人員晚于支付完成,則將無法在支付憑證上出現(xiàn)服務(wù)人員名片入口
Q:服務(wù)人員分配應(yīng)該采取什么樣的分配機(jī)制?
A:使用服務(wù)人員分配API進(jìn)行分配時(shí),服務(wù)人員的分配機(jī)制由商家內(nèi)部閉環(huán),可以靈活掌控。在支付前調(diào)用分配接口時(shí),商家可自行決定分配哪名服務(wù)人員,商家可選擇隨機(jī)分配、按時(shí)間段分配,或?yàn)槟彻P訂單指定特定服務(wù)人員的分配方式(例如在線下門店支付時(shí),可分配當(dāng)前為該顧客提供服務(wù)的服務(wù)人員)。使用免開發(fā)版本時(shí),商戶號下的所有訂單將隨機(jī)分配給不同服務(wù)人員,商家可通過小程序調(diào)整服務(wù)人員分配的時(shí)間段,但是不能針對不同訂單分配特定的服務(wù)人員
Q:為什么打開了免開發(fā)版本的自動分配按鈕,支付憑證下還是沒有出現(xiàn)服務(wù)人員的名片入口?
A:打開自動分配按鈕時(shí),還需為服務(wù)人員設(shè)置分配規(guī)則,只有設(shè)置了規(guī)則的服務(wù)人員才會被分配到指定時(shí)間段的訂單中。若未給服務(wù)人員設(shè)置分配規(guī)則,則該服務(wù)人員不會實(shí)現(xiàn)自動分配