银联在线支付对接流程以及签名算法

银联在线支付

简介

银联在线支付支持PC网关、手机SDK、WAP网关、云闪付等多种支付场景,其中云闪付产品可以完美支持ApplePay、Samsung Pay、Huawei Pay等市面上常见的手机厂商推出的支付品牌,对接银联在线支付,可弥补因无微信客户端和支付宝客户端所造成的用户流失,还可以做形式多样的支付优惠活动,银联可通过对商户号交易控制实现其立减、满减等支付优惠活动。

支付流程

根据开发文档组织支付报文,发起网关支付请求。APP支付,需要curl请求支付网关(appTransReq.do),获取到tn码,然后app通过tn码发起支付请求。PC、WAP网关支付,则直接将支付报文通过表单POST提交至银联支付网关(frontTransReq.do)。

签名机制

银联在线支付,商户端在调用支付网关、退款网关、支付查询网关、退款查询网关等业务需要使用OpenSSL对报文进行非对称加密,加密证书类型为RSA,加密算法为SHA-1。同样,商户端对来自银联发来的数据报文,也要同样的使用银联提供的公钥文件对其签名做验证操作;

在线开发文档

https://open.unionpay.com/ajweb/product

证书下载、导出流程

https://open.unionpay.com/ajweb/help/file/techFile?cateLog=agreement

银联在线支付签名验签算法

  • PHP版本
/**
 * 银联在线支付demo
 * 使用OpenSSL进行非对称加密、验签
 * @author think2017@gmail.com
 */
class chinapayPayment
{
    
    
    public function __construct()
    {
        
    }
    
    
    /**
     **@desc 获取支付请求报文
     **/
    public function ransReqParams()
    {
        //Todo...
    }
    
    
    /**
     **@desc 退款申请
     **/
    public function doRefund()
    {
        //Todo...
    }
    
    
    /**
     **@desc 支付查询
     **/
    public function doQuery()
    {
        //Todo...
    }
    
    
    /**
     **@desc 退款查询
     **/
    public function doRefundQuery()
    {
        //Todo...
    }
    
    
    /**
    * 使用商户私钥文件对报文进行签名
    */
    public function signature($postPrams)
    {
        ksort($postPrams);

        $strInfo = '';
        foreach ($postPrams as $key=>$val) {
            if($strInfo){
                $strInfo .= "&".$key."=".$val;
            }else{
                $strInfo = $key."=".$val;
            }
        }
        
        $retval = $this->readPrivateKeyData();
        
        if ($retval['code'] != 200) {
           return false;
        }

        $sha1x16 = sha1($strInfo, FALSE);
        if (openssl_sign($sha1x16, $signature, $retval['privateKey'], OPENSSL_ALGO_SHA1)) {
            $signatureBase64 = base64_encode($signature);
        }

        return $signatureBase64 ? $signatureBase64 : false;
    }
    
    
    /**
    * 使用银行公钥文件进行验签
    */
    public function verfiySign($requestData)
    {
        $retval = $this->readPublicKeyData();
        
        if ($retval['code'] != 200) {
           return false;
        }
        
        $isSuccess = false;
        
        if( $retval['certId'] == $requestData['certId'] ){
            $signature = $requestData['signature'];
            unset($requestData['signature']);
            $sRequest = $this->coverParamsToString($requestData);
            $sha1x16 = sha1($sRequest, false);
            $isSuccess = openssl_verify($sha1x16, base64_decode($signature), $retval['publicKey'], OPENSSL_ALGO_SHA1);
        }
        
        return $isSuccess;
    }
    

    /**
     * 读取商户私钥,私钥证书文件后缀为.pfx
    **/
    private function readPrivateKeyData()
    {
        $pkcs12 = file_get_contents($this->privateKeyFile);

        if (openssl_pkcs12_read($pkcs12, $certs, $this->privatekeyPass)) { 
            $x509data = $certs ['cert'];
            openssl_x509_read ( $x509data );
            $certdata = openssl_x509_parse ( $x509data );
            return ['code' => 200, 'certId' => $certdata['serialNumber'], 'privateKey' => $certdata['pkey']];
        }
        
        return ['code' => 500, 'certId' => '', 'privateKey' => ''];
    }
    
    

    /**
     * 读取银行公钥,公钥证书文件后缀为.cer
    **/
    private function readPublicKeyData()
    {
        $x509data = file_get_contents($this->publicKeyFile);
        openssl_x509_read($x509data);
        $certdata = openssl_x509_parse($x509data);
        
        if ($certdata) {
            return ['code' => 200, 'certId' => $certdata['serialNumber'], 'publicKey' => $x509data];
        }
        
        return ['code' => 500, 'certId' => '', 'publicKey' => ''];
    }

    
    /**
     * 数组 排序后转化为字体串
     * @param array $params            
     * @return string
     */
    public function coverParamsToString($params) 
    {
        $strSign = '';
        ksort($params);
        foreach($params as $key => $val){
            if($key == 'signature'){
                continue;
            }
            $strSign .= sprintf("%s=%s&", $key, $val);
        }
        return substr($strSign, 0, strlen($strSign) - 1);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值