视频一区二区三区自拍_千金肉奴隷1985未删减版在线观看_国产成人黄色视频在线播放_少女免费播放片高清在线观看_国产精品v欧美精品v

商戶(hù)進(jìn)件
特約商戶(hù)進(jìn)件
基礎(chǔ)支付
JSAPI支付
APP支付
H5支付
Native支付
小程序支付
合單支付
付款碼支付
經(jīng)營(yíng)能力
支付即服務(wù)
點(diǎn)金計(jì)劃
行業(yè)方案
平臺(tái)收付通
智慧商圈
微信支付分停車(chē)服務(wù)
電子發(fā)票
營(yíng)銷(xiāo)工具
代金券
商家券
委托營(yíng)銷(xiāo)
支付有禮
小程序發(fā)券插件
H5發(fā)券
圖片上傳(營(yíng)銷(xiāo)專(zhuān)用)
現(xiàn)金紅包
資金應(yīng)用
分賬
連鎖品牌分賬
風(fēng)險(xiǎn)合規(guī)
商戶(hù)開(kāi)戶(hù)意愿確認(rèn)
消費(fèi)者投訴2.0
商戶(hù)平臺(tái)處置通知
其他能力
圖片上傳
視頻上傳
微信支付平臺(tái)證書(shū)

委托營(yíng)銷(xiāo)開(kāi)發(fā)指引

1. 接口規(guī)則

為了在保證支付安全的前提下,帶給商戶(hù)簡(jiǎn)單、一致且易用的開(kāi)發(fā)體驗(yàn),我們推出了全新的微信支付APIv3接口。該版本API的具體規(guī)則請(qǐng)參考“APIv3接口規(guī)則

2. 開(kāi)發(fā)準(zhǔn)備

2.1. 搭建和配置開(kāi)發(fā)環(huán)境

為了幫助開(kāi)發(fā)者調(diào)用開(kāi)放接口,我們提供了JAVA、PHP、GO三種語(yǔ)言版本的開(kāi)發(fā)庫(kù),封裝了簽名生成、簽名驗(yàn)證、敏感信息加/解密、媒體文件上傳等基礎(chǔ)功能(更多語(yǔ)言版本的開(kāi)發(fā)庫(kù)將在近期陸續(xù)提供

測(cè)試步驟

1、根據(jù)自身開(kāi)發(fā)語(yǔ)言,選擇對(duì)應(yīng)的開(kāi)發(fā)庫(kù)并構(gòu)建項(xiàng)目,具體配置請(qǐng)參考下面鏈接的詳細(xì)說(shuō)明:

    ? wechatpay-java(推薦)wechatpay-apache-httpclient,適用于Java開(kāi)發(fā)者。

    ? wechatpay-php(推薦)、wechatpay-guzzle-middleware,適用于PHP開(kāi)發(fā)者

    注:當(dāng)前開(kāi)發(fā)指引接口PHP示例代碼采用wechatpay-guzzle-middleware版本

    ? wechatpay-go,適用于Go開(kāi)發(fā)者

更多資源可前往微信支付開(kāi)發(fā)者社區(qū)搜索查看

2、創(chuàng)建加載商戶(hù)私鑰、加載平臺(tái)證書(shū)、初始化httpClient的通用方法


@Before
public void setup() throws IOException {
    // 加載商戶(hù)私鑰(privateKey:私鑰字符串)
    PrivateKey merchantPrivateKey = PemUtil
            .loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes("utf-8")));
 
    // 加載平臺(tái)證書(shū)(mchId:商戶(hù)號(hào),mchSerialNo:商戶(hù)證書(shū)序列號(hào),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;
 
// 商戶(hù)相關(guān)配置,
$merchantId = '1000100'; // 商戶(hù)號(hào)
$merchantSerialNumber = 'XXXXXXXXXX'; // 商戶(hù)API證書(shū)序列號(hào)
$merchantPrivateKey = PemUtil::loadPrivateKey('./path/to/mch/private/key.pem'); // 商戶(hù)私鑰文件路徑
 
// 微信支付平臺(tái)配置
$wechatpayCertificate = PemUtil::loadCertificate('./path/to/wechatpay/cert.pem'); // 微信支付平臺(tái)證書(shū)文件路徑
 
