PHP icbc工商銀行オープンプラットフォーム集約支払い、QRコードスキャン支払いドッキングステップ

66970 ワード

前言最近、仕事の原因で工商銀行の微信重合支払いインターフェースとQRコードスキャン支払いインターフェースをドッキングし、ネット上のphpチュートリアルが少なすぎるので、ドッキング手順を記録します.プログラム開発前の準備
1、関連インタフェースのドキュメントを読んで、工商銀行の支払いインタフェースの呼び出しの流れを熟知して、インタフェースのドキュメントの住所は以下の通りです:工商銀行のインタフェースのドキュメント.添付:集約支払インタフェース、QRコードスキャン支払インタフェース
2、関連するパラメータを準備する.共通パラメータは以下の通りである.
appid:工商銀行appid mer_id:工商銀行口座番号、商戸線下ファイル番号、特約商戸12位、特約部門15位store_code:e生活ファイル番号icbc_pulic_key:ゲートウェイ公開鍵private_key:秘密鍵publicを適用するkey:公開鍵encryptKeyの適用:AES暗号化鍵
2.1、関連パラメータソースappid,mer_id,store_code,icbc_pulic_keyはすべて工行のスタッフに提供して、private_keyは公開秘密鍵ペアを適用してjavaSdkをダウンロードした後、自分で生成することができる.Windows環境では、RSAアルゴリズムの生成を例に、binディレクトリに入り、keygen_をダブルクリックします.rsa.batファイルは、一対のRSA公開鍵と鍵を生成します.Linux環境、RSAアルゴリズムの生成を例に:binディレクトリに切り替え、実行./keygen_rsa.shコマンドは、一対のRSA公開鍵と鍵を生成します.公開秘密鍵ペアを生成した後、公開鍵をスタッフに構成します.アルゴリズムの復号化のためにencryptKey(AES暗号化鍵)構成も提供する必要があることに注意してください.
3、従業員と関連インタフェースの開通を申請して、工行はインタフェースを分けて開放して、インタフェースはあなたの口座の下に配置しなければならなくて、やっと呼び出すことができます.
4、ダウンロード工行のphpsdk注意事項:中にphpをインストールすることを要求するinfosec拡張、この拡張はca検証を完了するためにインストールされたもので、公衆番号集約支払いとQRコードスキャン支払いインタフェースは一般的にca検証ではなく、RSA 2とAESだけでは使用できないはずです.公開アルゴリズムだからです.
5、コード例、コードクラスを使用するときは、主にSDKファイルをクラスに導入します.

/**
 * Created by PhpStorm.
 * User: lv
 * Date: 2020/3/10
 * Time: 13:37
 */

/**
 *     :            
 */
class IcbcPay
{
    function __construct()
    {
        //    
        require_once(ROOT_PATH . 'data/extend/icbc/icbc-api-sdk-cop-php/DefaultIcbcClient.php');
        require_once(ROOT_PATH . 'data/extend/icbc/icbc-api-sdk-cop-php/UiIcbcClient.php');
    }

    public function index()
    {
        //         
    }


    /**
     *       
     *
     * @return unknown
     */
    public function getIcbcpayConfig()
    {
        //     appid(       )
        $icbc_config['appid'] = '';

        //         (        (    12 ,    15 ))
        $icbc_config['mer_id'] = '';

        // e      
        $icbc_config['store_code'] = '';

        //    ,       1.0.0.1
        $icbc_config['interface_version'] = '1.0.0.1';

        //      ID;              ,           appid
        $icbc_config['tp_app_id'] = '';

        //     
        $icbc_config['icbc_pulic_key'] = '';

        //     
        $icbc_config['private_key'] = '';

        //     
        $icbc_config['encrypt_key'] = '';

        return $icbc_config;
    }

