• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

连连支付PHP第三方连连支付对接

武飞扬头像
蹦跶哒的王小哲
帮助1

前言:

前不久刚搞定了易宝支付,运营说,不用易宝支付了,改用连连支付。🆗🆗🆗 连连支付搞起~

学新通

对接过程:

一 在商户后台,下载连连提供的密钥生成工具。

获取公私密钥后,在商户后台配置公钥。

 学新通

注意:按着里面的使用说明文档进行操作生成。我最开始使用秘钥生成批处理生成秘钥,即使用上图中的 私钥生成双击开始  来生成的密钥,结果一直对接不成功。之后用了公私钥校验工具,发现公私钥不匹配,然后按照 RSA秘钥生成工具使用说明 里面的步骤 生成的公私钥。

二 下载连连支付php-SDK,根据连连接口对接文档进行开发。

可以根据连连支付提供的SDK文件自行开发,也可以下载我个人整理的SDK文件,其中包含有官方提供的SDK,以及我个人对SDK的修改和调整之后使用的SDK文件,还有私钥生成工具。

  1.  
    // 商户在充值/消费交易模式场景下使用,通过该接口完成收银台创单,然后跳转至连连收银台完成支付。
  2.  
    function test_tradeCreate()
  3.  
    {
  4.  
    $user_id = "LLianPayTest-In-User-12345";
  5.  
    $current = date("YmdHis");
  6.  
    $params = new TradeCreateParams();
  7.  
    $current = date("YmdHis");
  8.  
    $params->timestamp = $current;
  9.  
    $params->oid_partner = "商户号";
  10.  
    $params->txn_type = 'GENERAL_CONSUME';
  11.  
    $params->user_id = $user_id;
  12.  
    $params->user_type = 'ANONYMOUS';
  13.  
    $params->notify_url = '回调地址';
  14.  
    $params->return_url = '完成支付后跳转地址';
  15.  
    $params->pay_expire = '120'; // 订单失效时间
  16.  
    $params->flag_chnl = 'H5'; // 交易发起渠道
  17.  
    $params->risk_item = json_encode(array(
  18.  
    'frms_ware_category' => '4007',
  19.  
    'user_info_mercht_userno' => 'LLianPayTest-In-User-12345',
  20.  
    'user_info_bind_phone' => '手机号',
  21.  
    'user_info_dt_register' => '注册时间',
  22.  
    'goods_name' => '数藏',
  23.  
    'user_info_full_name' => '姓名',
  24.  
    'user_info_id_type' => 0,
  25.  
    'user_info_id_no' => '身份证号',
  26.  
    'user_info_identify_state' => 1,
  27.  
    'user_info_identify_type' => 3,
  28.  
    'frms_client_chnl' => 'H5',
  29.  
    'frms_ip_addr' => "IP地址",
  30.  
    'user_auth_flag' => 1,
  31.  
    )); // 风险控制参数(不同类别,风控参数不同,请自行调整)
  32.  
     
  33.  
     
  34.  
    $orderInfo = new TradeCreateOrderInfo();
  35.  
    $orderInfo->txn_seqno = 'LLianPayTest' . $current;
  36.  
    $orderInfo->txn_time = $current;
  37.  
    $orderInfo->total_amount = '0.01';
  38.  
    $orderInfo->goods_name = "shuzicangping";
  39.  
    $orderInfo->order_info = '订单信息';
  40.  
    $params->orderInfo = $orderInfo;
  41.  
     
  42.  
    // 收款方信息
  43.  
    $m_payeeInfo = new TradeCreatePayeeInfo();
  44.  
    $m_payeeInfo->payee_id = "商户号";
  45.  
    $m_payeeInfo->payee_type = 'MERCHANT';
  46.  
    $m_payeeInfo->payee_amount = '0.01';
  47.  
    $params->payeeInfo = array($m_payeeInfo);
  48.  
    // 付款方信息
  49.  
    $payerInfo['payer_type'] = "USER";
  50.  
    $payerInfo['payer_id'] = "LLianPayTest-In-User-12345";
  51.  
    $params->payerInfo = $payerInfo;
  52.  
    // 测试环境地址
  53.  
    $url = 'https://accpgw-ste.lianlianpay-inc.com/v1/cashier/paycreate';
  54.  
    $result = LLianPayClient::sendRequest($url, json_encode($params));
  55.  
     
  56.  
    echo $result;
  57.  
    }
  58.  
     
  59.  
    test_tradeCreate();
