php 接入建行惠市寶的驗籤規則

官方提供的代碼包,只有java代碼示例,費了九牛二虎之力,在羣裏溝通了應該有一個星期,把建行的驗籤規則的php寫法完成了。大家各取所需。

<?php

namespace app\data\repository\api;

use app\data\repository\common\CommonRepo;
use think\admin\extend\CodeExtend;
use think\admin\extend\HttpExtend;

/**
 * 惠市寶接口封裝(建行)
 * Class Huishibao
 * @package app\data\repository\api
 */
class Huishibao
{
    /**
     * 生成訂單接口
     *
     * @param string $order_no
     * @param float $amount
     * @param string $openid
     * @return array
     */
    public function reqGatherPlaceorder($order_no, $amount, $openid)
    {
        $url = 'https://xxx/gatherPlaceorder';
        $amount = CommonRepo::returnMoney($amount);

        $param = [
            'Ittparty_Stm_Id' => config('huishibao.Ittparty_Stm_Id'), // 發起渠道編號,默認送5個0
            'Py_Chnl_Cd' => config('huishibao.Py_Chnl_Cd'), // 支付渠道代碼,默認送25個0
            'Ittparty_Tms' => $this->time_ms(), // 發起方時間戳,yyyyMMddHHmmssfff 年月日, 時分秒,毫秒
            'Ittparty_Jrnl_No' => CommonRepo::create_uuid(), // 發起方流水號,該筆直連交易的客戶方流水號(不允許重複)
            'Mkt_Id' => config('huishibao.Mkt_Id'),  // 14位市場編號,該字段由銀行在正式上線前提供,測試階段有測試數據
            'Main_Ordr_No' => $order_no, // 客戶方主訂單流水號,不允許重複
            'Sub_Appid' => config('huishibao.Sub_Appid'),
            'Sub_Openid' => $openid,
            // 'Pymd_Cd' => '03', // 支付方式,01 PC端(收銀臺) 02 線下支付 03 移動端H5頁面 (收銀臺,支持app) 05 微信小程序 06 對私網銀 07 聚合二維碼 08龍支付 09被掃 11數字電子錢包 12無感支付 13共享錢包 14支付寶小程序
            'Pymd_Cd' => '05', // 支付方式,01 PC端(收銀臺) 02 線下支付 03 移動端H5頁面 (收銀臺,支持app) 05 微信小程序 06 對私網銀 07 聚合二維碼 08龍支付 09被掃 11數字電子錢包 12無感支付 13共享錢包 14支付寶小程序
            'Py_Ordr_Tpcd' => '03', // 訂單類型,03在途訂單(只有是否支持在途模式爲“是”時纔可以使用,品類管控市場訂單類型必須爲03),04普通訂單
            'Ccy' => '156', // 幣種,156人民幣
            'Ordr_Tamt' => $amount, // 訂單總金額
            'Txn_Tamt' => $amount, // 交易總金額
            'Pay_Dsc' => '在線支付',
            'Orderlist' => [ // 訂單類型爲“04普通訂單”時,子訂單列表至少要有1條記錄,訂單類型爲“02 消費券購買訂單”或“03 在途訂單”時,子訂單列表固定爲1條記錄
                [
                    'Mkt_Mrch_Id' => config('huishibao.Mkt_Mrch_Id'), // 商家編號,20位商家編號,該字段由銀行在正式上線前提供,測試階段有測試數據,訂單類型爲“03在途訂單”時,填寫市場方商家編號(市場編號+000000)
                    'Cmdty_Ordr_No' => $order_no, // 客戶方子訂單編號不允許重複
                    'Ordr_Amt' => $amount, // 訂單商品總金額,即應付金額,所有商品訂單金額之和等於主訂單金額;
                    'Txnamt' => $amount, // 消費者實付金額,所有商品訂單金額之和等於主交易總金額
                ]
            ],
            'Vno' => '4', // 版本號,默認填寫版本4
        ];

        $res_data = $this->commReq($url, $param);
        return $res_data;
    }