    /**
     * @param $msg_id //        ,        ,APP   
     * @param $tp_open_id //       ;        /            ,       appid      。
     * @param $out_trade_no //     ;         
     * @param string $tran_type //     OfflinePay-    ,OnlinePay-    
     * @param $goods_body //        
     * @param $goods_detail //      {‘good_name’:’    300ml  ’,’good_id’:’1001’,’good_num’:’1’}
     * @param $order_amount //    (  : )
     * @param $return_url //         。     ,             
     * @param $notify_url //         ;
     * @param $mer_hint //     。      ,               
     * @param $attach //     。         
     * @return string
     *                 ,     !
     */
    public function setAPV2Pay($msg_id, $tp_open_id, $out_trade_no, $tran_type = 'OnlinePay', $goods_body, $goods_detail, $order_amount, $return_url, $notify_url, $mer_hint, $attach)
    {

        $icbc_config = $this->getIcbcpayConfig();

        //     ID;              ,           ID;               ,          ID。
        $tp_app_id = $icbc_config['tp_app_id'];

        //    。     1-   ,          
        $install_times = '1';

        //    ,                        。   “HS”:           ,       ,     notify_url    ;   “AG”:           
        $notify_type = 'HS';

        //      ,     HS   。  “0”:          ,              ;  “1”,                 ,          
        $result_type = '0';


        $content = array(
            "interface_version" => (string)$icbc_config['interface_version'],
            "mer_id"            => (string)$icbc_config['mer_id'],
            "tp_app_id"         => (string)$tp_app_id,
            "tp_open_id"        => (string)$tp_open_id,
            "out_trade_no"      => (string)$out_trade_no,
            "tran_type"         => (string)$tran_type,
            "order_date"        => (string)date("YmdHis", $_SERVER['REQUEST_TIME']),
            "end_time"          => (string)date("YmdHis", $_SERVER['REQUEST_TIME'] + 300),  // order_date  5  
            "goods_body"        => (string)$goods_body,
            "goods_detail"      => (string)$goods_detail,
            "order_amount"      => (string)bcmul($order_amount, 100), //   (   )
            "spbill_create_ip"  => (string)$_SERVER['REMOTE_ADDR'],
            "install_times"     => (string)$install_times,
            "return_url"        => (string)$return_url, //     
            "notify_url"        => (string)$notify_url, //       
            "notify_type"       => (string)$notify_type,
            "result_type"       => (string)$result_type,
        );

        if (!empty($attach)) $content['attach'] = $attach;
        if (!empty($mer_hint)) $content['mer_hint'] = $mer_hint;


        //      
        $serviceUrl = 'https://gw.open.icbc.com.cn/ui/aggregate/payment/request/V2';

        //      
        $request = array(
            "serviceUrl"    => $serviceUrl,
            "method"        => 'POST',//     ,   POST GET
            "isNeedEncrypt" => true,//       
            "extraParams"   => null,//    ,     array
            "biz_content"   => $content,
        );

        //  form    
        $resp = $this->icbcClientForm($icbc_config, $request, $msg_id);

        return $resp;
    }


    /**
     *            
     *                 ,     。
     */
    public function getPayQrCode($msg_id, $out_trade_no, $pay_expire, $order_amt, $notify_url, $attach)
    {
        $icbc_config = $this->getIcbcpayConfig();

        //           0- ;1- ; 1 0  ,          
        $notify_flag = '1';

        //           ,0: ,1: ; 1 0  ,          
        $sp_flag = '0';

        $content = array(
            'mer_id'            => (string)$icbc_config['mer_id'],
            'out_trade_no'      => (string)$out_trade_no,
            'store_code'        => (string)$icbc_config['store_code'],//e      
            'order_amt'         => (string)bcmul($order_amt, 100), //   (   )
            'trade_date'        => (string)date("Ymd", $_SERVER['REQUEST_TIME']),  //      
            'trade_time'        => (string)date("His", $_SERVER['REQUEST_TIME']),  //      
            'tporder_create_ip' => (string)$_SERVER['REMOTE_ADDR'],
            'notify_url'        => (string)$notify_url, //       
            'notify_flag'       => (string)$notify_flag,
            'sp_flag'           => (string)$sp_flag,
            'pay_expire'        => (string)$pay_expire,//       
        );

        if (!empty($attach)) $content['attach'] = $attach;

        //      
        $serviceUrl = 'https://gw.open.icbc.com.cn/api/qrcode/V2/generate';

        //      
        $request = array(
            "serviceUrl"    => $serviceUrl,
            "method"        => 'POST',//     ,   POST GET
            "isNeedEncrypt" => false,//       
            "extraParams"   => null,//    ,     array
            "biz_content"   => $content,
        );

        //  curl  ,      
        $resp = $this->icbcClientCurl($icbc_config, $request, $msg_id);

        return $resp;
    }


