wupengfei 2 éve
szülő
commit
e00d9319b5

+ 14 - 4
application/api/controller/Recharge.php

@@ -6,7 +6,7 @@ use app\common\library\ShandeRapid;
 use app\common\library\Moyun;
 use think\Db;
 use think\Exception;
-
+use app\common\library\LianLianPay;
 /**
  * @title 余额充值
  * @controller Recharge
@@ -27,8 +27,8 @@ class Recharge extends Base
      * @method POST
      * @header name:Authorization require:1 desc:Token
      * @param name:money type:int require:1 default:1 desc:充值金额
-     * @param name:pay_type type:int require:1 default:sd_rapid desc:sd:杉德h5,sd_rapid:杉德快捷支付,moyun:墨云[支付宝]
-     * @param name:from type:int require:1 default1 desc:1 h5,2:app
+     * @param name:pay_type type:int require:1 default:sd_rapid desc:sd:杉德h5,sd_rapid:杉德快捷支付,moyun:墨云[支付宝],ll:连连支付
+     * @param name:from type:int require:1 default1 desc:1:h5,2:app[Android],3:app[ios]
      * @return name:order_no type:string default:0 desc:支付单号
      * @return name:id type:int default:0 desc:支付订单id
      * @return name:extend type:int default:0 desc:用户id
@@ -59,7 +59,8 @@ class Recharge extends Base
                     'order_no' =>get_order_sn(),
                     'pay_no' =>get_order_sn(),
                     'create_at' => date("Y-m-d H:i:s"),
-                    'pay_type' => $pay_type
+                    'pay_type' => $pay_type,
+                    'ext' => json_encode(['name'=>$user['true_name'],'phone'=>$user['phone'],'id_card'=>$user['id_card']])
                 ];
                 $order_id = Db::table('store_recharge_order')->insertGetId($voucher_order);
                 $notify_url = 'https://'.$_SERVER['HTTP_HOST'] . '/api/Pay/walletNotify';
@@ -97,6 +98,15 @@ class Recharge extends Base
                         if(!isset($res['data']) || !$res['data']) throw new Exception($res['msg']);
                         $retrun_data = $res['data'];
                         break;
+                    case 'll':
+                        $notify_url = 'https://'.$_SERVER['HTTP_HOST'] . '/api/Pay/lianLianNotify';
+                        $return_url ='https://'.$_SERVER['HTTP_HOST']."/h5/pages/mine/mine?id={$order_id}&orderNo={$voucher_order['order_no']}";//回调地址
+                        $risk_item= risk_item($user,'余额充值',$from == 1 ? 16 : 10);
+                        $obj = new LianLianPay();
+                        $res= $obj->cashierDesk($voucher_order['order_no'],$money,$this->uid,$notify_url,$return_url,'余额充值',$risk_item);
+                        $retrun_data = $res['pay_result'];
+                        $retrun_data['request_params'] = $res['request_params'];
+                        break;
                 }
                 Db::commit();
             }catch (\Exception $e){

+ 180 - 0
application/common/library/LianLianPay.php

@@ -0,0 +1,180 @@
+<?php
+namespace app\common\library;
+use llianpay\accp\client\LLianPayClient;
+use llianpay\accp\params\TradeCreateParams;
+use llianpay\accp\params\TradeCreateOrderInfo;
+use llianpay\accp\params\TradeCreatePayeeInfo;
+use llianpay\accp\params\GetRandomParams;
+use llianpay\accp\params\TradeCreatePayerInfo;
+
+date_default_timezone_set('Asia/Shanghai');
+header('Content-type:application/json;charset=utf-8');
+//require env('root_path').'application/vendor/autoload.php';
+$path = __DIR__ . \DIRECTORY_SEPARATOR . '..' . \DIRECTORY_SEPARATOR . 'vendor' . \DIRECTORY_SEPARATOR . 'autoload.php';
+require env('root_path').'application/common/library/llp/src/cfg.php';
+require env('root_path').'application/common/library/llp/src/client/LLianPayClient.php';
+require env('root_path').'application/common/library/llp/src/params/TradeCreateParams.php';
+require env('root_path').'application/common/library/llp/src/params/TradeCreateOrderInfo.php';
+require env('root_path').'application/common/library/llp/src/params/TradeCreatePayeeInfo.php';
+require env('root_path').'application/common/library/llp/src/params/TradeCreatePayerInfo.php';
+require env('root_path').'application/common/library/llp/src/params/GetRandomParams.php';
+class LianLianPay
+{
+
+   // 测试“统一支付创单”接口https://open.lianlianpay.com/docs/accp/accpstandard/accp-tradecreate.html
+    function tradeCreate($order_no,$money,$user_id,$notify_url,$return_url)
+    {
+        // 构建请求参数
+        $params = new TradeCreateParams();
+        $current = date("YmdHis");
+        $params->timestamp = $current;
+        $params->oid_partner = OID_PARTNER;
+        $params->txn_type = 'GENERAL_CONSUME';
+        $params->user_id = $user_id;//LLianPayTest-En-User-12345;
+        $params->notify_url = $notify_url;//'https://test.lianlianpay.com/notify';
+        $params->return_url = $return_url;//'https://test.lianlianpay.com/return';
+        //商户订单信息orderInfo
+        $orderInfo = new TradeCreateOrderInfo();
+        $orderInfo->txn_seqno = $order_no; //'LLianPayTest' . $current;
+        $orderInfo->txn_time = $current;
+        $orderInfo->total_amount = $money;//2.00;
+        $params->orderInfo = $orderInfo;
+
+        //收款方信息payeeInfo
+       /* $u_payeeInfo = new TradeCreatePayeeInfo();
+        $u_payeeInfo->payee_id = $user_id;//'LLianPayTest-En-User-12345';
+        $u_payeeInfo->payee_type = 'USER';
+        $u_payeeInfo->payee_amount = $money;//'1.00';*/
+
+        $m_payeeInfo = new TradeCreatePayeeInfo();
+        $m_payeeInfo->payee_id = OID_PARTNER;
+        $m_payeeInfo->payee_type = 'MERCHANT';
+        $m_payeeInfo->payee_amount = $money; //'1.00';
+
+       // $params->payeeInfo = array($u_payeeInfo, $m_payeeInfo);
+        $params->payeeInfo = array($m_payeeInfo);
+        // 测试环境地址
+        $url = 'https://accpapi-ste.lianlianpay-inc.com/v1/txn/tradecreate';
+       // var_dump(json_encode($params));
+        $result = LLianPayClient::sendRequest($url, json_encode($params));
+        return json_decode($result,true);
+    }
+
+    function getRandom()
+    {
+        // 构建请求参数
+        $params = new GetRandomParams();
+        $params->timestamp = date("YmdHis");
+        $params->oid_partner = OID_PARTNER;
+        $params->user_id = 'LLianPayTest-In-User-12345';
+        $params->flag_chnl = 'H5';
+        $params->pkg_name = 'test';
+        $params->app_name = 'test';
+        // 测试环境地址
+        $url = 'https://accpapi-ste.lianlianpay-inc.com/v1/acctmgr/get-random';
+        $result = LLianPayClient::sendRequest($url, json_encode($params));
+        return json_decode($result,true);
+    }
+
+    // 账户+收银台 (商户在充值/消费交易模式场景下使用,可通过该接口完成收银台创单,然后跳转至连连收银台完成支付。)
+    function cashierDesk($order_no,$money,$user_id,$notify_url,$return_url,$goods_name,$risk_item)
+    {
+        // 构建请求参数
+        $params = new TradeCreateParams();
+        $current = date("YmdHis");
+        $params->timestamp = $current;
+        $params->oid_partner = OID_PARTNER;
+        $params->txn_type = 'GENERAL_CONSUME';
+        $params->user_id = $user_id;//LLianPayTest-En-User-12345;
+        $params->user_type = 'ANONYMOUS';
+        $params->notify_url = $notify_url;//'https://test.lianlianpay.com/notify';
+        $params->return_url = $return_url;//'https://test.lianlianpay.com/return';
+        $params->flag_chnl = 'H5';
+        $params->risk_item = is_array( $risk_item ) ? json_encode($risk_item) : $risk_item;
+
+        //商户订单信息orderInfo
+        $orderInfo = new TradeCreateOrderInfo();
+        $orderInfo->txn_seqno = $order_no; //'LLianPayTest' . $current;
+        $orderInfo->txn_time = $current;
+        $orderInfo->total_amount = $money;//2.00;
+        $orderInfo->goods_name = $goods_name;//2.00;
+        $params->orderInfo = $orderInfo;
+
+        //收款方信息payeeInfo
+         $u_payeeInfo = new TradeCreatePayeeInfo();
+         $u_payeeInfo->payee_id = OID_PARTNER;//'LLianPayTest-En-User-12345';
+         $u_payeeInfo->payee_type = 'MERCHANT';
+         $u_payeeInfo->payee_amount = $money;//'1.00';
+         $params->payeeInfo = [$u_payeeInfo];
+
+         // 付款方信息payerInfo
+         $m_payeeInfo = new TradeCreatePayerInfo();
+         $m_payeeInfo->payer_type = 'USER';
+         $m_payeeInfo->payer_id = $user_id; //'1.00';
+         $params->payerInfo =$m_payeeInfo;
+
+
+         //$url = 'https://accpgw-ste.lianlianpay-inc.com/v1/cashier/paycreate';// 测试环境
+         $url = 'https://accpgw.lianlianpay.com/v1/cashier/paycreate';// 生成环境
+        // var_dump(json_encode($params));
+         $result = LLianPayClient::sendRequest($url, json_encode($params));
+         return ['pay_result'=> json_decode($result,true),'request_params'=>json_encode($params)];
+    }
+
+    public static function getSignData($order_no,$money,$user_id,$notify_url,$return_url,$goods_name,$risk_item)
+    {
+        // 构建请求参数
+        $params = new TradeCreateParams();
+        $current = date("YmdHis");
+        $params->timestamp = $current;
+        $params->oid_partner = OID_PARTNER;
+        $params->txn_type = 'GENERAL_CONSUME';
+        $params->user_id = $user_id;//LLianPayTest-En-User-12345;
+        $params->user_type = 'ANONYMOUS';
+        $params->notify_url = $notify_url;//'https://test.lianlianpay.com/notify';
+        $params->return_url = $return_url;//'https://test.lianlianpay.com/return';
+        $params->flag_chnl = 'H5';
+        $params->risk_item = is_array( $risk_item ) ? json_encode($risk_item) : $risk_item;
+
+        //商户订单信息orderInfo
+        $orderInfo = new TradeCreateOrderInfo();
+        $orderInfo->txn_seqno = $order_no; //'LLianPayTest' . $current;
+        $orderInfo->txn_time = $current;
+        $orderInfo->total_amount = $money;//2.00;
+        $orderInfo->goods_name = $goods_name;//2.00;
+        $params->orderInfo = $orderInfo;
+
+        //收款方信息payeeInfo
+        $u_payeeInfo = new TradeCreatePayeeInfo();
+        $u_payeeInfo->payee_id = OID_PARTNER;//'LLianPayTest-En-User-12345';
+        $u_payeeInfo->payee_type = 'MERCHANT';
+        $u_payeeInfo->payee_amount = $money;//'1.00';
+        $params->payeeInfo = [$u_payeeInfo];
+
+        // 付款方信息payerInfo
+        $m_payeeInfo = new TradeCreatePayerInfo();
+        $m_payeeInfo->payer_type = 'USER';
+        $m_payeeInfo->payer_id = $user_id; //'1.00';
+        $params->payerInfo =$m_payeeInfo;
+        return  json_encode($params);
+    }
+
+
+    public static function payResult($order_no,$timestamp)
+    {
+        $params = [
+            'timestamp'=>$timestamp,
+            'oid_partner'=>OID_PARTNER,
+            'accp_txno'=>$order_no,
+        ];
+        $url = 'https://accpapi.lianlianpay.com/v1/txn/query-payment';//生产环境
+        //$url = 'https://accpapi-ste.lianlianpay-inc.com/v1/txn/query-payment';//测试环境
+        $result = LLianPayClient::sendRequest($url, json_encode($params));
+        return json_decode($result,true);
+    }
+
+
+
+
+
+}

