Php 對接微信V3業(yè)務(wù)"商家轉(zhuǎn)賬到零錢"功能

首先吐槽一下

微信真的是越搞越垃圾,文檔和shit一樣,直接看不懂,微信的包也是,稍微一點(diǎn)沒注意,就直接蹦,一點(diǎn)面子都不給,哈哈哈哈。。。
因?yàn)槟壳绊?xiàng)目涉及到一個(gè)分銷的功能,首先就想到了微信的"企業(yè)付款到零錢功能",然后去申請,商戶后臺看到的只有"商家付款到零錢",心里想著也是一樣的,反正都是打款,應(yīng)該和以前大差不差的,結(jié)果,"商家付款到零錢"這個(gè)功能前前后后提交申請10多次,一直沒過,人工隨時(shí)排隊(duì),又解決不了問題,每次說反饋上去,然后3天后,發(fā)條短信給你,讓你"以實(shí)際審核為準(zhǔn)",麻辣隔壁,服了,好消息是:經(jīng)過長達(dá)半年的抗戰(zhàn)(2022-11 ~ 2023-05) 月,我的功能終于下來。

步入正題

首先我選擇的composer包是yansongda/pay ~3.2.0 (本來想沿用easywechant,奈何V3版本的功能需要php8.0以上,所以放棄了)

composer require yansongda/pay:~3.2.0 -vvv

創(chuàng)建一個(gè)config配置文件(生成的文件 pay.php,位于:項(xiàng)目根目錄/config/pay.php)

php artisan vendor:publish --provider="Yansongda\LaravelPay\PayServiceProvider" --tag=laravel-pay

文件大致內(nèi)容


declare(strict_types=1);

use Yansongda\Pay\Pay;

return [
    // 支付寶支付相關(guān)配置
    'alipay' => [
        'default' => [
            // 必填-支付寶分配的 app_id
            'app_id' => '',
            // 必填-應(yīng)用私鑰 字符串或路徑
            'app_secret_cert' => '',
            // 必填-應(yīng)用公鑰證書 路徑
            'app_public_cert_path' => '',
            // 必填-支付寶公鑰證書 路徑
            'alipay_public_cert_path' => '',
            // 必填-支付寶根證書 路徑
            'alipay_root_cert_path' => '',
            'return_url' => '',
            'notify_url' => '',
            // 選填-服務(wù)商模式下的服務(wù)商 id,當(dāng) mode 為 Pay::MODE_SERVICE 時(shí)使用該參數(shù)
            'service_provider_id' => '',
            // 選填-默認(rèn)為正常模式。可選為: MODE_NORMAL, MODE_SANDBOX, MODE_SERVICE
            'mode' => Pay::MODE_NORMAL,
        ],
    ],
    //   微信支付相關(guān)配置
    'wechat' => [
        'default' => [
            // 必填-商戶號,服務(wù)商模式下為服務(wù)商商戶號
            'mch_id' => '',
            // 必填-商戶秘鑰
            'mch_secret_key' => '',
            // 必填-商戶私鑰 字符串或路徑
            'mch_secret_cert' => '',
            // 必填-商戶公鑰證書路徑
            'mch_public_cert_path' => '',
            // 必填
            'notify_url' => '',
            // 選填-公眾號 的 app_id
            'mp_app_id' => '',
            // 選填-小程序 的 app_id
            'mini_app_id' => '',
            // 選填-app 的 app_id
            'app_id' => '',
            // 選填-合單 app_id
            'combine_app_id' => '',
            // 選填-合單商戶號
            'combine_mch_id' => '',
            // 選填-服務(wù)商模式下,子公眾號 的 app_id
            'sub_mp_app_id' => '',
            // 選填-服務(wù)商模式下,子 app 的 app_id
            'sub_app_id' => '',
            // 選填-服務(wù)商模式下,子小程序 的 app_id
            'sub_mini_app_id' => '',
            // 選填-服務(wù)商模式下,子商戶id
            'sub_mch_id' => '',
            // 選填-微信公鑰證書路徑, optional,強(qiáng)烈建議 php-fpm 模式下配置此參數(shù)
            'wechat_public_cert_path' => [
                '45F59D4DABF31918AFCEC556D5D2C6E376675D57' => __DIR__.'/Cert/wechatPublicKey.crt',
            ],
            // 選填-默認(rèn)為正常模式??蛇x為: MODE_NORMAL, MODE_SERVICE
            'mode' => Pay::MODE_NORMAL,
        ],
    ],
    // 銀聯(lián)支付相關(guān)配置
    'unipay' => [
        'default' => [
            // 必填-商戶號
            'mch_id' => '',
            // 必填-商戶公私鑰
            'mch_cert_path' => '',
            // 必填-商戶公私鑰密碼
            'mch_cert_password' => '000000',
            // 必填-銀聯(lián)公鑰證書路徑
            'unipay_public_cert_path' => '',
            // 必填
            'return_url' => '',
            // 必填
            'notify_url' => '',
        ],
    ],
    // GuzzleHttp相關(guān)配置
    'http' => [ // optional
        'timeout' => 5.0, // 請求超時(shí)時(shí)間
        'connect_timeout' => 5.0,  // 連接超時(shí)時(shí)間
        // 更多配置項(xiàng)請參考 [Guzzle](https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html)
    ],
    // optional,默認(rèn) warning;日志路徑為:sys_get_temp_dir().'/logs/yansongda.pay.log'
    'logger' => [
        'enable' => false,  // 開啟日志或者關(guān)閉  true or false
        'file' => null,   // 日志保存路徑 默認(rèn)路徑:sys_get_temp_dir().'/logs/yansongda.pay.log'
        'level' => 'debug', // 日志級別 Debug、Info、Notice、Warning、Error、Critical、Alert、Emergency
        'type' => 'single', // optional, 可選 daily.
        'max_file' => 30, // 留存多少天內(nèi)的日志,默認(rèn)30天,根據(jù)實(shí)際需要可以更改
    ],
];