    /**
     *     ,    ,          form  
     * @param $icbc_config
     * @param $json_content
     * @param $msg_id
     */
    public function icbcClientForm($icbc_config, $request, $msg_id)
    {

        //APP   ,   API         
        $appId = $icbc_config['appid'];

        //    
        $privateKey = $icbc_config['private_key'];

        //    ,CA-         ,RSA-RSAWithSha1,RSA2-RSAWithSha256,   RSA2,
        $signType = \IcbcConstants::$SIGN_TYPE_RSA2;

        //    ,   UTF-8
        $charset = 'UTF-8';

        //      ,   json
        $format = 'json';

        //    
        $icbcPulicKey = $icbc_config['icbc_pulic_key'];

        //AES    ,    
        $encryptKey = $icbc_config['encrypt_key'];

        //    ,        AES  
        $encryptType = 'AES';

        //  ca     ,     ,          ,php      php_infosec.dll,  sdk    php7.0     
        $ca = '';

        //      CA ,           ,    
        $password = '';

        //         
        $client = new \UiIcbcClient($appId, $privateKey, $signType, $charset, $format,
            $icbcPulicKey, $encryptKey, $encryptType, $ca, $password);

        //      
        $resp = $client->buildPostForm($request, $msg_id, '');

        return $resp;
    }

    /**
     *     ,    ,  curl  
     * @param $icbc_config
     * @param $json_content
     * @param $msg_id
     */
    public function icbcClientCurl($icbc_config, $request, $msg_id)
    {

        //APP   ,   API         
        $appId = $icbc_config['appid'];

        //    
        $privateKey = $icbc_config['private_key'];

        //    ,CA-         ,RSA-RSAWithSha1,RSA2-RSAWithSha256,   RSA2,
        $signType = \IcbcConstants::$SIGN_TYPE_RSA2;

        //    ,   UTF-8
        $charset = 'UTF-8';

        //      ,   json
        $format = 'json';

        //    
        $icbcPulicKey = $icbc_config['icbc_pulic_key'];

        //AES    ,    
        $encryptKey = $icbc_config['encrypt_key'];

        //    ,        AES  
        $encryptType = 'AES';

        //  ca     ,     ,          ,php      php_infosec.dll,  sdk    php7.0     
        $ca = '';

        //      CA ,           ,    
        $password = '';

        //              ,    sdk      【IcbcSignature::verify】      ,    $password  ,        。
        $client = new \DefaultIcbcClient($appId, $privateKey, $signType, $charset, $format,
            $icbcPulicKey, $encryptKey, $encryptType, $ca, $password);

        //      
        $resp = $client->execute($request, $msg_id, '');

        $resp = $resp ? json_decode($resp, true) : '';

        return $resp;
    }