+ 0 - 0
application/common/library/llp/.gitignore


+ 23 - 0
application/common/library/llp/README.md

@@ -0,0 +1,23 @@
+# LLP-ACCP-PHP
+
+欢迎来到连连账户+开放平台API接口的PHP示例代码仓库, 本仓库包含示例代码及必要的说明。
+
+## 主要内容:
+
+本仓库中所有Demo均请求连连账户+STE环境,Demo仅做参考,建议只参考签名方法,请仔细阅读Demo代码,如有问题及时群内连连技术技术。
+
+### 前置要求:
+当前使用的php-7.4.30
+
+### 使用说明
+1、keys/llianpay_public_key.pem为连连的公钥,测试环境和正式环境均为这个,不用替换。<br/>
+2、keys/merchant_private_key.pem为测试商户号的私钥,如使用贵司正式商户号,此私钥要替换成商户正式的私钥。<br/>
+3、keys/merchant_public_key.pem为测试商户号的公钥,如使用贵司正式商户号,此公钥要替换成商户正式的公钥。<br/>
+4、src/security/LLianPayAccpSignature.php 包含签名、验签。<br/>
+5、src/client/LLianPayClient.php 包含发起请求方法。<br/>
+
+### Demo说明(持续完善中)
+#### 充值/消费API:
+* 统一支付创单:TradeCreateDemo.php https://open.lianlianpay.com/docs/accp/accpstandard/accp-tradecreate.html
+#### 公共API:
+* 随机因子获取:GetRandomDemo.php https://open.lianlianpay.com/docs/accp/accpstandard/get-random.html