    /**
     * 查詢訂單信息
     *
     * @param string $order_no
     * @return array
     */
    public function reqOrderInfQuery($order_no)
    {
        $url = 'https://xxx/OrderInfQuery';

        $param = [
            'Ittparty_Stm_Id' => config('huishibao.Ittparty_Stm_Id'), // 發起渠道編號,默認送5個0
            'Py_Chnl_Cd' => config('huishibao.Py_Chnl_Cd'), // 支付渠道代碼,默認送25個0
            'Ittparty_Tms' => $this->time_ms(), // 發起方時間戳,yyyyMMddHHmmssfff 年月日, 時分秒,毫秒
            'Ittparty_Jrnl_No' => CommonRepo::create_uuid(), // 發起方流水號,該筆直連交易的客戶方流水號(不允許重複)
            'Mkt_Id' => config('huishibao.Mkt_Id'),  // 14位市場編號,該字段由銀行在正式上線前提供,測試階段有測試數據
            'Main_Ordr_No' => $order_no,
            'Vno' => '4', // 版本號,默認填寫版本4
        ];

        $res_data = $this->commReq($url, $param);
        return $res_data;
    }

    /**
     * 確認收貨接口
     * 1、請避免在0點前後5分鐘內進行確認收貨。
     * 2、本接口不適用於品類管控的市場。
     *
     * @param string $order_no_huishibao 惠市寶生成的訂單編號
     * @return array
     */
    public function reqMergeNoticeArrival($order_no_huishibao)
    {
        $url = 'https://xxx/mergeNoticeArrival';

        $param = [
            'Ittparty_Stm_Id' => config('huishibao.Ittparty_Stm_Id'), // 發起渠道編號,默認送5個0
            'Py_Chnl_Cd' => config('huishibao.Py_Chnl_Cd'), // 支付渠道代碼,默認送25個0
            'Ittparty_Tms' => $this->time_ms(), // 發起方時間戳,yyyyMMddHHmmssfff 年月日, 時分秒,毫秒
            'Ittparty_Jrnl_No' => CommonRepo::create_uuid(), // 發起方流水號,該筆直連交易的客戶方流水號(不允許重複)
            'Mkt_Id' => config('huishibao.Mkt_Id'),  // 14位市場編號,該字段由銀行在正式上線前提供,測試階段有測試數據
            'Prim_Ordr_No' => $order_no_huishibao, // 惠市寶生成的訂單編號
            'Vno' => '4', // 填寫版本爲4
        ];

        $res_data = $this->commReq($url, $param);
        return $res_data;
    }

    /**
     * 查詢支付結果接口
     *
     * @param string $order_no
     * @return array
     */
    public function reqGatherEnquireOrder($order_no)
    {
        $url = 'https://xxx/gatherEnquireOrder';

        $param = [
            'Ittparty_Stm_Id' => config('huishibao.Ittparty_Stm_Id'), // 發起渠道編號,默認送5個0
            'Py_Chnl_Cd' => config('huishibao.Py_Chnl_Cd'), // 支付渠道代碼,默認送25個0
            'Ittparty_Tms' => $this->time_ms(), // 發起方時間戳,yyyyMMddHHmmssfff 年月日, 時分秒,毫秒
            'Ittparty_Jrnl_No' => CommonRepo::create_uuid(), // 發起方流水號,該筆直連交易的客戶方流水號(不允許重複)
            'Mkt_Id' => config('huishibao.Mkt_Id'),  // 14位市場編號,該字段由銀行在正式上線前提供,測試階段有測試數據
            'Main_Ordr_No' => $order_no,
            'Vno' => '4', // 版本號,默認填寫版本4
        ];

        $res_data = $this->commReq($url, $param);
        return $res_data;
    }

    /**
     * 訂單全額退款接口
     *
     * @param string $refund_no 退款流水號
     * @param string $order_no_huishibao_flow 惠市寶生成的交易流水號
     * @return array
     */
    public function reqRefundOrderFull($refund_no, $order_no_huishibao_flow)
    {
        $url = 'https://xxx/refundOrder';

        $param = [
            'Ittparty_Stm_Id' => config('huishibao.Ittparty_Stm_Id'), // 發起渠道編號,默認送5個0
            'Py_Chnl_Cd' => config('huishibao.Py_Chnl_Cd'), // 支付渠道代碼,默認送25個0
            'Ittparty_Tms' => $this->time_ms(), // 發起方時間戳,yyyyMMddHHmmssfff 年月日, 時分秒,毫秒
            'Ittparty_Jrnl_No' => CommonRepo::create_uuid(), // 發起方流水號,該筆直連交易的客戶方流水號(不允許重複)
            'Mkt_Id' => config('huishibao.Mkt_Id'),  // 14位市場編號,該字段由銀行在正式上線前提供,測試階段有測試數據
            'Cust_Rfnd_Trcno' => $refund_no, // 該字段由發起方生成,請求退款時不允許重複(當出現請求超時情況時,客戶可憑藉此字段重複發起退款,對於同一筆客戶方退款流水號,惠市寶確保只發生一次退款)。重複流水號可查詢該流水號退款請求結果;不同流水號爲發起新請求。
            'Py_Trn_No' => $order_no_huishibao_flow, // 惠市寶生成,與該訂單的支付動作唯一匹配
            'Vno' => '4', // 版本號,默認填寫版本4
        ];

        $res_data = $this->commReq($url, $param);
        return $res_data;
    }

