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

基礎支付
JSAPI支付
APP支付
H5支付
Native支付
小程序支付
合單支付
付款碼支付
經營能力
微信支付分
支付即服務
行業(yè)方案
智慧商圈
微信支付分停車服務
電子發(fā)票
營銷工具
代金券
商家券
委托營銷
支付有禮
小程序發(fā)券插件
H5發(fā)券
圖片上傳(營銷專用)
現金紅包
資金應用
商家轉賬到零錢
分賬
風險合規(guī)
消費者投訴2.0
其他能力
清關報關
圖片上傳
視頻上傳
微信支付平臺證書

H5支付開發(fā)指引

1. 接口規(guī)則

為了在保證支付安全的前提下,帶給商戶簡單、一致且易用的開發(fā)體驗,我們推出了全新的微信支付APIv3接口。該版本API的具體規(guī)則請參考“APIv3接口規(guī)則
備注:當前接口用于微信國內錢包

2. 開發(fā)準備

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

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

測試步驟

1、根據自身開發(fā)語言,選擇對應的開發(fā)庫并構建項目,具體配置請參考下面鏈接的詳細說明:

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

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

    注:當前開發(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;
 
// 商戶相關配置,
$merchantId = '1000100'; // 商戶號
$merchantSerialNumber = 'XXXXXXXXXX'; // 商戶API證書序列號
$merchantPrivateKey = PemUtil::loadPrivateKey('./path/to/mch/private/key.pem'); // 商戶私鑰文件路徑
 
// 微信支付平臺配置
$wechatpayCertificate = PemUtil::loadCertificate('./path/to/wechatpay/cert.pem'); // 微信支付平臺證書文件路徑
 
// 構造一個WechatPayMiddleware
$wechatpayMiddleware = WechatPayMiddleware::builder()
    ->withMerchant($merchantId, $merchantSerialNumber, $merchantPrivateKey) // 傳入商戶相關配置
    ->withWechatPay([ $wechatpayCertificate ]) // 可傳入多個微信支付平臺證書,參數類型為array
    ->build();
 
// 將WechatPayMiddleware添加到Guzzle的HandlerStack中
$stack = GuzzleHttp\HandlerStack::create();
$stack->push($wechatpayMiddleware, 'wechatpay');
 
// 創(chuàng)建Guzzle HTTP Client時,將HandlerStack傳入,接下來,正常使用Guzzle發(fā)起API請求,WechatPayMiddleware會自動地處理簽名和驗簽
$client = new GuzzleHttp\Client(['handler' => $stack]);

/*
    Package core 微信支付api v3 go http-client 基礎庫,你可以使用它來創(chuàng)建一個client,并向微信支付發(fā)送http請求
    只需要你在初始化客戶端的時候,傳遞credential以及validator
    credential用來生成http header中的authorization信息
    validator則用來校驗回包是否被篡改
    如果http請求返回的err為nil,一般response.Body 都不為空,你可以嘗試對其進行序列化
    請注意及時關閉response.Body
    注意:使用微信支付apiv3 go庫需要引入相關的包,該示例代碼必須引入的包名有以下信息

    "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
    }
    //設置header頭中authorization信息
    opts := []option.ClientOption{
        option.WithMerchant(mchID, mchCertSerialNumber, privateKey), // 設置商戶相關配置
        option.WithWechatPay([]*x509.Certificate{wechatPayCertificate}), // 設置微信支付平臺證書,用于校驗回包信息用
    }
    return opts, nil
}

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

說明:

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

通過包管理工具引入SDK后,可根據下面每個接口的示例代碼替換相關參數后進行快速測試

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

    1.簽名生成

    2.簽名驗證

    3.敏感信息加解密

    4.merchantPrivateKey(私鑰)

    5.wechatpayCertificates(平臺證書)

    6.APIV3Key(V3 key)

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

2.2. 業(yè)務開發(fā)配置

2.2.1. 開通H5支付權限

● 前往微信支付商戶平臺—>產品中心—>H5支付—>申請開通

2.2.2.服務器配置要求

● 登錄【微信支付商戶平臺—>產品中心—>開發(fā)配置—>H5支付】,設置后一般10分鐘內生效。

注意:

  • 域名必須通過ICP備案
  • 域名填寫格式不包含http://或https://

3. 快速接入

3.1. 業(yè)務流程圖

安全標準規(guī)范流程圖

重點步驟說明:

步驟1 用戶向商戶系統(tǒng)后臺請求下單,商戶后臺必須做好安全校驗

  • 當跨域請求不是簡單請求時,瀏覽器會發(fā)起Options預檢請求,此時商戶后臺需要支持Options請求且校驗Origin頭部,如果不在允許的白名單列表內,則返回403且不返回Access-Control-Allow-* 相關頭部
  • 針對GET/POST的跨域下單請求,商戶后臺需要校驗Origin頭部是否合法且用戶Cookie是否完備(若用戶未登陸則先引導登陸商戶站點),否則返回403且不返回Access-Control-Allow-* 相關頭部

步驟2 商戶可通過H5下單API創(chuàng)建支付訂單。

步驟3 用戶通過微信外部的瀏覽器調起微信支付中間頁,進行發(fā)起支付請求。

步驟5 用戶支付成功后,商戶可接收到微信支付支付結果通知支付通知API

步驟8 商戶在沒有接收到微信支付結果通知的情況下需要主動調用查詢訂單API查詢支付結果。

注意:

  • 商戶需按照安全規(guī)范進行接入,若因未遵循規(guī)范接入而出現安全問題,財付通將根據《微信支付服務協議》條款處理
  • 以上圖示,僅為示例,只供參考。請商戶自行確認是否實現了跨越訪問白名單限制和用戶登錄態(tài)校驗。

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

本文檔展示了如何使用微信支付服務端 SDK 快速接入H5支付產品,完成與微信支付對接的部分。

注意:

  • 文檔中的代碼示例是用來闡述 API 基本使用方法,代碼中的示例參數需替換成商戶自己賬號及請求參數才能跑通。
  • 以下接入步驟僅提供參考,請商戶結合自身業(yè)務需求進行評估、修改。
3.2.1. 【服務端】H5下單

步驟說明:用戶使用微信外部的瀏覽器訪問商戶H5頁面,當用戶選擇相關商品購買時,商戶系統(tǒng)先調用該接口在微信支付服務后臺生成預支付交易單。

示例代碼

 public void CreateOrder() throws Exception{
//請求URL
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/h5");
          
// 請求body參數
String reqdata = "{"
              + "\"amount\": {"
              + "\"total\": 100,"
              + "\"currency\": \"CNY\""
              + "},"
              + "\"scene_info\": {"
              + "\"payer_client_ip\":\"14.23.150.211\","
              + "\"h5_info\": {"
              + "\"type\": \"IOS\"" + "}},"
              + "\"mchid\": \"1900006891\","
              + "\"description\": \"Image形象店-深圳騰大-QQ公仔\(zhòng)","
              + "\"notify_url\": \"https://www.weixin.qq.com/wxpay/pay.php\","
              + "\"out_trade_no\": \"1217752501201407033233388881\","
              + "\"goods_tag\": \"WXG\","
              + "\"appid\": \"wxdace645e0bc2c424\"" + "}";     
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) {
        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/pay/transactions/h5', //請求URL
    [
        // JSON請求體
        'json' => [
            "time_expire" => "2018-06-08T10:34:56+08:00",
            "amount" => [
                "total" => 100,
                "currency" => "CNY",
            ],
            "mchid" => "1900006891",
            "description" => "Image形象店-深圳騰大-QQ公仔",
            "notify_url" => "https://www.weixin.qq.com/wxpay/pay.php",
            "out_trade_no" => "1217752501201407033233368022",
            "goods_tag" => "WXG",
            "appid" => "wxdace645e0bc2c424",
            "attach" => "自定義數據說明",
            "scene_info" => [
                "store_info" => [
                    "address" => "廣東省深圳市南山區(qū)科技中一道10000號",
                    "area_code" => "440305",
                    "name" => "騰訊大廈分店",
                    "id" => "0001",
                ],
                "device_id" => "013467007045764",
                "payer_client_ip" => "14.23.150.211",
                "h5_info"=>[
                    "type"=>"IOS"
                ],
            ]
        ],
        '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) {
// 進行錯誤處理
echo $e->getMessage()."\n";
if ($e->hasResponse()) {
    echo "failed,resp code = " . $e->getResponse()->getStatusCode() . " return body = " . $e->getResponse()->getBody() . "\n";
}
return;
}

func CreateOrder() {
       // 初始化客戶端
    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
    }
    //設置請求地址
  URL := "https://api.mch.weixin.qq.com/v3/pay/transactions/h5"
  //設置請求信息,此處也可以使用結構體來進行請求
  mapInfo := map[string]interface{}{
    "mchid": "1900006XXX",
    "out_trade_no": "H51217752501201407033233368018",
    "appid": "wxdace645e0bc2cXXX",
    "description": "Image形象店-深圳騰大-QQ公仔",
    "notify_url": "https://weixin.qq.com/",
    "amount": map[string]interface{}{
      "total": 1,
      "currency": "CNY",
    },
    "scene_info": map[string]interface{}{
      "payer_client_ip": "127.0.0.1",
      "h5_info": map[string]interface{}{
        "type": "Wap",
     },
    },
  }
  // 發(fā)起請求
  response, err := client.Post(ctx, URL, mapInfo)
  if err != nil{
    log.Printf("client post err:%s",err)
    return
  }
  // 校驗回包內容是否有邏輯錯誤
  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))
}
    

重要參數說明

? out_trade_no:商戶系統(tǒng)內部訂單號,只能是數字、大小寫字母_-*且在同一個商戶號下唯一

? description:商品描述

? notify_url:支付回調通知URL,該地址必須為直接可訪問的URL,不允許攜帶查詢串

? total:訂單總金額,單位為分

? scene_info:支付場景描述

更多參數、響應詳情及錯誤碼請參見H5下單API接口文檔

3.2.2.【客戶端】微信外部的瀏覽器拉起微信支付中間頁

步驟說明:通過H5下單API成功獲取H5下單返回的支付中間頁(h5_url)后,用戶需要通過微信外部的瀏覽器調起微信支付收銀臺

注意:

  • h5_url為拉起微信支付收銀臺的中間頁面,可通過訪問該url來拉起微信客戶端,完成支付,h5_url的有效期為5分鐘
  • 微信支付收銀臺中間頁會進行H5權限的校驗,安全性檢查
  • 正常流程用戶支付完成后會返回至發(fā)起支付的頁面,如需返回至指定頁面,則可以在h5_url后拼接上redirect_url參數,來指定回調頁面。您希望用戶支付完成后跳轉至https://www.wechatpay.com.cn,則拼接后的地址為h5_url= https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx20161110163838f231619da20804912345&package=1037687096&redirect_url=https%3A%2F%2Fwww.wechatpay.com.cn
  • 需對redirect_url進行urlencode處理
  • 由于設置redirect_url后,回跳指定頁面的操作可能發(fā)生在:

    1、微信支付中間頁調起微信收銀臺后超過5秒

    2、用戶點擊“取消支付”或支付完成后點擊“完成”按鈕。因此無法保證頁面回跳時,支付流程已結束,所以商戶設置的redirect_url地址不能自動執(zhí)行查單操作,應讓用戶去點擊按鈕觸發(fā)查單操作,回跳頁面展示效果可參考下圖

3.2.3.【服務端】接收支付結果通知

步驟說明:當用戶完成支付,微信會把相關支付結果將通過異步回調的方式通知商戶,商戶需要接收處理,并按文檔規(guī)范返回應答

注意

  • 支付結果通知是以POST 方法訪問商戶設置的通知url,通知的數據以JSON 格式通過請求主體(BODY)傳輸。通知的數據包括了加密的支付結果詳情
  • 加密不能保證通知請求來自微信。微信會對發(fā)送給商戶的通知進行簽名,并將簽名值放在通知的HTTP頭Wechatpay-Signature。商戶應當驗證簽名,以確認請求來自微信,而不是其他的第三方。簽名驗證的算法請參考 《微信支付API v3簽名驗證》
  • 支付通知http應答碼為200或204才會當作正常接收,當回調處理異常時,應答的HTTP狀態(tài)碼應為500,或者4xx
  • 商戶成功接收到回調通知后應返回成功的http應答碼為200或204
  • 同樣的通知可能會多次發(fā)送給商戶系統(tǒng)。商戶系統(tǒng)必須能夠正確處理重復的通知。 推薦的做法是,當商戶系統(tǒng)收到通知進行處理時,先檢查對應業(yè)務數據的狀態(tài),并判斷該通知是否已經處理。如果未處理,則再進行處理;如果已處理,則直接返回結果成功。在對業(yè)務數據進行狀態(tài)檢查和處理之前,要采用數據鎖進行并發(fā)控制,以避免函數重入造成的數據混亂
  • 對后臺通知交互時,如果微信收到商戶的應答不符合規(guī)范或超時,微信認為通知失敗,微信會通過一定的策略定期重新發(fā)起通知,盡可能提高通知的成功率,但微信不保證通知最終能成功。(通知頻率為15s/15s/30s/3m/10m/20m/30m/30m/30m/60m/3h/3h/3h/6h/6h - 總計 24h4m)

更多參數、響應詳情及錯誤碼請參見 JSAPI / APP / H5 / Native / 小程序支付通知API接口文檔

3.2.4. 【服務端】查詢訂單

步驟說明:當商戶后臺、網絡、服務器等出現異常,商戶系統(tǒng)最終未接收到支付通知時,商戶可通過查詢訂單接口核實訂單支付狀態(tài)

示例代碼(通過微信訂單號查詢):


public void QueryOrder() throws Exception {
   
  //請求URL
  URIBuilder uriBuilder = new URIBuilder("https://api.mch.weixin.qq.com/v3/pay/transactions/id/4200000745202011093730578574");
  uriBuilder.setParameter("mchid", mchId);
 
  //完成簽名并執(zhí)行請求
  HttpGet httpGet = new HttpGet(uriBuilder.build());
  httpGet.addHeader("Accept", "application/json");
  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) {
          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/pay/transactions/id/1217752501201407033233368018?mchid=1230000109', //請求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) {
    // 進行錯誤處理
    echo $e->getMessage()."\n";
    if ($e->hasResponse()) {
        echo "failed,resp code = " . $e->getResponse()->getStatusCode() . " return body = " . $e->getResponse()->getBody() . "\n";
    }
    return;
}

func QueryOrder() {
       // 初始化客戶端
    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
    }
    //設置請求地址
    URL := "https://api.mch.weixin.qq.com/v3/pay/transactions/id/1217752501201407033233368018?mchid=1900000000"
    // 發(fā)起請求
    response, err := client.Get(ctx, URL)
    if err != nil{
        log.Printf("client get err:%s",err)
        return
    }
    // 校驗回包內容是否有邏輯錯誤
    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))
}
    

注意:

  • 查詢訂單可通過微信支付訂單號商戶訂單號兩種方式查詢,兩種查詢方式返回結果相同

更多參數、響應詳情及錯誤碼請參見 JSAPI / APP / H5 / Native / 小程序查詢訂單API接口文檔

3.2.5. 【服務端】關閉訂單

步驟說明:當商戶訂單支付失敗需要生成新單號重新發(fā)起支付,要對原訂單號調用關單,避免重復支付;系統(tǒng)下單后,用戶支付超時,系統(tǒng)退出不再受理,避免用戶繼續(xù),請調用關單接口

示例代碼


  public void CloseOrder() throws Exception {
     
    //請求URL
    HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/sdkphp12345678920201028112429/close");
    //請求body參數
    String reqdata ="{\"mchid\": \""+mchId+"\"}";
     
    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) {
            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/pay/transactions/out-trade-no/{out_trade_no}/close', //請求URL
        [
            // JSON請求體
            'json' => [
                "mchid " => "1230000109",
            ],
            '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) {
    // 進行錯誤處理
    echo $e->getMessage()."\n";
    if ($e->hasResponse()) {
        echo "failed,resp code = " . $e->getResponse()->getStatusCode() . " return body = " . $e->getResponse()->getBody() . "\n";
    }
    return;
  }
  

func CloseOrder() {
       // 初始化客戶端
    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
    }
    //設置請求地址
    URL := "https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/1217752501201407033233368018/close"
    //設置請求信息,此處也可以使用結構體來進行請求
    mapInfo := map[string]interface{}{
      "mchid": "1900006891",
    }
  
    // 發(fā)起請求
    response, err := client.Post(ctx, URL, mapInfo)
    if err != nil{
      log.Printf("client post err:%s",err)
      return
    }
    // 校驗回包內容是否有邏輯錯誤
    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))
}
    

注意

  • 訂單生成后不能馬上調用關單接口,最短調用時間間隔為5分鐘
  • 已支付成功的訂單不能關閉

更多參數、響應詳情及錯誤碼請參見 JSAPI / APP / H5 / Native / 小程序接口文檔

3.2.6. 【服務端】申請交易賬單

步驟說明:微信支付按天提供交易賬單文件,商戶可以通過該接口獲取賬單文件的下載地址

示例代碼


public void TradeBill() throws Exception {
   
  //請求URL
  URIBuilder uriBuilder = new URIBuilder("https://api.mch.weixin.qq.com/v3/bill/tradebill");
  uriBuilder.setParameter("bill_date", "2020-11-09");
  uriBuilder.setParameter("bill_type", "ALL");
 
  //完成簽名并執(zhí)行請求
  HttpGet httpGet = new HttpGet(uriBuilder.build());
  httpGet.addHeader("Accept", "application/json");
  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) {
          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/bill/tradebill?bill_date=2019-06-11&bill_type=ALL', //請求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) {
    // 進行錯誤處理
    echo $e->getMessage()."\n";
    if ($e->hasResponse()) {
        echo "failed,resp code = " . $e->getResponse()->getStatusCode() . " return body = " . $e->getResponse()->getBody() . "\n";
    }
    return;
}
      

func TradeBill() {
       // 初始化客戶端
    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
    }
   //設置請求地址
    URL := "https://api.mch.weixin.qq.com/v3/bill/tradebill?bill_date=2019-06-11&bill_type=ALL"
  // 發(fā)起請求
  response, err := client.Get(ctx, URL)
  if err != nil{
    log.Printf("client get err:%s",err)
    return
  }
  // 校驗回包內容是否有邏輯錯誤
  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))
}
    

注意

更多參數、響應詳情及錯誤碼請參見 JSAPI / APP / H5 / Native / 小程序接口文檔

3.2.7. 【服務端】下載賬單

步驟說明:通過申請交易賬單接口獲取到賬單下載地址(download_url)后,再通過該接口獲取到對應的賬單文件,文件內包含交易相關的金額、時間、營銷等信息,供商戶核對訂單、退款、銀行到賬等情況

示例代碼


public void DownloadUrl(String download_url) throws Exception{
  PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes("utf-8")));
   
  //初始化httpClient
  //該接口無需進行簽名驗證、通過withValidator((response) -> true)實現
  httpClient =  WechatPayHttpClientBuilder.create().withMerchant(mchId, mchSerialNo, merchantPrivateKey).withValidator((response) -> true).build();
   
  //請求URL
  //賬單文件的下載地址的有效時間為30s
  URIBuilder uriBuilder = new URIBuilder(download_url);
  HttpGet httpGet = new HttpGet(uriBuilder.build());
  httpGet.addHeader("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) {
          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/billdownload/file?token=xx', //請求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) {
    // 進行錯誤處理
    echo $e->getMessage()."\n";
    if ($e->hasResponse()) {
        echo "failed,resp code = " . $e->getResponse()->getStatusCode() . " return body = " . $e->getResponse()->getBody() . "\n";
    }
    return;
}

func DownloadUrl() {
       // 初始化客戶端
    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
    }
    //設置請求地址
    URL := "https://api.mch.weixin.qq.com/v3/billdownload/file?token=xxx"  //申請賬單接口獲取到的download_url
  // 發(fā)起請求
  response, err := client.Get(ctx, URL)
  if err != nil{
    log.Printf("client get err:%s",err)
    return
  }
  // 校驗回包內容是否有邏輯錯誤
  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))
}
    

注意

? 賬單文件的下載地址的有效時間為30s

? 強烈建議商戶將實際賬單文件的哈希值和之前從接口獲取到的哈希值進行比對,以確認數據的完整性

更多參數、響應詳情及錯誤碼請參見 JSAPI / APP / H5 / Native / 小程序下載賬單API接口文檔

4. 常見問題

Q:調起H5支付報"商家參數格式有誤,請聯系商家解決"

A:請按以下幾點進行排查:

  • 1. 當前調起H5支付的referer為空導致,一般是因為直接訪問頁面調起H5支付,請按正常流程進行頁面跳轉后發(fā)起支付,或自行抓包確認referer值是否為空
  • 2. 如果是APP里調起H5支付,需要在webview中手動設置referer,如(Map extraHeaders = new HashMap();extraHeaders.put("Referer", "商戶申請H5時提交的授權域名");//例如 http://www.tg885.com )
Q:調起H5支付報"商家存在未配置的參數,請聯系商家解決"

A:請按以下幾點進行排查:

  • 1,當前調起H5支付的域名(微信側從referer中獲取)與申請H5支付時提交的授權域名不一致,如需添加或修改授權域名,請登錄商戶號對應的【商戶平臺 -> 產品中心 -> 開發(fā)配置】自行配置
  • 2,如果設置了回跳地址redirect_url,請確認設置的回跳地址的域名與申請H5支付時提交的授權域名是否一致
Q:調起H5支付報"支付請求已失效,請重新發(fā)起支付"

A:H5下單返回的H5_URL生成后,有效期為5分鐘,如超時請重新生成H5_URL后再發(fā)起支付

Q:調起H5支付報" 請在微信外打開訂單,進行支付"

A:H5支付不能直接在微信客戶端內調起,請在外部瀏覽器調起

Q:調起H5支付報" 簽名驗證失敗"或“系統(tǒng)繁忙,請稍后再試”

A:請按以下幾點進行排查:

  • 1,請確認同一個H5_URL只被一個微信號調起,如果不同微信號調起請重新下單生成新的H5_URL
  • 2,如H5_URL有添加redirect_url,請確認參數拼接格式是否有誤,是否有對redirect_url的值做urlencode,可參考以下例子格式:

    https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx20161110163838f231619da20804912345&package=1037687096&redirect_url=https%3A%2F%2Fwww.wechatpay.com.cn

Q:IOS在使用某些瀏覽器完成H5支付后會回到safari瀏覽器

A:完成H5支付后需通過schame信息返回調起支付的瀏覽器,但由于部分瀏覽器隱藏了這個信息,在無法拿到schame信息的情況下,就會默認回到safari瀏覽器



技術咨詢

文檔反饋