学新通
  1.  
    class LLianPayClient
  2.  
    {
  3.  
    static public function sendRequest($url, $content)
  4.  
    {
  5.  
    if (empty($url)) {
  6.  
    log_write("[发送请求中]:请求URL非法,请核实!"."\n",'error');
  7.  
    }
  8.  
    if (empty($content)) {
  9.  
    log_write("[发送请求中]:请求参数非法,请核实!"."\n",'error');
  10.  
    }
  11.  
    // 签名
  12.  
    $signVar = LLianPayAccpSignature::sign($content);
  13.  
     
  14.  
    log_write("请求签名值为:: " . $signVar."\n",'error');
  15.  
    log_write("请求参数为:: " . $content."\n",'error');
  16.  
    $sResult = LLianPayAccpSignature::getHttpResponseJSON($url, $content,$signVar);
  17.  
    return $sResult;
  18.  
    }
  19.  
     
  20.  
    }
学新通
  1.  
    class LLianPayAccpSignature
  2.  
    {
  3.  
    /**
  4.  
    * 对数据先进行MD5处理,后使用私钥进行RSA加签
  5.  
    * @param $data 待加签数据
  6.  
    * @return string 返回签名
  7.  
    */
  8.  
    public static function sign($data = '')
  9.  
    {
  10.  
    if (empty($data)) {
  11.  
    log_write("[加签处理中]:待加签数据为空,请核实!"."\n",'error');
  12.  
    return False;
  13.  
    }
  14.  
    $private_key = self::_get_pem_content('/keys/merchant_private_key.pem');
  15.  
    if (empty($private_key)) {
  16.  
    log_write("[加签处理中]:私钥错误,请核实!"."\n",'error');
  17.  
    return False;
  18.  
    }
  19.  
     
  20.  
    $pkeyid = openssl_get_privatekey($private_key);
  21.  
    if (empty($pkeyid)) {
  22.  
    log_write("[加签处理中]:私钥错误,请核实!"."\n",'error');
  23.  
    return False;
  24.  
    }
  25.  
     
  26.  
    // 对数据进行MD5处理
  27.  
    $md5Var = md5($data);
  28.  
     
  29.  
    // 使用数据的MD5值和私钥进行RSA加密
  30.  
    $verify = openssl_sign($md5Var, $signature, $pkeyid, OPENSSL_ALGO_MD5);
  31.  
    $result = base64_encode($signature);
  32.  
    log_write("[加签处理中],签名值为:" . $result."\n",'error');
  33.  
    return $result;
  34.  
    }
  35.  
     
  36.  
    /**
  37.  
    * 利用连连公钥和进行验签
  38.  
    * @param $data 待验证数据
  39.  
    * @param $signature 签名值
  40.  
    * @return -1:error验签异常 1:correct验证成功 0:incorrect验证失败
  41.  
    */
  42.  
    public static function checkSign($data = '', $signature = '')
  43.  
    {
  44.  
    if (empty($data) || empty($signature)) {
  45.  
    log_write("[验签处理中]:待验签数据或签名值为空,请核实!"."\n",'error');
  46.  
    return False;
  47.  
    }
  48.  
     
  49.  
    $public_key = self::_get_pem_content('/keys/llianpay_public_key.pem');
  50.  
    if (empty($public_key)) {
  51.  
    log_write("[验签处理中]:验签公钥错误,请核实!"."\n",'error');
  52.  
    return False;
  53.  
    }
  54.  
     
  55.  
    $pkeyid = openssl_get_publickey($public_key);
  56.  
    if (empty($pkeyid)) {
  57.  
    log_write("[验签处理中]:验签公钥错误,请核实!"."\n",'error');
  58.  
    return False;
  59.  
    }
  60.  
     
  61.  
    // 对数据进行MD5处理
  62.  
    $md5Var = md5($data);
  63.  
    log_write("[验签处理中]:待验签数据对应MD5值为:" . $md5Var."\n",'error');
  64.  
    // 使用数据的MD5值和签名值进行RSA校验
  65.  
    $ret = openssl_verify($md5Var, base64_decode($signature), $pkeyid, OPENSSL_ALGO_MD5);
  66.  
    switch ($ret) {
  67.  
    case 0:
  68.  
    log_write("[验签处理中]:验签完成,验签结果为:错误"."\n",'error');
  69.  
    break;
  70.  
    case 1:
  71.  
    log_write("[验签处理中]:验签完成,验签结果为:正确"."\n",'error');
  72.  
    break;
  73.  
    default:
  74.  
    log_write("[验签处理中]:验签异常!"."\n",'error');
  75.  
    break;
  76.  
    }
  77.  
    return $ret;
  78.  
    }
  79.  
    // 发送post 请求
  80.  
    public static function getHttpResponseJSON($url, $para,$Signature) {
  81.  
    // log_write($json,'error');
  82.  
    $curl = curl_init($url);
  83.  
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); //信任任何证书
  84.  
    curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");
  85.  
    curl_setopt($curl, CURLOPT_POSTFIELDS, $para);
  86.  
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
  87.  
    curl_setopt($curl, CURLOPT_HTTPHEADER, array(
  88.  
    'timestamp' => date("YmdHis"),
  89.  
    'Content-type:application/json;charset=utf-8',
  90.  
    'Signature-Type:RSA',
  91.  
    'Signature-Data:'.$Signature
  92.  
    ));
  93.  
    $responseText = curl_exec($curl);
  94.  
    log_write("返回值:".$responseText."\n",'error');
  95.  
    curl_close($curl);
  96.  
    $result = json_decode($responseText,true);
  97.  
    return $result;
  98.  
    }
  99.  
     
  100.  
    // 使用连连公钥进行数据加密(用于绑定银行卡接口参数加密)
  101.  
    public static function publicKeyEncrypt($data = '')
  102.  
    {
  103.  
    $public_key = self::_get_pem_content('/keys/llianpay_public_key.pem');
  104.  
    if (empty($public_key)) {
  105.  
    log_write("[加签处理中]:公钥错误,请核实!"."\n",'error');
  106.  
    return False;
  107.  
    }
  108.  
    openssl_public_encrypt($data,$encrypted,$public_key);
  109.  
    $encrypted = base64_encode($encrypted);
  110.  
    return $encrypted;
  111.  
    }
  112.  
     
  113.  
    private static function _get_pem_content($file_path)
  114.  
    {
  115.  
    return file_get_contents(dirname(__FILE__) . $file_path);
  116.  
    }
  117.  
    }