    /**
     * 訂單部分退款接口
     *
     * @param string $refund_no 退款流水號
     * @param string $order_no_huishibao_flow 惠市寶生成的交易流水號
     * @param string $order_no_sub 惠市寶生成的子訂單編號
     * @param string $amount 部分退款金額
     * @return array
     */
    public function reqRefundOrder($refund_no, $order_no_huishibao_flow, $order_no_sub, $amount)
    {
        $url = 'https://xxx/refundOrder';
        $amount = CommonRepo::returnMoney($amount);

        $param = [
            'Ittparty_Stm_Id' => config('huishibao.Ittparty_Stm_Id'), // 發起渠道編號,默認送5個0
            'Py_Chnl_Cd' => config('huishibao.Py_Chnl_Cd'), // 支付渠道代碼,默認送25個0
            'Ittparty_Tms' => $this->time_ms(), // 發起方時間戳,yyyyMMddHHmmssfff 年月日, 時分秒,毫秒
            'Ittparty_Jrnl_No' => CommonRepo::create_uuid(), // 發起方流水號,該筆直連交易的客戶方流水號(不允許重複)
            'Mkt_Id' => config('huishibao.Mkt_Id'),  // 14位市場編號,該字段由銀行在正式上線前提供,測試階段有測試數據
            'Cust_Rfnd_Trcno' => $refund_no, // 該字段由發起方生成,請求退款時不允許重複(當出現請求超時情況時,客戶可憑藉此字段重複發起退款,對於同一筆客戶方退款流水號,惠市寶確保只發生一次退款)。重複流水號可查詢該流水號退款請求結果;不同流水號爲發起新請求。
            'Py_Trn_No' => $order_no_huishibao_flow, // 惠市寶生成,與該訂單的支付動作唯一匹配
            'Rfnd_Amt' => $amount, // 訂單全額退款時不需要送,訂單部分退款時必須送此值,且值等於所有子訂單的退款金額之和
            'Sub_Ordr_List' => [
                [
                    'Sub_Ordr_Id' => $order_no_sub, // 惠市寶生成的子訂單編號
                    'Rfnd_Amt' => $amount,
                ],
            ],
            'Vno' => '4', // 版本號,默認填寫版本4
        ];

        $res_data = $this->commReq($url, $param);
        return $res_data;
    }

    /**
     * 分賬狀態查詢接口
     *
     * @param string $order_no_huishibao_flow 惠市寶生成的交易流水號
     * @return array
     */
    public function reqSubAccountEnquire($order_no_huishibao_flow)
    {
        $url = 'https://xxx/subAccountEnquire';

        $param = [
            'Ittparty_Stm_Id' => config('huishibao.Ittparty_Stm_Id'), // 發起渠道編號,默認送5個0
            'Py_Chnl_Cd' => config('huishibao.Py_Chnl_Cd'), // 支付渠道代碼,默認送25個0
            'Ittparty_Tms' => $this->time_ms(), // 發起方時間戳,yyyyMMddHHmmssfff 年月日, 時分秒,毫秒
            'Ittparty_Jrnl_No' => CommonRepo::create_uuid('', false), // 發起方流水號,該筆直連交易的客戶方流水號(不允許重複)
            'Mkt_Id' => config('huishibao.Mkt_Id'),  // 14位市場編號,該字段由銀行在正式上線前提供,測試階段有測試數據
            'Py_Trn_No' => $order_no_huishibao_flow,
            'Vno' => '5', // 填寫版本爲4
        ];

        $res_data = $this->commReq($url, $param);
        return $res_data;
    }

