tp5 php 对接通联支付的协议支付

话不多说,直接上代码。

以获取签约短信为例

  /**
     * 签约短信
     * @param $data
     * @return array
     * @throws BaseException
     */
    public function bindMsg($data)
    {
        $nonceStr = $this->nonceStr();//流水号
        // API参数
        $params = [
            'INFO'=>[
                'TRX_CODE' => '310001',
                'VERSION' => '04',
                'DATA_TYPE' => '2',
                'LEVEL' => '5',
                'MERCHANT_ID' => $this->config['mch_id'],
                'USER_NAME' => $this->config['username'],  
                'USER_PASS' => $this->config['userpass'],
                'REQ_SN' => $nonceStr,
            ],
            'FAGRA'=>[
                'MERCHANT_ID' => $this->config['mch_id'],
                'ACCOUNT_TYPE' => $data['account_type'],
                'ACCOUNT_NO' => $data['account_no'],
                'ACCOUNT_NAME' => $data['account_name'],
                'ACCOUNT_PROP' => $data['account_prop'],
                'ID_TYPE' => $data['id_type'],
                'ID' => $data['id'],
                'TEL' => $data['tel']
            ]
        ];
        // 生成签名
        $params['INFO']['SIGNED_MSG'] = $this->makeSign($params);
        $this->doLogs($params);
        // 请求API
        $url = $this->config['url'].'?MERCHANT_ID='.$this->config['mch_id'].'&REQ_SN='.$nonceStr;
        $postData = iconv("UTF-8//IGNORE", "GBK", $this->toXml($params));
        $ret_xml = $this->post($url, $postData);
        $ret_json = $this->fromXml($ret_xml);
        //验签
        if(!$this->verifySign($ret_xml)){
           throw new BaseException(['msg' => "验签失败!",'code'=>0]);
        }
        return $ret_json;
    }

第一步:生成签名,通过私钥文件生成签名

    /**
     * 生成签名
     * @param $data
     * @return string 
     */
    private function makeSign($data)
    {
        $data = iconv("UTF-8//IGNORE", "GBK", $this->toXml($data));
        $pwd = $this->config['pravate_cert_password'];
        $certPath = $this->config['pravate_cert_path'];//私钥文件地址
        $privateKey = file_get_contents($certPath);
        if (!$privateKey) {
            throw new BaseException(['msg' => "读取密钥文件失败",'code'=>0]);
        }
        openssl_pkcs12_read($privateKey, $certs, $pwd);
        if(!openssl_sign($data, $signature, $certs['pkey'])){
            return false;
        } 
        $sign = bin2hex($signature); //strtoupper
        return $sign;
    }

第二步:输出xml字符

    /**
     * 输出xml字符
     * @param $values
     * @return bool|string
     */
    private function toXml($values)
    {
        if (!is_array($values) || count($values) <= 0) {
            return false;
        }
        $xml = '<?xml version="1.0" encoding="GBK"?><AIPG>';
        foreach ($values as $key => $val) {
            $xml .= "<" . $key . ">";
            foreach ($val as $k => $v) {
                $xml .= "<" . $k . ">" . $v . "</" . $k . ">";
            }
            $xml .="</" . $key . ">";
        }
        $xml .= "</AIPG>";
        return $xml;
    }

第三步:发起post请求

    /**
     * 模拟POST请求
     * @param $url
     * @param array $data
     * @param bool $useCert
     * @param array $sslCert
     * @return mixed
     */
    protected function post($url, $data = [])
    {
        $header = [
            'Content-Type:text/html; charset=GBK;'
        ];
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
        curl_setopt($curl, CURLOPT_HEADER, false);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_POST, TRUE);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        $result = curl_exec($curl);
        curl_close($curl);
        return $result;
    }

第四步:将返回数据xml转为数组

    /**
     * 将xml转为array
     * @param $xml
     * @return mixed
     */
    private function fromXml($xml)
    {
        // 禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        return json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
    }

第五步:回调数据验签

    /**
     * 校验签名
     * @param array 参数
     */
    private function verifySign($xmlString){
        preg_match('/\<SIGNED_MSG\>([\s\S]*?)<\/SIGNED_MSG\>/', $xmlString, $matches);
        $sign = $matches[1];
        $data = str_replace($matches[0], '', $xmlString);
        $sign = hex2bin($sign);
        $filePath = $this->config['public_cert_path'];//公钥地址
        $cert = file_get_contents($filePath);
        if (!$cert) {
            throw new BaseException(['msg' => "读取密钥文件失败",'code'=>0]);
        }
        $publickey =  '-----BEGIN CERTIFICATE-----'.PHP_EOL
        .chunk_split(base64_encode($cert), 64, PHP_EOL)
        .'-----END CERTIFICATE-----'.PHP_EOL;
        $key = openssl_get_publickey($publickey);
        $result = openssl_verify($data, $sign, $key, OPENSSL_ALGO_SHA1) === 1;
        openssl_free_key($key);
        return $result;
    }

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值