// 構(gòu)造一個(gè)WechatPayMiddleware
$wechatpayMiddleware = WechatPayMiddleware::builder()
    ->withMerchant($merchantId, $merchantSerialNumber, $merchantPrivateKey) // 傳入商戶(hù)相關(guān)配置
    ->withWechatPay([ $wechatpayCertificate ]) // 可傳入多個(gè)微信支付平臺(tái)證書(shū),參數(shù)類(lèi)型為array
    ->build();
 
// 將WechatPayMiddleware添加到Guzzle的HandlerStack中
$stack = GuzzleHttp\HandlerStack::create();
$stack->push($wechatpayMiddleware, 'wechatpay');
 
// 創(chuàng)建Guzzle HTTP Client時(shí),將HandlerStack傳入,接下來(lái),正常使用Guzzle發(fā)起API請(qǐng)求,WechatPayMiddleware會(huì)自動(dòng)地處理簽名和驗(yàn)簽
$client = new GuzzleHttp\Client(['handler' => $stack]);

/*
    Package core 微信支付api v3 go http-client 基礎(chǔ)庫(kù),你可以使用它來(lái)創(chuàng)建一個(gè)client,并向微信支付發(fā)送http請(qǐng)求
    只需要你在初始化客戶(hù)端的時(shí)候,傳遞credential以及validator
    credential用來(lái)生成http header中的authorization信息
    validator則用來(lái)校驗(yàn)回包是否被篡改
    如果http請(qǐng)求返回的err為nil,一般response.Body 都不為空,你可以嘗試對(duì)其進(jìn)行序列化
    請(qǐng)注意及時(shí)關(guān)閉response.Body
    注意:使用微信支付apiv3 go庫(kù)需要引入相關(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) {
    //商戶(hù)號(hào)
    mchID := ""
    //商戶(hù)證書(shū)序列號(hào)
    mchCertSerialNumber := ""
    //商戶(hù)私鑰文件路徑
    privateKeyPath := ""
    //平臺(tái)證書(shū)文件路徑
    wechatCertificatePath := ""

    // 加載商戶(hù)私鑰
    privateKey, err := utils.LoadPrivateKeyWithPath(privateKeyPath)
    if err != nil {
        log.Printf("load private err:%s", err.Error())
        return nil, err
    }
    // 加載微信支付平臺(tái)證書(shū)
    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è)置商戶(hù)相關(guān)配置
        option.WithWechatPay([]*x509.Certificate{wechatPayCertificate}), // 設(shè)置微信支付平臺(tái)證書(shū),用于校驗(yàn)回包信息用
    }
    return opts, nil
}

3、基于接口的示例代碼,替換請(qǐng)求參數(shù)后可發(fā)起測(cè)試

說(shuō)明:

? 上面的開(kāi)發(fā)庫(kù)為微信支付官方開(kāi)發(fā)庫(kù),其它沒(méi)有審核或者控制下的第三方工具和庫(kù),微信支付不保證它們的安全性和可靠性

通過(guò)包管理工具引入SDK后,可根據(jù)下面每個(gè)接口的示例代碼替換相關(guān)參數(shù)后進(jìn)行快速測(cè)試

? 開(kāi)發(fā)者如果想詳細(xì)了解簽名生成、簽名驗(yàn)證、敏感信息加/解密、媒體文件上傳等常用方法的具體代碼實(shí)現(xiàn),可閱讀下面的詳細(xì)說(shuō)明:

    1.簽名生成

    2.簽名驗(yàn)證

    3.敏感信息加解密

    4.merchantPrivateKey(私鑰)

    5.wechatpayCertificates(平臺(tái)證書(shū))

    6.APIV3Key(V3 key)

? 如想更詳細(xì)的了解我們的接口規(guī)則,可查看我們的接口規(guī)則指引文檔

3. 快速接入

3.1. 業(yè)務(wù)流程圖

業(yè)務(wù)流程時(shí)序圖:

步驟4 商戶(hù)調(diào)用《建立合作關(guān)系》接口,將指定優(yōu)惠券批次(支付券或商家券)授權(quán)給指定APPID

步驟7 用戶(hù)在商家小程序直播間,可領(lǐng)取對(duì)應(yīng)優(yōu)惠券;(優(yōu)惠券領(lǐng)取后,自動(dòng)插入用戶(hù)微信卡包)

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

文檔展示了如何使用微信支付服務(wù)端 SDK 快速接入委托營(yíng)銷(xiāo)產(chǎn)品,完成與微信支付對(duì)接的部分。

注意

  • 文檔中的代碼示例是用來(lái)闡述 API 基本使用方法,代碼中的示例參數(shù)需替換成商戶(hù)自己賬號(hào)及請(qǐng)求參數(shù)才能跑通
  • 以下接入步驟僅提供參考,請(qǐng)商戶(hù)結(jié)合自身業(yè)務(wù)需求進(jìn)行評(píng)估、修改。
3.2.1. 【服務(wù)端】建立合作關(guān)系

步驟說(shuō)明:該接口主要為商戶(hù)提供營(yíng)銷(xiāo)資源的授權(quán)能力,可授權(quán)給其他商戶(hù)或小程序,方便商戶(hù)間的互利合作。

示例代碼:


public void BuildRelations() throws Exception{
    //請(qǐng)求URL
    HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/marketing/partnerships/build");
    // 請(qǐng)求body參數(shù)
    String reqdata = "{"
            + "\"authorized_data\": {"
            + "\"business_type\":\"FAVOR_STOCK\","
            + "\"stock_id\":\"2433405\""
            + "},"
            + "\"partner\": {"
            + "\"appid\":\"wx4e1916a585d1f4e9\","
            + "\"type\":\"APPID\""
            + "}"
            + "}";
    StringEntity entity = new StringEntity(reqdata,"utf-8");
    entity.setContentType("application/json");
    httpPost.setEntity(entity);
    httpPost.setHeader("Accept", "application/json");
    httpPost.setHeader("Idempotency-Key","12345");
    //完成簽名并執(zhí)行請(qǐng)求
    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) { //處理成功,無(wú)返回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/marketing/partnerships/build', //請(qǐng)求URL
        [
            // JSON請(qǐng)求體
            'json' => [
                "authorized_data" => [
                    "business_type" => "FAVOR_STOCK", 
                    "stock_id" => "2433405", 
                ],
                "partner" => [
                    "appid" => "wx4e1916a585d1f4e9", 
                    "type" => "APPID", 
                ]
            ],
            'headers' => [ 
                'Accept' => 'application/json',
                'Idempotency-Key' => '12345'
            ]
        ]
    );
    $statusCode = $resp->getStatusCode();
    if ($statusCode == 200) { //處理成功
        echo "success,return body = " . $resp->getBody()->getContents()."\n";
    } else if ($statusCode == 204) { //處理成功,無(wú)返回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 BuildRelations() {
       // 初始化客戶(hù)端
    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è)置請(qǐng)求地址
  URL := "https://api.mch.weixin.qq.com/v3/marketing/partnerships/build"
  //設(shè)置請(qǐng)求信息,此處也可以使用結(jié)構(gòu)體來(lái)進(jìn)行請(qǐng)求
  mapInfo := map[string]interface{}{
    "authorized_data": map[string]interface{}{
      "business_type": "FAVOR_STOCK",
      "stock_id": "2433405",
    },
    "partner": map[string]interface{}{
      "appid": "wx4e1916a585d1f4e9",
      "type": "APPID",
    },
  }

  // 發(fā)起請(qǐng)求
  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(shuō)明

? type:合作方類(lèi)別,枚舉值:

APPID:合作方為APPID

MERCHANT:合作方為商戶(hù)

? business_type:授權(quán)業(yè)務(wù)類(lèi)別,枚舉值:

FAVOR_STOCK:代金券批次

BUSIFAVOR_STOCK:商家券批次

更多參數(shù)、響應(yīng)詳情及錯(cuò)誤碼請(qǐng)參見(jiàn)建立合作關(guān)系接口文檔

3.2.2. 【服務(wù)端】查詢(xún)合作關(guān)系列表

步驟說(shuō)明:該接口主要為商戶(hù)提供合作關(guān)系列表的查詢(xún)能力。

示例代碼:


public void QueryRelations() throws Exception{
    //請(qǐng)求URL
    HttpGet httpGet = new HttpGet("https://api.mch.weixin.qq.com/v3/marketing/partnerships?authorized_data=%7b%22business_type%22%3a%22BUSIFAVOR_STOCK%22%7d&partner=%7b%22type%22%3a%22APPID%22%7d&offset=0&limit=5");
    httpGet.setHeader("Accept", "application/json");

    //完成簽名并執(zhí)行請(qǐng)求
    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) { //處理成功,無(wú)返回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/marketing/partnerships?authorized_data=%7b%22business_type%22%3a%22BUSIFAVOR_STOCK%22%7d&partner=%7b%22type%22%3a%22APPID%22%7d&offset=0&limit=5', //請(qǐng)求URL
        [
            'headers' => [ 'Accept' => 'application/json']
        ]
    );
    $statusCode = $resp->getStatusCode();
    if ($statusCode == 200) { //處理成功
        echo "success,return body = " . $resp->getBody()->getContents()."\n";
    } else if ($statusCode == 204) { //處理成功,無(wú)返回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 QueryRelations() {
       // 初始化客戶(hù)端
    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è)置請(qǐng)求地址
    URL := "https://api.mch.weixin.qq.com/v3/marketing/partnerships?authorized_data=%7b%22business_type%22%3a%22BUSIFAVOR_STOCK%22%7d&partner=%7b%22type%22%3a%22APPID%22%7d&offset=0&limit=5"
  // 發(fā)起請(qǐng)求
  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(shuō)明

? business_type:授權(quán)業(yè)務(wù)類(lèi)別,枚舉值:

FAVOR_STOCK:代金券批次

BUSIFAVOR_STOCK:商家券批次

更多參數(shù)、響應(yīng)詳情及錯(cuò)誤碼請(qǐng)參見(jiàn)查詢(xún)合作關(guān)系列表接口文檔

4. 常見(jiàn)問(wèn)題

Q:調(diào)用建立合作關(guān)系接口返回“appid與mchid不匹配”

A:請(qǐng)按照以下幾點(diǎn)檢查:

1. appid或mch_id填寫(xiě)錯(cuò)誤,請(qǐng)確認(rèn)appid和mch_id是否正確

2. appid與mch_id未綁定,請(qǐng)綁定后再調(diào)用接口,綁定步驟請(qǐng)參考《綁定指引》文檔

Q:調(diào)用建立合作關(guān)系接口返回“商戶(hù)號(hào)不存在”

A商戶(hù)號(hào)不存在,請(qǐng)確認(rèn)請(qǐng)求頭中的商戶(hù)號(hào)是否正確或者是否有空格

Q:查詢(xún)合作關(guān)系列表API返回“簽名錯(cuò)誤或簽名信息不完整”

A:請(qǐng)按照以下幾點(diǎn)檢查:

1. 簽名與生成Authorization用的同一個(gè)時(shí)間戳跟隨機(jī)串

2. 構(gòu)造簽名串時(shí),里面的url不需要ToLowCase(),不用UrlEncode(),商戶(hù)請(qǐng)求的url后綴是什么,簽名用的url后綴就是什么

3. 查詢(xún)訂單使用的是GET,構(gòu)建簽名串時(shí),里面的請(qǐng)求報(bào)文為空且需要換行符

4. 檢查證書(shū)和商戶(hù)號(hào)是否正確,如為服務(wù)商模式,則需使用服務(wù)商的相關(guān)證書(shū)。簽名相關(guān)問(wèn)題請(qǐng)參考《接口規(guī)則》文檔

Q:調(diào)用建立合作關(guān)系接口返回“商戶(hù)證書(shū)序列號(hào)有誤。請(qǐng)使用簽名私鑰匹配的證書(shū)序列號(hào)”

A:請(qǐng)求頭中的API證書(shū)序列號(hào)錯(cuò)誤,請(qǐng)排查確認(rèn)。證書(shū)序列號(hào)查看路徑:【商戶(hù)平臺(tái)->API安全->API證書(shū)->查看證書(shū)】

Q:調(diào)用建立合作關(guān)系接口返回“Http頭缺少Accept或User-Agent”

A:Http頭缺少Accept或User-Agent,請(qǐng)根據(jù)V3接口規(guī)則內(nèi)容進(jìn)行排查



技術(shù)咨詢(xún)

文檔反饋