php 银联支付(快捷支付)

7 篇文章 1 订阅

 

杉德全支付平台

注意:

需要的资料:

1.商户公钥  获取方式:先安装证书(注意:证书在收到邮件后14天内下载,并且只能下载一次),然后用IE打开https://cs.cfca.com.cn/cgi-bin/userCertDownload/v_input.do?displayAgreement=true 点击“工具—Internet选项”,查看证书,注意查看证书中的商户号是否与邮箱中发送的商户号一致,然后导出公钥

2.商户私钥 跟上边公钥导出方式一样

3.私钥证书密码 此密码是公钥导出时设置的密码

开始步骤

1.根据收到的开通邮件,找到登陆CFCA官网数字证书下载平台https://cs.cfca.com.cn/cgi-bin/userCertDownload/v_input.do?displayAgreement=true,使用本邮件提供的证书序列号和授权码,下载加密证书安装,然后再按流程导出商户公钥(后缀为 .cer)和商户私钥(文件后缀为.pfx)文件 公钥私钥导出手册:https://open.sandpay.com.cn/developmentAccess/guide?msg=6684

2.使用邮箱中的商户号去开放平台注册账号,然后在开放平台-参数设置中上传该公钥,完成编辑后请刷新页面查看审核状态。状态显示为“已审核”后1小时左右生效,请耐心等待。(需要注册并登录,注册时使用开户邮件中的商户号注册)

3.找到开发文档 https://open.sandpay.com.cn//developmentAccess/moredoc?openpage=demo 接口文档中提供有demo 然后下载对应的demo 文件

4.将之前的  公钥,私钥,私钥密码,商户号配置好,将下载好的公钥,私钥文件放到项目cert文件下,然后配置好,获取私钥路径

<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/11/15
 * Time: 15:21
 */

namespace app\v1\controller;
use app\common\controller\Checking;
use app\common\controller\Factory;
use merchants\Configs;
use merchants\WithdrawBank;
use think\Controller;
use think\Db;
use think\Exception;

class UnionPay extends Controller
{
    protected $mid='';//商户号  100211701160001
    protected $notifyUrl='';//异步回调地址
    protected $frontUrl='http://api.yfr2018.com/v1/notify/check_bank?order_id=';//同步回调地址
    public function webPay(){
        $out_trade_no = $_GET['orderId'];	//商户网站唯一订单号
        $orders=$this->query($out_trade_no);
        if ($orders['head']['respCode']=='000000'){
            if ($orders['body']['orderStatus']!='00'){
                #订单支付失败修改订单号
                $orderModel = Factory::createModel( 'orders' );
                $out_trade_no=Checking::ordeSnByUnique( 'pay_order_num', $orderModel );
                Db::name('orders')->where(['pay_order_num'=>$_GET['orderId']])->update(['pay_order_num'=>$out_trade_no,'last_order_num'=>$_GET['orderId']]);
            }
        }
        $order=Db::name('orders')->where(['pay_order_num'=>$out_trade_no])->find();
        $money=$order['real_price']*100;
        $data = array(
            'head' => array(
                'version' => '1.0',
                'method' => 'sandPay.fastPay.quickPay.index',
                'productId' => '00000016',
                'accessType' => '1',
                'mid' => $this->mid,
                'channelType' => '07',
                'reqTime' => date('YmdHis', time())
            ),
            'body' => array(
                'userId' => $order['user_id'],
                'orderCode' => $order['pay_order_num'],//商户订单号
                'orderTime' => date('YmdHis',strtotime($order['create_time'])+86400),
                'totalAmount' => str_pad($money,'12',0,STR_PAD_LEFT),
                'subject' => '悦芙蓉',//订单标题
                'body' =>'悦芙蓉',//订单描述
                'currencyCode' => '156',//币种
                'notifyUrl' => $this->notifyUrl,
                'frontUrl' => $this->frontUrl.$out_trade_no,
                'clearCycle' => '0',
                'extend' => ''
            )
        );
        // step2: 私钥签名
        $prikey = loadPk12Cert(PRI_KEY_PATH, CERT_PWD);
        $sign = sign($data, $prikey);
        // step3: 拼接post数据
        $post = array(
            'charset' => 'utf-8',
            'signType' => '01',
            'data' => json_encode($data),
            'sign' => urlencode($sign)
        );
        // step4: post请求
        $url = 'https://cashier.sandpay.com.cn/fastPay/quickPay/index';
        $html_form = createAutoFormHtml( $post, $url );
        return $html_form;
    }

