银联支付php单文件实现

/*首次写csdn 博客 , 如有不足 , 还望包含 .  微信和支付宝单文件实现接口的文章较多 , 也就不往上写了 .  因为网上银联接口php方面的信息比较少, 只是需要调用银联退款接口 . 用银联下载的sdk怎么调 都报签名错误 .  后来自己基于银联 sdk 封装了一个单文件 实现 银联 查询 和 退款的接口 ,如果有需要的也可以自行添加其他接口 , 都比较简单.  其中log类可以自定义,也可以写个方法代替 , 看个人喜好就行 .  这个单文件写在这供大家参考下 , 也作为自己的备忘.*/

话不多说 ,直接上代码 . 

<?php
header('Content-Type:text/html;charset=utf-8 ');


//银联目录 ( 只用证书和日志类  可自定义)
defined('UNIONPAY_PATH') or define('UNIONPAY_PATH',$_SERVER ['DOCUMENT_ROOT']."你的证书目录"); 
//日志 目录 
defined('SDK_LOG_FILE_PATH') or define("SDK_LOG_FILE_PATH",UNIONPAY_PATH . '你的日志类目录');
//日志级别
defined('SDK_LOG_LEVEL') or define("SDK_LOG_LEVEL",'INFO');

/*使用方法*/

$Unipay = new Unipay();
$input_arr['out_trade_no'] = '第三方订单号';
$input_arr['out_refund_no'] = '退单单号' ;
$input_arr['total_fee'] = "1" ; //总金额
$input_arr['refund_fee'] = "1" ; //要退的金额
$input_arr['post_time'] = "20181101102212" ; //下单时间

var_dump($Unipay->refund($input_arr));



/*银联支付类*/
class Unipay{
    private $mch_id = '****************';  //银联商户 id
    private $cert_path = '/unionpay_pc/key/**************.pfx';  //签名证书路径
    private $cert_pwd = '******';   //签名证书密码
    private $cert_id;   //证书id
    private $backUrl;   //回调地址
    
    private $log;  //日志类
    private $signature; //签名
    