    /**
     * *       
     * @param $postArr         
     * @param $notify_url    url
     * @return int|void
     * @throws Exception
     */
    public function icbcCheckSign($postArr, $notify_url)
    {
        $icbc_config = $this->getIcbcpayConfig();

        //       
        $postParame = $postArr;
        $sign       = $postParame['sign'];
        unset($postParame['sign']);
        //      
        $WebUtils      = new \WebUtils();
        $IcbcSignature = new \IcbcSignature();
        $path          = parse_url($notify_url, PHP_URL_PATH);
        $content       = $WebUtils->buildOrderedSignStr($path, $postParame);

        //    ,CA-         ,RSA-RSAWithSha1,RSA2-RSAWithSha256,   RSA2,
        $signType = \IcbcConstants::$SIGN_TYPE_RSA;

        //    ,   UTF-8
        $charset = \IcbcConstants::$CHARSET_UTF8;

        //      CA ,           ,    
        $password = '';

        //    
        $icbcPulicKey = $icbc_config['icbc_pulic_key'];

        (boolean)$signVerified = $IcbcSignature->verify($content, $signType, $icbcPulicKey, $charset, $sign, $password);

        return $signVerified;
    }

    /**
     *       demo
     */
    public function demo()
    {
        include_once('data\extend\icbc\icbc-api-sdk-cop-php/UiIcbcClient.php');
        $msg_id  = 'aa' . rand(10000000, 999999999);
        $content = array(
            "interface_version" => "1.0.0.1",
            "mer_id"            => 'mer_id',
            "tp_app_id"         => 'tp_app_id',
            "tp_open_id"        => 'tp_open_id',
            "out_trade_no"      => '12311212',
            "tran_type"         => "OfflinePay",
            "order_date"        => date("YmdHis", $_SERVER['REQUEST_TIME']),
            "end_time"          => date("YmdHis", $_SERVER['REQUEST_TIME'] + 300),  // order_date  5  
            "goods_body"        => '12',
            "goods_detail"      => "{'good_name':1,'good_id':2,'good_num':'1'}",
            "order_amount"      => bcmul(0.01, 100), //   (   )
            "spbill_create_ip"  => $_SERVER['REMOTE_ADDR'],
            "install_times"     => "1",
            "return_url"        => "http://ip/index/pay/successful", //     
            "notify_url"        => "http://ip/index/pay/notify", //       
            "notify_type"       => "HS",
            "result_type"       => "0",
        );
        $request = array(
            "serviceUrl"    => 'https://gw.open.icbc.com.cn/api/qrcode/V2/generate',
            "method"        => 'POST',
            "isNeedEncrypt" => true,
            "extraParams"   => null,
            "biz_content"   => $content,
        );

        $client = new \UiIcbcClient('appid',
            '  key',
            \IcbcConstants::$SIGN_TYPE_RSA2,
            'UTF-8',
            'json',
            '    ',
            'AES  key',
            'AES',
            '',
            '');
        $resp   = $client->buildPostForm($request, $msg_id, '');
        echo $resp;
        die;
    }
}

6、ピット注意6.1、工行公式サイトsdkファイル【DefaultIcbcClient.php】の【execute】メソッドが提供する【IcbcSignature::verify】メソッドにはパラメータが欠けており、$this->passwordパラメータを補う必要があります.そうしないと呼び出しに成功しません.完全に次のとおりです.
//    
$passed = IcbcSignature::verify($respBizContentStr, IcbcConstants::$SIGN_TYPE_RSA, $this->icbcPulicKey, $this->charset, $sign,$this->password);

6.2、【AES.php】ファイル中、@mcrypt_module_OpenシリーズメソッドはPHP 7.2から廃棄されており,エラーを報告した後にエラー抑制子を付けるか,置換スキームを書き換える必要がある.
6.3、低バージョンの工行SDK【IcbcConstants.php】ファイルの中でタイムゾーンの設定が間違っていて、東八区上海に修正する必要があります.正しいコードは以下の通りです.
/** Date     **/
//public static $DATE_TIMEZONE = "Etc/GMT+8";//java GMT+8
public static $DATE_TIMEZONE = "Asia/Shanghai";//   

6.4、注文時間について現在、工行には4セットのテスト環境があり、各テスト環境のシステム時間は現実時間と一致しない.注文時間が無効なエラーと間違えた場合、工行開発者が提供した小道具を使ってテスト環境の時間を取得し、テスト環境の時間で注文有効時間を交換してください.