+ 31 - 0
application/common/library/llp/composer.json

@@ -0,0 +1,31 @@
+{
+  "name": "llianpay-accp/api-demo",
+  "type": "project",
+  "autoload": {
+    "psr-4": {
+      "llianpay\\accp\\": "src/"
+    }
+  },
+  "authors": [
+    {
+      "name": "llianpay_tech_support",
+      "email": "tech_support@lianlianpay.com"
+    }
+  ],
+  "require": {
+    "guzzlehttp/guzzle": "^7.4",
+    "ext-json": "*",
+    "ext-ctype": "*",
+    "ext-openssl": "*",
+    "monolog/monolog": "^2.3"
+  },
+  "repositories": {
+    "packagist": {
+      "type": "composer",
+      "url": "https://mirrors.aliyun.com/composer/"
+    }
+  },
+  "require-dev": {
+    "phpunit/phpunit": "8.5.*"
+  }
+}

+ 5 - 0
application/common/library/llp/keys/llianpay_public_key.pem

@@ -0,0 +1,5 @@
+-----BEGIN PUBLIC KEY-----
+MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCSS/DiwdCf/aZsxxcacDnooGph3d2JOj5GXWi+
+q3gznZauZjkNP8SKl3J2liP0O6rU/Y/29+IUe+GTMhMOFJuZm1htAtKiu5ekW0GlBMWxf4FPkYlQ
+kPE0FtaoMP3gYfh+OwI+fIRrpW3ySn3mScnc6Z700nU/VYrRkfcSCbSnRwIDAQAB
+-----END PUBLIC KEY-----