具體內(nèi)容可以看官方文檔
傳送門

轉(zhuǎn)賬到零錢的一些配置和代碼

由于我只需要微信的功能,所以我精簡了一下
<?php

declare(strict_types=1);

use Yansongda\Pay\Pay;

return [
    'wechat' => [
        'default' => [
            // 必填-商戶號,服務(wù)商模式下為服務(wù)商商戶號
            'mch_id' => '',
            // 必填-商戶秘鑰
            'mch_secret_key' => '',
            // 必填-商戶私鑰 字符串或路徑,文件名:apiclient_key.pem 的文件
            'mch_secret_cert' => '',
            // 必填-商戶公鑰證書路徑,文件名:apiclient_cert.pem的文件
            'mch_public_cert_path' => '',
            // 必填
            'notify_url' => '', // 回調(diào)地址
            // 選填-小程序 的 app_id
            'mini_app_id' => '',
            // 選填-微信公鑰證書路徑, optional,強(qiáng)烈建議 php-fpm 模式下配置此參數(shù)
            // 這個(gè)參數(shù)需要去下載證書,具體下載方法在下面貼出來
            'wechat_public_cert_path' => [],
            // 選填-默認(rèn)為正常模式??蛇x為: MODE_NORMAL, MODE_SERVICE
            'mode' => Pay::MODE_NORMAL,
        ],
    ],
    'http' => [ // optional
        'timeout' => 5.0,
        'connect_timeout' => 5.0,
        // 更多配置項(xiàng)請參考 [Guzzle](https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html)
    ],
    // optional,默認(rèn) warning;
    'logger' => [
        'enable' => true,
        'file' => str_replace('\\', '/', storage_path()).'/logs/transfer/transferLog.log', // 日志我是放在laravel默認(rèn)的日志目錄下
        'level' => 'warning',
        'type' => 'daily', // daily 按天生成日志,生成日志格式 transferLog-2023-05-15.log
        'max_file' => 180,
    ],
];
具體下載微信公鑰證書的方法