    public function __construct($mch_id='',$cert_path='',$cert_pwd=''){
        include_once UNIONPAY_PATH . '/unionpay_pc/func/log.class.php';
        $this->log = new PhpLog ( SDK_LOG_FILE_PATH, "PRC", SDK_LOG_LEVEL );
        if($mch_id!='') $this->mch_id = $mch_id;
        if($cert_path!='') {$this->cert_path = $cert_path;}else{$this->cert_path = UNIONPAY_PATH.$this->cert_path;}
        if($cert_pwd!='') $this->cert_pwd = $cert_pwd;
        $this->cert_id = $this->getSignCertId ();
        $this->backUrl = '你的回调地址';
    } 
    /**
     * 获取证书id
     */
    function getSignCertId(){
        $pkcs12certdata = file_get_contents ( $this->cert_path );
    openssl_pkcs12_read ( $pkcs12certdata, $certs, $this->cert_pwd );
    $x509data = $certs ['cert'];
    openssl_x509_read ( $x509data );
    $certdata = openssl_x509_parse ( $x509data );
    $cert_id = $certdata ['serialNumber'];
    return $cert_id;
    }
        /**
     * 申请退款
     * @param type $input_arr
     * @return type
     */
    function refund($orders,$type=''){
        //请求参数
        $query = $this->unionPayQuery('', $orders);
        if ($query['respCode'] != "00") {
            return $query;
        }
        $params = array(
          //以下信息非特殊情况不需要改动
          'version' => '5.0.0',      //版本号
          'encoding' => 'utf-8',       //编码方式
          'certId' => $this->cert_id, //证书id
          'signMethod' => '01',       //签名方法
          'txnType' => '04',         //交易类型
          'txnSubType' => '00',       //交易子类
          'bizType' => '000301',       //业务类型
          'accessType' => '0',      //接入类型
          'channelType' => '07',       //渠道类型
          'backUrl' => $this->backUrl, //后台通知地址
          //TODO 以下信息需要填写   
          'merId' => $this->mch_id,     //商户代码,请改成自己的商户号
          'orderId' =>  $orders['out_refund_no'],   //商户订单号,8-32位数字字母,不能含“-”或“_”,可以自行定制规则,重新产生-此处为在退款订单前拼接 T
          'origQryId' => $query["queryId"], //原消费的queryId,可以从查询接口或者通知接口中获取
          'txnTime' => date('YmdHis', time()),    //订单发送时间,格式为YYYYMMDDhhmmss,重新产生,不同于原消费
          'txnAmt' => $orders['refund_fee'],   //交易金额,退货总金额需要小于等于原消费
        );
        $this->sign ( $params ); // 签名
        $params['signature'] = $this->signature;
        $url = 'https://gateway.95516.com/gateway/api/backTransReq.do';
        $result_arr =  $this->to_array($this->curlPost ( $params, $url));
        $this->log->LogInfo ( json_encode($result_arr) );
        return $result_arr;
    }
    /**
     * 获取preid
     * @param type $request
     * @param type $orders
     */
    function unionPayQuery($request, $orders){
        $params = array(
          //以下信息非特殊情况不需要改动
          'version' => '5.0.0',    //版本号
          'certId' => $this->cert_id, //证书id
          'encoding' => 'utf-8',     //编码方式
          'signMethod' => '01',     //签名方法
          'txnType' => '00',       //交易类型
          'txnSubType' => '00',     //交易子类
          'bizType' => '000000',     //业务类型
          'accessType' => '0',    //接入类型
          'backUrl' => $this->backUrl,        //后台通知地址
          'channelType' => '07',     //渠道类型

          //TODO 以下信息需要填写
          'orderId' => $orders['out_trade_no'],  //请修改被查询的交易的订单号,8-32位数字字母,不能含“-”或“_”
          'merId' => $this->mch_id,   //商户代码,请改自己的测试商户号
          'txnTime' => date('YmdHis', $orders['post_time']), //请修改被查询的交易的订单发送时间,格式为YYYYMMDDhhmmss
        );
        $sign = $this->sign ( $params ); // 签名
        $params['signature'] = $this->signature;
        $url = 'https://gateway.95516.com/gateway/api/queryTrans.do';
        $result_arr = $this->to_array($this->curlPost ( $params, $url));
        $this->log->LogInfo ( json_encode($result_arr) );
        return $result_arr;
    }
    /**
    * 签名
    *
    * @param String $params_str
    */
    function sign($params) {
            $this->log->LogInfo ( '=====签名报文开始======' );
            if(isset($params['transTempUrl'])){
                    unset($params['transTempUrl']);
            }
            // 转换成key=val&串
            $params_str = $this->coverParamsToString ( $params );
            
            $this->log->LogInfo ( "签名key=val&...串 >" . $params_str );

            $params_sha1x16 = sha1 ( $params_str, FALSE );
            $this->log->LogInfo ( "摘要sha1x16 >" . $params_sha1x16 );
            // 签名证书路径
            $cert_path = $this->cert_path;
            $private_key = $this->getPrivateKey ( $cert_path );
            // 签名
            $sign_falg = openssl_sign ( $params_sha1x16, $signature, $private_key, OPENSSL_ALGO_SHA1 );
            if ($sign_falg) {
                    $signature_base64 = base64_encode ( $signature );
                    $this->log->LogInfo ( "签名串为 >" . $signature_base64 );
                    return $params ['signature'] = $this->signature = $signature_base64;
            } else {
                    $this->log->LogInfo ( ">>>>>签名失败<<<<<<<" );
            }
            $this->log->LogInfo ( '=====签名报文结束======' );
            return false;
    }
    /**
     * 数组 排序后转化为字体串
     *
     * @param array $params            
     * @return string
     */
    function coverParamsToString($params) {
            $sign_str = '';
            // 排序
            ksort ( $params );
            foreach ( $params as $key => $val ) {
                    if ($key == 'signature') {
                            continue;
                    }
                    $sign_str .= sprintf ( "%s=%s&", $key, $val );
                    // $sign_str .= $key . '=' . $val . '&';
            }
            return substr ( $sign_str, 0, strlen ( $sign_str ) - 1 );
    }
    /**
    * 返回(签名)证书私钥 -
    *
    * @return unknown
    */
    function getPrivateKey($cert_path) {
            $pkcs12 = file_get_contents ( $cert_path );
            openssl_pkcs12_read ( $pkcs12, $certs, $this->cert_pwd  );
            return $certs ['pkey'];
    }
    /**
     * 结果转数组
     * @param type $str
     * @return type
     */
    function to_array($str){
        $result_arr_1 = explode('&',$str);
        $array = array();
        foreach($result_arr_1 as $k=>$v){
            $one = explode('=',$v);
            $array[$one[0]] = $one[1];
        }
        return $array;
    }
    /**
     * curl方法
     * @param type $postData
     * @param type $url
     * @param type $options
     * @return type
     */
    function curlPost($postData = '',$url = '', $options = array())
    {
        if (is_array($postData)) {
            $postData = http_build_query($postData);
        }
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL允许执行的最长秒数
        if (!empty($options)) {
            curl_setopt_array($ch, $options);
        }
        //https请求 不验证证书和host
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }
    function dump($var, $echo = true, $label = null, $strict = true) {
        $label = ($label === null) ? '' : rtrim($label) . ' ';
        if (!$strict) {
            if (ini_get('html_errors')) {
                $output = print_r($var, true);
                $output = '<pre>' . $label . htmlspecialchars($output, ENT_QUOTES) . '</pre>';
            } else {
                $output = $label . print_r($var, true);
            }
        } else {
            ob_start();
            var_dump($var);
            $output = ob_get_clean();
            if (!extension_loaded('xdebug')) {
                $output = preg_replace('/\]\=\>\n(\s+)/m', '] => ', $output);
                $output = '<pre>' . $label . htmlspecialchars($output, ENT_QUOTES) . '</pre>';
            }
        }
        if ($echo) {
            echo($output);
            return null;
        } else
            return $output;
    }
    function show_err($str){
        exit(json_encode(array('staus'=>0,'infotxt'=>$str,'icon'=>'error','time'=>2)));
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值