+ 51 - 0
application/common/library/llp/keys/merchant_private_key.pem

@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+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
+-----END RSA PRIVATE KEY-----

+ 14 - 0
application/common/library/llp/keys/merchant_public_key.pem

@@ -0,0 +1,14 @@
+-----BEGIN PUBLIC KEY-----
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1vNue0Pephyd+uC95pzh
+/XkOKzCv1RVJ2vQTau1Fl74XdNIqXoTlU2O+IEi+RwP5Mz1dX7jkf7wmc+kBLnox
+o8NTQQXCZGT8hmMDQaHDjvx7qWm8VageDPZXJilQNHwdTKG8DjpCYXCqHlsvnJLE
+SeEdAprFW45sQ4Pq3mofk/EoazAUl0FOcbK5mSi0yBEpB54Ac/qUAMeXFZlK1tR/
+aqNWkWjTQ9oPSMplIE8Vdg3APmYGFjOH3lgyQSrEjSEq5QduUo5o/j4/fyyAANyn
+cq7nB5kJH1lPGdNSMEMV6TJ2kej+vKkz1R+4YU2qJ2Ej0huFcjvjyXqDNSHwpk7h
+50alTeKc7+Yh5LU4FZs5PfNyfp9e9gQdAqjiFsHhdTHrnyEyuHiRgM1KBzDDB7by
+S7AXsja9uC2MwzQr1Ew2lMeWAmtb1aCTU6+TCo2yvBYgNjorTpyALPkwMWCfSZA+
+5lQ03dPsTjjsGwNflckmMlv17PY4jFJ8JLQgLcL5+McahtKg8efwyo0s34ZSAURB
+VtQ50lDKbmHfmz7sRDQP0ACnie95K14ezxJ9HubYL8otcC4dsIbqhW9Tp47PAoXG
+9FNxbR3nK2avpLlm1FYkT7SR9eB8fKVeKXmRHBSmY8rp1MrMB77RpFT9OMehysVQ
+GnH5sizGK5d2NPsuStB7uH0CAwEAAQ==
+-----END PUBLIC KEY-----

+ 35 - 0
application/common/library/llp/src/cfg.php

@@ -0,0 +1,35 @@
+<?php
+
+use Monolog\Formatter\LineFormatter;
+use Monolog\Handler\StreamHandler;
+use Monolog\Logger;
+
+// 商户私钥
+const merchant_private_key_path = '/keys/merchant_private_key.pem';
+// 商户公钥
+const merchant_public_key_path = '/keys/merchant_public_key.pem';
+// 连连公钥
+const llianpay_public_key_path = '/keys/llianpay_public_key.pem';
+// 商户id
+const OID_PARTNER = '2022092008372557';
+// 签名类型
+const sign_type = 'RSA';
+
+define("ROOT_PATH", dirname(__DIR__) . "/");
+
+function Logger(): Logger
+{
+    // 自定义时间格式
+    $dateFormat = "Y-m-d H:i:s";
+    // 自定义日志内容格式
+    //$output = "%datetime% > %level_name% > %channel% > %message% > %context% > %extra% \n ";
+    $output = "[%datetime%] %channel%.%level_name%: %message% %context%\n";
+    $line_formatter = new LineFormatter($output, $dateFormat);
+
+    $log_stream_handler = new StreamHandler(ROOT_PATH . 'logs/app.log', Logger::DEBUG);
+    $log_stream_handler->setFormatter($line_formatter);
+
+    $log = new Logger("app");
+    $log->pushHandler($log_stream_handler);
+    return $log;
+}