    /**
     * 订单查询
     */
    public function query($order_id){
        $data = array(
            'head' => array(
                'version' => '1.0',
                'method' => 'sandpay.trade.query',
                'productId' => '00000016',
                'accessType' => '1',
                'mid' => $this->mid,
                'channelType' => '07',
                'reqTime' => date('YmdHis', time())
            ),
            'body' => array(
                'orderCode' => $order_id,//商户订单号
                'extend' => ''
            )
        );
        // step2: 私钥签名
        $prikey = loadPk12Cert(PRI_KEY_PATH, CERT_PWD);
        $sign = sign($data, $prikey);
        // step3: 拼接post数据
        $post = array(
            'charset' => 'utf-8',
            'signType' => '01',
            'data' => json_encode($data),
            'sign' => urlencode($sign)
        );
        // step4: post请求
        $result = http_post_json('https://cashier.sandpay.com.cn/gateway/api/order/query', $post);
        $arr = parse_result($result);
        //step5: 公钥验签
//        $pubkey = loadX509Cert(PUB_KEY_PATH);
//        try {
//            verify($arr['data'], $arr['sign'], $pubkey);
//        } catch (Exception $e) {
//            echo $e->getMessage();
//            exit;
//        }
        // step6: 获取credential
        $data = json_decode($arr['data'], true);
//        if ($data['orderStatus']){
//
//        }
       return $data;
    }

    /**
     * 实时代收
     */
    public function agentpay(){
        dump(11);
        $getConfig=Config::getConfig();
        halt($getConfig);
        $config=Config::Config();
        $info=$getConfig['agentpay'];
        // step1: 拼接报文及配置
        $transCode = $info['transCode']; // 交易码
        $accessType = '0'; // 接入类型 0-商户接入,默认;1-平台接入
        $merId = $info['merId']; // 此处更换商户号
        $path = $info['url']; // 服务地址
        $pt = $info['pt']; // 报文

        // step2: 生成AESKey并使用公钥加密
        $with=new WithdrawBank();
        $AESKey = aes_generate(16);
        $encryptKey = $with->RSAEncryptByPub($AESKey, $config['pubKey']);
        // step3: 使用AESKey加密报文
        $encryptData = $with->AESEncrypt($pt, $AESKey);
        // step4: 使用私钥签名报文
        $sign = $with->sign($pt, $config['priKey']);
        // step5: 拼接post数据
        $post = array(
            'transCode' => $transCode,
            'accessType' => $accessType,
            'merId' => $merId,
            'encryptKey' => $encryptKey,
            'encryptData' => $encryptData,
            'sign' => $sign
        );

        // step6: post请求
        $result = $with->http_post_json(API_HOST . $path, $post);
        parse_str($result, $arr);

        try {
            // step7: 使用私钥解密AESKey
            $decryptAESKey = $with->RSADecryptByPri($arr['encryptKey'], $config['priKey']);

            // step8: 使用解密后的AESKey解密报文
            $decryptPlainText =$with->AESDecrypt($arr['encryptData'], $decryptAESKey);

            // step9: 使用公钥验签报文
            $with->verify($decryptPlainText, $arr['sign'], $config['pubKey']);
        } catch (Exception $e) {
            echo $e->getMessage();
            exit;
        }

        print_r($decryptPlainText);
    }

}

下边是用到的方法,代码没有整理 