学新通

注意:

(1)注意调整相应参数,以及写日志方法

(2)传输参数类型为object对象;

(3)user_type   参数 要传 ANONYMOUS。学新通

之前根据SDK,里面的用户类型默认:REGISTERED:注册用户,第一次支付的时候就会有报错:接口返回 2003  用户查询失败或不存在 。

 三 回调

  1.  
    /**
  2.  
    * 支付回调
  3.  
    */
  4.  
    public function notify()
  5.  
    {
  6.  
    $data = file_get_contents("php://input");
  7.  
    $signature = \request()->header('Signature-Data');
  8.  
    // SDK 初始化文件加载
  9.  
    $llpaySubmit = new LLianPayAccpSignature();
  10.  
    $result = $llpaySubmit->checkSign($data,$signature);
  11.  
    if($result){
  12.  
    // log_write('哈哈哈哈回调成功了--------','error');
  13.  
    $data = json_decode($data,true);
  14.  
     
  15.  
    // 订单支付成功业务处理
  16.  
    $status = $model->onPaySuccess($pay_type, ['transaction_id' => $data['order_no']]);
  17.  
    // 清除未支付订单的url缓存
  18.  
    RedisLocal::delete_from_redis($data['order_no'].'llnomal_pay_url');
  19.  
    if ($status == false) {
  20.  
    log_write('连连业务处理失败:'.$model->getError(),'error');
  21.  
    }
  22.  
    }else{
  23.  
    log_write('验签名失败','error');
  24.  
    return 'error';
  25.  
    }
  26.  
    return 'Success';
  27.  
    }
学新通

 注意:

(1)发起支付调起时的回调地址一定要写对!这个至关重要!

(2)从接收到的数据的 header 中获取 Signature-Data  签名值 进行验签。学新通

 (3)如果回调不成功,可以通过写日志形式进行记录,便于查找出错点。

注意事项:

一 签约项目类型

要搞清楚与连连的签约类型,不同的签约项目有不同的请求接口,以及支付对接文档;

我上面对接的支付类型是 银行卡快捷支付。

二 参数类型

传参类型为object对象,而不是array数组!!!

这个真的是很坑很坑,因为目前项目中有连连支付的sdk,前期偷懒想着改改就可以了,谁知一直验签不成功,后来才发现,系统中的请求参数是数组类型的,就是因为这个原因一直不成功~无语至极@--@

三 如果使用连连支付的支付页面,要考虑储存调起支付后返回的网关地址

问题:使用连连支付,支付取消,返回订单列表,再次选择支付-连连支付,则提示“流水号重复,请勿重复提交。”

原因:请求连连支付后,此笔订单已生成相应的流水号,当返回再次选择连连支付,该订单已创建有流水账号,因此会有错误提示。

解决方案:订单状态为:未支付,点击去支付-连连支付。

(1)拿到请求连连接口返回的网关地址,先将网关地址记录到redis缓存中,并设置缓存失效时间;

(2)支付成功、关闭/取消订单操作中清除该地址缓存;

(3)在订单列表,判断如果订单状态为:未支付&&支付方式为:连连支付,则在该笔订单返回字段中增加  网关地址  字段;

(4)前端判断 未支付&&连连支付&&网关地址 则直接使用返回的  网关地址 字段,即可再次调起支付。

总结

学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgaejge
系列文章
更多 icon
同类精品
更多 icon
继续加载