+ 60 - 0
application/common/library/llp/src/client/LLianPayClient.php

@@ -0,0 +1,60 @@
+<?php
+
+namespace llianpay\accp\client;
+
+use GuzzleHttp\Client;
+use llianpay\accp\security\LLianPayAccpSignature;
+use Psr\Http\Message\StreamInterface;
+//use llianpay\accp\security\LLianPayAccpSignature;
+require env('root_path').'application/common/library/llp/src/security/LLianPayAccpSignature.php';
+class LLianPayClient
+{
+    public static function sendRequest($url, $content): StreamInterface
+    {
+        if (empty($url)) {
+            Logger()->error("[发送请求中]:请求URL非法,请核实!");
+        }
+        if (empty($content)) {
+            Logger()->error("[发送请求中]:请求参数非法,请核实!");
+        }
+
+        //$signVar = (new LLianPayAccpSignature())::sign($content);
+        $signVar = LLianPayAccpSignature::sign($content);
+        Logger()->info("[发送请求中]:请求URL为:" . $url);
+        Logger()->info("[发送请求中]:请求参数为:: " . $content);
+        Logger()->info("[发送请求中]:请求签名值为:: " . $signVar);
+
+        $client = new Client();
+        // 拼接请求头
+        $header = [
+            'timestamp' => date("YmdHis"),
+            'Signature-Data' => $signVar,
+            'Signature-Type' => 'RSA',
+            'Content-Type' => 'application/json;charset=UTF-8',
+        ];
+        // 发送请求
+        $response = $client->post($url,
+            [
+                'body' => $content,
+                'headers' => $header,
+                'verify' => false
+            ]);
+        Logger()->info("[请求完成]:响应结果为:" . $response->getBody());
+
+        foreach ($response->getHeaders() as $name => $values) {
+            foreach ($values as $value) {
+                if ($name == 'Signature-Data') {
+                    Logger()->info("[请求完成]:响应签名为:" . $value);
+                    // 验签
+                    $isValid = LLianPayAccpSignature::checkSign($response->getBody(), $value);
+                    if ($isValid == 1) {
+                        Logger()->info("[请求完成]:验签结果为:正确");
+                    } else {
+                        Logger()->info("[请求完成]:验签结果为:错误");
+                    }
+                }
+            }
+        }
+        return $response->getBody();
+    }
+}

+ 4 - 0
application/common/library/llp/src/index.php

@@ -0,0 +1,4 @@
+<?php
+require '../vendor/autoload.php';
+
+require 'cfg.php';

+ 33 - 0
application/common/library/llp/src/params/GetRandomParams.php

@@ -0,0 +1,33 @@
+<?php
+
+namespace llianpay\accp\params;
+
+class GetRandomParams
+{
+    // 时间戳,格式yyyyMMddHHmmss HH以24小时为准,如20170309143712
+    public  $timestamp;
+    // 商户号,ACCP系统分配给平台商户的唯一编号
+    public  $oid_partner;
+    // 用户在商户系统中的唯一编号,要求该编号在商户系统能唯一标识用户
+    public  $user_id;
+    /*
+    交易发起渠道。
+    ANDROID
+    IOS
+    H5
+    PCH5
+    PC
+    */
+    public  $flag_chnl;
+    // APP包名。flag_chnl为H5时,送商户一级域名,测试环境传test
+    public  $pkg_name;
+    // APP应用名。flag_chnl为H5时,送商户一级域名,测试环境传test
+    public  $app_name;
+    /*
+    加密算法。
+    RSA:国际通用RSA算法
+    SM2 :国密算法
+    默认 RSA算法
+    */
+    public  $encrypt_algorithm;
+}

+ 16 - 0
application/common/library/llp/src/params/TradeCreateOrderInfo.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace llianpay\accp\params;
+
+// 统一支付创单---商户订单信息
+class TradeCreateOrderInfo
+{
+    public  $txn_seqno;
+    public  $txn_time;
+    public  $total_amount;
+    public  $fee_amount;
+    public  $order_info;
+    public  $goods_name;
+    public  $goods_url;
+    public  $coupon_pay_mode;
+}

+ 35 - 0
application/common/library/llp/src/params/TradeCreateParams.php