function createAutoFormHtml($params, $reqUrl) {
    $encodeType = isset ( $params ['encoding'] ) ? $params ['encoding'] : 'UTF-8';
    $html = <<<eot
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset={$encodeType}" />
</head>
<body onload="javascript:document.sandpay.submit();">
    <form id="sandpay" name="sandpay" action="{$reqUrl}" method="post">

eot;
    foreach ( $params as $key => $value ) {
        $html .= " <textarea name=\"{$key}\" hidden='hidden'  id=\"{$key}\">{$value}</textarea>\n";
    }
    $html .= <<<eot
    </form>
</body>
</html>
eot;
    return $html;
}

/**
 * 获取私钥
 * @param $path
 * @param $pwd
 * @return mixed
 * @throws Exception
 */
function loadPk12Cert($path, $pwd)
{
    try {
        $file = file_get_contents($path);
        if (!$file) {
            throw new \Exception('loadPk12Cert::file
					_get_contents');
        }

        if (!openssl_pkcs12_read($file, $cert, $pwd)) {
            throw new \Exception('loadPk12Cert::openssl_pkcs12_read ERROR');
        }
        return $cert['pkey'];
    } catch (\Exception $e) {
        throw $e;
    }
}

/**
 * 获取公钥
 * @param $path
 * @return mixed
 * @throws Exception
 */
function loadX509Cert($path)
{
    try {
        $file = file_get_contents($path);
        if (!$file) {
            throw new \Exception('loadx509Cert::file_get_contents ERROR');
        }

        $cert = chunk_split(base64_encode($file), 64, "\n");
        $cert = "-----BEGIN CERTIFICATE-----\n" . $cert . "-----END CERTIFICATE-----\n";

        $res = openssl_pkey_get_public($cert);
        $detail = openssl_pkey_get_details($res);
        openssl_free_key($res);
        if (!$detail) {
            throw new \Exception('loadX509Cert::openssl_pkey_get_details ERROR');
        }
        return $detail['key'];
    } catch (\Exception $e) {
        throw $e;
    }
}

/**
 * 私钥签名
 * @param $plainText
 * @param $path
 * @return string
 * @throws Exception
 */
function sign($plainText, $path)
{
    $plainText = json_encode($plainText);
    try {
        $resource = openssl_pkey_get_private($path);
        $result = openssl_sign($plainText, $sign, $resource);
        openssl_free_key($resource);

        if (!$result) {
            throw new \Exception('签名出错' . $plainText);
        }

        return base64_encode($sign);
    } catch (\Exception $e) {
        throw $e;
    }
}

/**
 * 公钥验签
 * @param $plainText
 * @param $sign
 * @param $path
 * @return int
 * @throws Exception
 */
function verify($plainText, $sign, $path)
{
    $resource = openssl_pkey_get_public($path);
    $result = openssl_verify($plainText, base64_decode($sign), $resource);
    openssl_free_key($resource);

    if (!$result) {
        throw new \Exception('签名验证未通过,plainText:' . $plainText . '。sign:' . $sign, '02002');
    }

    return $result;
}

/**
 * 发送请求
 * @param $url
 * @param $param
 * @return bool|mixed
 * @throws Exception
 */
function http_post_json($url, $param)
{
    if (empty($url) || empty($param)) {
        return false;
    }
    $param = http_build_query($param);
    try {

        $ch = curl_init();//初始化curl
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $param);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        //正式环境时解开注释
//        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
//        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $data = curl_exec($ch);//运行curl
        curl_close($ch);
//        halt($data);
        if (!$data) {
            throw new \Exception('请求出错');
        }

        return $data;
    } catch (\Exception $e) {
        throw $e;
    }
}

function parse_result($result)
{
    $arr = array();
    $response = urldecode($result);
    $arrStr = explode('&', $response);
    foreach ($arrStr as $str) {
        $p = strpos($str, "=");
        $key = substr($str, 0, $p);
        $value = substr($str, $p + 1);
        $arr[$key] = $value;
    }

    return $arr;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦夏夜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值