建議還是下載弄一下,不然每次請求都會多一次請求,默認(rèn)會去微信那邊動態(tài)獲取這個(gè)證書
傳送門

image.png

具體轉(zhuǎn)賬代碼

use Yansongda\Pay\Pay;

class TestController {

  public function transfer() {
          $result = Pay::wechat(config('pay'))->transfer([
              'appid' => wxxxxxxx, // 微信小程序的app_id
              'out_batch_no' => (string)time(), // 商家批次單號
              'batch_name' => '提現(xiàn)',    // 該筆批量轉(zhuǎn)賬的名稱
              'batch_remark' => '商家付款到零錢',  // 轉(zhuǎn)賬說明
              'total_amount' => 0.1 * 100,  // 轉(zhuǎn)賬金額,單位:分 
              'total_num' => 1,   // 轉(zhuǎn)賬總筆數(shù)
              'transfer_detail_list' => [   
                [
                    'out_detail_no' => (string)(time() + 5),  // 商家明細(xì)單號
                    'transfer_amount' => 0.1 * 100,  // 轉(zhuǎn)賬金額
                    'transfer_remark' => '商家付款到零錢',  // 單條轉(zhuǎn)賬備注(微信用戶會收到該備注)
                    'openid' => 'ozxxxxxxxxxx', //  轉(zhuǎn)賬用戶的 openid
                ],
            ],
        ]);
        // 返回結(jié)果
        return response()->json($result);
   }
}

返回參數(shù):

{
    "batch_id": "1318888888888888888888888888888888888888888",
    "create_time": "2023-05-15T15:19:09+08:00",
    "out_batch_no": "1684135149"
}

至此,商家轉(zhuǎn)賬到零錢成功

由于這個(gè)API不具備回調(diào)功能所以想知道轉(zhuǎn)賬的狀態(tài)只有2種辦法

1.微信商戶后臺直接去查詢(不建議,麻煩)

2.通過api查詢

由于yansongda V3版本并沒有直接提供一些查詢方法,但是微信所有的方法都封裝到了插件里面。

具體文檔

傳送門

image.png

由于我們需要去查詢"商家付款到零錢"是否成功,所以需要找到這些類

image.png

可以去看看具體源碼的實(shí)現(xiàn),這里直接列出最終請求的地方

image.png

從上述代碼中可以看出,如果想通過商家批次單號查詢批次單QueryOutBatchNoPlugin查詢訂單,需要傳入兩個(gè)參數(shù),其他具體的可選參數(shù)可以通過"微信官網(wǎng)文檔"查看

具體代碼

class TestController {
  public function queryOutBatch() {
        $pay = Pay::wechat(config('pay'));
        //   獲取插件
        $plugins = $pay->mergeCommonPlugins([QueryOutBatchNoPlugin::class]);
        // need_query_detail:【是否查詢轉(zhuǎn)賬明細(xì)單】 true-是;false-否,默認(rèn)否。商戶可選擇是否查詢指定狀態(tài)的轉(zhuǎn)賬明細(xì)單,當(dāng)轉(zhuǎn)賬批次單狀態(tài)為“FINISHED”(已完成)時(shí),才會返回滿足條件的轉(zhuǎn)賬明細(xì)單
        $result = $pay->pay($plugins ,['out_batch_no' => '1684122786','need_query_detail' => false]);
        return response()->json($result);
  }
}

查詢返回

image.png

如果想通過其他的方法去查詢,在上述獲取插件的方法,傳入對應(yīng)的類,調(diào)用該類,并傳入對應(yīng)的值即可

如果遇到提示:此IP地址不允許調(diào)用該接口

則表示未配置白名單,去配置一下即可


image.png

去設(shè)置


image.png

添加即可,可能會有延遲。


image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容