@@ -0,0 +1,35 @@
+<?php
+
+namespace llianpay\accp\params;
+
+class TradeCreateParams
+{
+    // 时间戳,格式yyyyMMddHHmmss HH以24小时为准,如20170309143712
+    public  $timestamp;
+    // 商户号,ACCP系统分配给平台商户的唯一编号
+    public  $oid_partner;
+    /*
+    交易类型。
+    用户充值:USER_TOPUP
+    商户充值:MCH_TOPUP
+    普通消费:GENERAL_CONSUME
+    担保消费:SECURED_CONSUME
+    */
+    public  $txn_type;
+    // 用户在商户系统中的唯一编号,要求该编号在商户系统能唯一标识用户
+    public  $user_id;
+    /*
+    用户类型。默认:注册用户。
+    注册用户:REGISTERED
+    匿名用户:ANONYMOUS
+    */
+    public  $user_type;
+    // 交易结果异步通知接收地址,建议HTTPS协议。
+    public  $notify_url;
+    public  $return_url;
+    public  $pay_expire;
+    // 商户订单信息
+    public  $orderInfo;
+    // 收款方信息
+    public  $payeeInfo;
+}

+ 13 - 0
application/common/library/llp/src/params/TradeCreatePayeeInfo.php

@@ -0,0 +1,13 @@
+<?php
+
+namespace llianpay\accp\params;
+
+// 统一支付创单---收款方信息
+class TradeCreatePayeeInfo
+{
+    public  $payee_id;
+    public  $payee_type;
+    public  $payee_accttype;
+    public  $payee_amount;
+    public  $payee_memo;
+}

+ 11 - 0
application/common/library/llp/src/params/TradeCreatePayerInfo.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace llianpay\accp\params;
+
+// 统一支付创单---付款方信息
+class TradeCreatePayerInfo
+{
+    public  $payer_type;
+    public  $payer_id;
+
+}

+ 94 - 0
application/common/library/llp/src/security/LLianPayAccpSignature.php

@@ -0,0 +1,94 @@
+<?php
+
+namespace llianpay\accp\security;
+
+class LLianPayAccpSignature
+{
+    /**
+     * 对数据先进行MD5处理,后使用私钥进行RSA加签
+     * @param $data 待加签数据
+     * @return string 返回签名
+     */
+    public static function sign($data = '')
+    {
+        if (empty($data)) {
+            Logger()->error("[加签处理中]:待加签数据为空,请核实!");
+            return False;
+        }
+
+        $private_key = self::_get_pem_content(merchant_private_key_path);
+        if (empty($private_key)) {
+            Logger()->error("[加签处理中]:私钥错误,请核实!");
+            return False;
+        }
+
+        $pkeyid = openssl_get_privatekey($private_key);
+        if (empty($pkeyid)) {
+            Logger()->error("[加签处理中]:私钥错误,请核实!");
+            return False;
+        }
+
+        // 对数据进行MD5处理
+        $md5Var = md5($data);
+        Logger()->info("[加签处理中]:待签名源内容:" . $data);
+        Logger()->info("[加签处理中]:待签名源内容对应MD5值为:" . $md5Var);
+        
+        // 使用数据的MD5值和私钥进行RSA加密
+        $verify = openssl_sign($md5Var, $signature, $pkeyid, OPENSSL_ALGO_MD5);
+        $result = base64_encode($signature);
+        Logger()->info("[加签处理中],签名值为:" . $result);
+        return $result;
+    }
+
+    /**
+     * 利用连连公钥和进行验签
+     * @param $data 待验证数据
+     * @param $signature 签名值
+     * @return -1:error验签异常 1:correct验证成功 0:incorrect验证失败
+     */
+    public static function checkSign($data = '', $signature = '')
+    {
+        if (empty($data) || empty($signature)) {
+            Logger()->error("[验签处理中]:待验签数据或签名值为空,请核实!");
+            return False;
+        }
+
+        $public_key = self::_get_pem_content(llianpay_public_key_path);
+        if (empty($public_key)) {
+            Logger()->error("[验签处理中]:验签公钥错误,请核实!");
+            return False;
+        }
+
+        $pkeyid = openssl_get_publickey($public_key);
+        if (empty($pkeyid)) {
+            Logger()->error("[验签处理中]:验签公钥错误,请核实!");
+            return False;
+        }
+
+        // 对数据进行MD5处理
+        $md5Var = md5($data);
+        Logger()->info("[验签处理中]:待验签数据为:" . $data);
+        Logger()->info("[验签处理中]:待验签数据对应MD5值为:" . $md5Var);
+        Logger()->info("[验签处理中]:待验签名值为:" . $signature);
+
+        // 使用数据的MD5值和签名值进行RSA校验
+        $ret = openssl_verify($md5Var, base64_decode($signature), $pkeyid, OPENSSL_ALGO_MD5);
+        switch ($ret) {
+            case 0:
+                Logger()->info("[验签处理中]:验签完成,验签结果为:错误");
+                break;
+            case 1:
+                Logger()->info("[验签处理中]:验签完成,验签结果为:正确");
+                break;
+            default:
+                Logger()->error("[验签处理中]:验签异常!");
+                break;
+        }
+        return $ret;
+    }
+
+    private static function _get_pem_content($file_path)
+    {
+        return file_get_contents(dirname(__FILE__, 3) . $file_path);
+    }
+}