    /**
     * 在途信息確認接口
     *
     * @param string $order_no_huishibao_flow 惠市寶生成的交易流水號
     * @param array $part_list 分賬方列表 [[ 'Seq_No' => 1, 'Mkt_Mrch_Id' => '41060860800392000000', 'Amt' => 1 ]]
     * @return array
     */
    public function reqConfirmOnTheWay($order_no_huishibao_flow, $part_list)
    {
        $url = 'https://xxx/confirmOnTheWay';

        $param = [
            'Ittparty_Stm_Id' => config('huishibao.Ittparty_Stm_Id'), // 發起渠道編號,默認送5個0
            'Py_Chnl_Cd' => config('huishibao.Py_Chnl_Cd'), // 支付渠道代碼,默認送25個0
            'Ittparty_Tms' => $this->time_ms(), // 發起方時間戳,yyyyMMddHHmmssfff 年月日, 時分秒,毫秒
            'Ittparty_Jrnl_No' => CommonRepo::create_uuid(), // 發起方流水號,該筆直連交易的客戶方流水號(不允許重複)
            'Mkt_Id' => config('huishibao.Mkt_Id'),  // 14位市場編號,該字段由銀行在正式上線前提供,測試階段有測試數據
            'Py_Trn_No' => $order_no_huishibao_flow,
            'Parlist' => $part_list,
            'Vno' => '3', // 填寫版本爲3
        ];

        $res_data = $this->commReq($url, $param);
        return $res_data;
    }

    /**
     * 返回結果驗籤
     *
     * @param string $str_raw
     * @param string $string
     * @return int
     */
    public function valid_encrypt($str_raw, $string)
    {
        $key = chunk_split(config('huishibao.public_key_bank'), 64, "\n");

        $key = "-----BEGIN PUBLIC KEY-----\n" . wordwrap($key) . "-----END PUBLIC KEY-----";
        $result = openssl_verify($str_raw, base64_decode($string), $key, OPENSSL_ALGO_SHA256);
        return $result;
    }

    /**
     * @return \think\Response
     */
    public function res_error()
    {
        return response('forbid', 401);
    }

    /**
     * @return void
     */
    public function res_success()
    {
        $success_data = [
            'Svc_Rsp_St' => '00', // 服務響應狀態,00-成功,01-失敗
        ];
        CommonRepo::echo_json($success_data);
    }

    /**
     * 寫文件
     *
     * @param string $path
     * @param string $content
     * @return int|false
     */
    public function filePutContent($path, $content, $type = '')
    {
        $date = date('c');
        $content = "[{$date}] [{$type}] {$content}\n";
        return file_put_contents($path, $content, FILE_APPEND);
    }

    /**
     * @param array $param
     * @return string
     */
    public function join_param(array $param)
    {
        unset($param['Sign_Inf']);
        unset($param['Svc_Rsp_St']);
        unset($param['Svc_Rsp_Cd']);
        unset($param['Rsp_Inf']);

        ksort($param);

        $str = '';
        foreach ($param as $k => $v) {
            if ($v !== '') {
                if (is_array($v)) {
                    if (is_array($v[0])) {
                        foreach ($v as $vv) {
                            $str .= ($this->join_param($vv) . '&');
                        }
                    } else {
                        $str .= ($this->join_param($v) . '&');
                    }
                } else {
                    $str .= "$k=$v&";
                }
            }
        }
        $str = trim($str, '&');
        return $str;
    }

    /**
     * @param string $url
     * @param array $param
     * @return array
     */
    private function commReq($url, $param)
    {
        $param_str = $this->join_param($param);
        $param['Sign_Inf'] = $this->encrypt($param_str); // 簽名信息,將上述參數進行拼接並用私鑰生成簽名
        $opt = [
            'headers' => [
                'Content-Type: application/json; charset=utf-8',
            ],
        ];
        $res = HttpExtend::post($url, CommonRepo::jsonRet($param), $opt);
        $res_data = CommonRepo::jsonDecode($res);
        return $res_data;
    }

    /**
     * @param string $str
     * @return string
     */
    private function encrypt($str)
    {
        $key = chunk_split(config('huishibao.private_key'), 64, "\n");

        $key = "-----BEGIN RSA PRIVATE KEY-----\n" . wordwrap($key) . "-----END RSA PRIVATE KEY-----";
        $res = openssl_sign($str, $sign, $key, OPENSSL_ALGO_SHA256);
        if (!$res) {
            die('sign fail');
        }
        $sign = base64_encode($sign);
        return $sign;
    }

    /**
     * 發起方時間戳,yyyyMMddHHmmssfff 年月日, 時分秒,毫秒
     * @return string
     */
    private function time_ms()
    {
        return CommonRepo::timeCut(null, 'no_space') . '000';
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章