+ 29 - 0
application/common/library/llp/tests/GetRandomDemo.php

@@ -0,0 +1,29 @@
+<?php
+
+use llianpay\accp\client\LLianPayClient;
+use llianpay\accp\params\GetRandomParams;
+
+require '../vendor/autoload.php';
+require '../src/cfg.php';
+require '../src/client/LLianPayClient.php';
+require '../src/params/GetRandomParams.php';
+
+// 测试“随机因子获取”接口https://open.lianlianpay.com/docs/accp/accpstandard/get-random.html
+function test_getRandom()
+{
+    // 构建请求参数
+    $params = new GetRandomParams();
+    $params->timestamp = date("YmdHis");
+    $params->oid_partner = OID_PARTNER;
+    $params->user_id = 'LLianPayTest-In-User-12345';
+    $params->flag_chnl = 'H5';
+    $params->pkg_name = 'test';
+    $params->app_name = 'test';
+
+    // 测试环境地址
+    $url = 'https://accpapi-ste.lianlianpay-inc.com/v1/acctmgr/get-random';
+    $result = LLianPayClient::sendRequest($url, json_encode($params));
+    echo $result;
+}
+
+test_getRandom();

+ 31 - 0
application/common/library/llp/tests/TestSignature.php

@@ -0,0 +1,31 @@
+<?php
+
+use llianpay\accp\security\LLianPayAccpSignature;
+
+require '../vendor/autoload.php';
+require '../src/cfg.php';
+require '../src/security/LLianPayAccpSignature.php';
+
+function test_sign()
+{
+    $data = '{"app_name":"test","encrypt_algorithm":"RSA","flag_chnl":"H5","oid_partner":"2020042200284052","pkg_name":"test","timestamp":"20220831151608","user_id":"LLianPayTest-In-User-12345"}';
+    $result = LLianPayAccpSignature::sign($data);
+    echo 'MD5值: ' . md5($data) . '<br/>';
+    echo '签名值: ' . $result . '<br/>';
+}
+
+function test_checkSign()
+{
+    $data = '{"license":"UjNpRHFyYWhSYzk5R1AzcTBCb1ZucURyLzhpekNiN1dGYkRWM1A3NjlnSzZnK0VZMDVzeno3akYrYS84VlR4UHhxRkFJRjJmeWdWKzJsU1hTV2hNMzg5WTBpbFk0bGhzU01GcXQvOTcyQmZ4akNtUXlrNEpMVnk0OXR0eXhRZ3RpYmFIMXkxcHg5UDZIbnBweG8rbGZqcS9Yekh1VGJ1K3kyZnBFS3didC9nPXsiaWQiOjAsInR5cGUiOiJ0ZXN0IiwicGxhdGZvcm0iOjEwLCJub3RiZWZvcmUiOiIyMDIyMDUzMCIsIm5vdGFmdGVyIjoiMjAyMjExMzAifQ==","map_arr":"WycxMDYnLCAnODQnLCAnNTgnLCAnMTAxJywgJzg1JywgJzEyMCcsICcxMTEnLCAnMzgnLCAnMTIyJywgJzU5JywgJzEwOCcsICc3NScsICc5OCcsICc3OScsICc0MycsICc3OCcsICc5NCcsICc4MCcsICcxMDQnLCAnNzYnLCAnMTIzJywgJzgzJywgJzkzJywgJzU0JywgJzUyJywgJzU1JywgJzM1JywgJzQxJywgJzg4JywgJzkwJywgJzY0JywgJzQ1JywgJzg3JywgJzEwMCcsICc2NycsICc0OScsICc5MScsICc0MicsICc5NycsICc0NicsICc4OScsICcxMDInLCAnNTEnLCAnNTMnLCAnMzYnLCAnNjEnLCAnODYnLCAnNzQnLCAnMzknLCAnMTE2JywgJzEwOScsICcxMTInLCAnMTI0JywgJzEwMycsICcxMTknLCAnMzQnLCAnODEnLCAnNzAnLCAnMTE0JywgJzEwNycsICc5NicsICc3NycsICczNycsICc2NScsICc5NScsICc2MicsICc1MCcsICcxMTcnLCAnMTI1JywgJzkyJywgJzEyMScsICcxMTgnLCAnMzMnLCAnNzEnLCAnOTknLCAnMTEwJywgJzEyNicsICc0NCcsICcxMTMnLCAnNjgnLCAnNjknLCAnNjAnLCAnNjMnLCAnODInLCAnNDAnLCAnNzMnLCAnNDgnLCAnNTYnLCAnMTA1JywgJzQ3JywgJzU3JywgJzY2JywgJzExNScsICc3Midd","oid_partner":"2020042200284052","random_key":"94a5696e-5ce7-411e-9e5c-9077de1e88b9","random_value":"03160636186708760105019522103795","ret_code":"0000","ret_msg":"交易成功","rsa_public_content":"308189028181009017e40c4b053ef663903066618131e705a91641441d8bc5de082a12147559dcbc790e7b85a0e42a388effa2b7d0c5f734733ef14869fb735b5245bda1d79e32c35004288190e080f8abe8ae7c8f2ff81738c1c32d6e944be7ad1197cb1d8c76455d6da8d623a0513647f5a59d1e9aa6ca077f136040b550ad411728455bf6230203010001","user_id":"LLianPayTest-In-User-12345"}';
+    $signature = 'RRnv2UU0myYQa3kACFRneWySWMXviJYSsY8lxyVV281N4hj9dbx5hgS3TJh2AW31Wus5q31BSI0b5jBUzGeF+F+OaWtFwmGfXWsOL0SYY4rCdeo2sXfNVwkzanPgdp9XqE2beWMXDNAFpTTjs6XfITHM8CREg6kbur7Smg6KhWM=';
+    
+    $result = LLianPayAccpSignature::checkSign($data, $signature);
+    if ($result == 1) {
+        echo '验签结果: 正确!';
+    } else {
+        echo '验签结果:错误!';
+    }
+}
+
+test_sign();
+test_checkSign();

+ 48 - 0
application/common/library/llp/tests/TradeCreateDemo.php

@@ -0,0 +1,48 @@
+<?php
+
+use llianpay\accp\client\LLianPayClient;
+use llianpay\accp\params\TradeCreateParams;
+use llianpay\accp\params\TradeCreateOrderInfo;
+use llianpay\accp\params\TradeCreatePayeeInfo;
+
+require '../vendor/autoload.php';
+require '../src/cfg.php';
+require '../src/client/LLianPayClient.php';
+require '../src/params/TradeCreateParams.php';
+require '../src/params/TradeCreateOrderInfo.php';
+require '../src/params/TradeCreatePayeeInfo.php';
+
+// 测试“统一支付创单”接口https://open.lianlianpay.com/docs/accp/accpstandard/accp-tradecreate.html
+function test_tradeCreate()
+{
+    // 构建请求参数
+    $params = new TradeCreateParams();
+    $current = date("YmdHis");
+    $params->timestamp = $current;
+    $params->oid_partner = OID_PARTNER;
+    $params->txn_type = 'GENERAL_CONSUME';
+    $params->user_id = 'LLianPayTest-In-User-12345';
+    $params->notify_url = 'https://test.lianlianpay.com/notify';
+    $params->return_url = 'https://test.lianlianpay.com/return';
+    $orderInfo = new TradeCreateOrderInfo();
+    $orderInfo->txn_seqno = 'LLianPayTest' . $current;
+    $orderInfo->txn_time = $current;
+    $orderInfo->total_amount = 2.00;
+    $params->orderInfo = $orderInfo;
+
+    $u_payeeInfo = new TradeCreatePayeeInfo();
+    $u_payeeInfo->payee_id = 'LLianPayTest-En-User-12345';
+    $u_payeeInfo->payee_type = 'USER';
+    $u_payeeInfo->payee_amount = '1.00';
+    $m_payeeInfo = new TradeCreatePayeeInfo();
+    $m_payeeInfo->payee_id = OID_PARTNER;
+    $m_payeeInfo->payee_type = 'MERCHANT';
+    $m_payeeInfo->payee_amount = '1.00';
+    $params->payeeInfo = array($u_payeeInfo, $m_payeeInfo);
+    // 测试环境地址
+    $url = 'https://accpapi-ste.lianlianpay-inc.com/v1/txn/tradecreate';
+    $result = LLianPayClient::sendRequest($url, json_encode($params));
+    echo $result;
+}
+
+test_tradeCreate();

+ 0 - 0
public/lianLianNotify.txt