mer_no = '6888806122762';//商户号 6888806122762[正式] 68888TS122762[测试] $this->mer_key = '6mksKr1IsfU0kTD9DNayV67cvfYJVQWLOOLYwJX1rOq5DJVsppgr07JYEMG5g+4hgx/Dlc/pW00=';//未使用 $this->business_private = APP_PATH.'common/library/sandpay/prdnew.pfx';//私钥 prd.pfx[正式] 68888TS122762.pfx[测试] $this->sandpay_public = APP_PATH.'common/library/sandpay/prdnew.cer';//公钥 sand-prd-prd.cer[正式] sand-test-test.cer[测试] $this->sandpublic = APP_PATH.'common/library/sandpay/sand.cer';//衫德公钥 $this->privateKeyPwd = 'jin860815';//私钥密码 jin860815[正式] 123456[测试] $this->domain_url = config('domain_url'); $this->h5_url = config('h5_url'); $this->md5key = 'kYgEWLWLOUxnxHgcqzdIwvNT9uGPGAAdfe7HyxdHNxa6dfGXO4+DEF+oWkvKRuAcS0h5VeRxfu6SZNbopT9Gz77aAb//j5EciX8mUUtf+8P0ELLrObXih1KbHnhxHKtA6VEMOSJPtypixuz+UKFTiw==';//未使用 } /** * 衫德微信收款 * https://www.yuque.com/sd_cw/xfq1vq/ut7292 * @return array */ public function wechat($params=[]){ $result = [ 'status' => 1, 'msg' => '', 'data' => [], ]; try { //统一下单参数 $time = time(); $createTime = date('YmdHis',$time); /*wx_app_id:移动应用Appid(微信开放平台获取,wx开头)gh_ori_id:小程序原始id(微信公众平台获取,gh_开头) path_url:拉起小程序页面默认地址 miniProgramType:开发时根据小程序是开发版、体验版或正式版自行选择。正式版:0; 开发版:1; 体验版:2*/ $payExtra = ['wx_app_id'=>'wx64e2709ce8095ab6','gh_ori_id'=>'gh_be8042ce502b','path_url'=>'pages/zf/index?','miniProgramType'=>'2']; $ip = request()->ip(); $ipStr = str_replace('.','_',$ip); $orderNo = isset($params['order_no']) ? $params['order_no'] : 'P23082914483724021875'; $goodsName = isset($params['goods_name']) ? $params['goods_name'] : 'test'; $money = isset($params['money']) ? $params['money'] : "0.1"; $type = isset($params['type']) ? $params['type'] : 'gold';//vip=会员,gold=充值 $extend = ['type' => $type]; $payExtraStr = json_encode($payExtra); $payExtraStr = stripslashes($payExtraStr); //$payExtraStr = str_replace('\\','',$payExtraStr); $paramsData = [ 'version' => '10',//版本号 默认为10 'mer_no' => $this->mer_no,//商户号 商户号是68888开头13位 'mer_order_no' => $orderNo,//商户订单号 自定义,最小长度12位 到30位 'create_time' => $createTime,//订单创建时间 yyyyMMddHHmmss例 20180813142345 'order_amt' => $money,//订单金额 例:"order_amt"="0.11" 单位: 元 //部分产品金额有最小额度限制,建议设置大于0.1元 'notify_url' => 'https://zhiliao.huxiukeji.com/api/sandpay/notify',//异步通知地址 例http://sandcash/notify 主动通知商户充转提付、开户签约结果的https路径。通知地址必须为直接可以访问的URL。该地址需向杉德报备。回调地址规则:https://cshall.sandpay.com.cn/knowledge/detail/10390 'create_ip' => $ipStr,//客户端IP 用户所在客户端的真实ip其中的“.”替换为“_” 。例192_168_0_1。 'pay_extra' => $payExtraStr,//支付扩展域 'accsplit_flag' => 'NO',//分账标识 例:NO 无分账:NO;有分账:YES 'sign_type' => 'RSA',//签名类型,默认RSA 'store_id' => '000000',//门店号 没有就填默认值000000 //'activity_no' => '',//[非必填]优惠活动编码 //'benefit_amount' => '',//[非必填]优惠金额 'extend' => json_encode($extend),//[非必填json]扩展域 如上送,在异步通知和查询接口中将返回相同的值 //H5产品URL上需要编码 //此字段云账户产品不支持 //'merch_extend_params' => '',//[非必填json]商户扩展参数 商户扩展参数,JSON格式:{mchReceiveRemark:S0划款备注}//H5产品URL上需要编码 ]; $paramsDataTemp = $this->getSignContent($paramsData); // step2: 生成AESKey并使用公钥加密 //$AESKey = $this->aes_generate(16); $pubKey = $this->loadX509Cert($this->sandpay_public);//公钥 $priKey = $this->loadPk12Cert($this->business_private, $this->privateKeyPwd);//私钥 //$encryptKey = $this->RSAEncryptByPub($AESKey, $pubKey); // step3: 使用AESKey加密报文 //$encryptData = $this->AESEncrypt($paramsData, $AESKey); // step4: 使用私钥签名报文 $sign = $this->signNew($paramsDataTemp); // step7: 使用私钥解密AESKey //$decryptAESKey = $this->RSADecryptByPri($encryptKey, $priKey); // step8: 使用解密后的AESKey解密报文 //$decryptPlainText = $this->AESDecrypt($encryptData, $decryptAESKey); // step9: 使用公钥验签报文 //$this->tixian_verify($decryptPlainText, $sign, $pubKey); //不参与签名 $expireTime = date('YmdHis',$time + 60 * 30); $metaOption = [['s'=>'Android','n'=> '','id'=>'','sc'=>'']]; $paramsNo = [ 'return_url' => '',//[不参与签名]前台跳转地址 例 http://sandcash/return 支付完成之后的重定向跳转地址,用于返回商户的APP或网页 //02020004、02010005:return_url需传空,且不参与签名,例:"return_url":"" 'expire_time' => $expireTime,//[不参与签名]订单失效时间 yyyyMMddHHmmss 例20180813142415,建议设置0.5~1小时 'goods_name' => $goodsName,//[不参与签名]商品名称 不能含有特殊字符 'product_code' => '02010005',//[不参与签名]产品编码 例02010005 APP包装微信小程序02010005 'clear_cycle' => '3',//[不参与签名]例 : "clear_cycle"="3"; 3-D1;0-T1;1-T0;2-D0 'sign' => $sign,//[不参与签名]签名结果 'jump_scheme' => 'sandcash://scpay',//[不参与签名]跳转scheme 没有就填默认值sandcash://scpay //此参数是安卓支付宝SDK跳转所需参数,如自定义,需要和客户端工程配置保持一致,例:android:scheme = "aaa",android:host = "bbb",jump_scheme 需填“aaa://bbb”。 'meta_option' => json_encode($metaOption),//[不参与签名]终端/网站参数[{"s":"Android","n":"","id":"","sc":""},{"s":"IOS","n":"","id":"","sc":""}] //本参数填文档示例值就可以 'limit_pay' => '',//[不参与签名][非必填]限定支付方式 例 1 微信:传1屏蔽所有信用卡 支付宝:传1-限定不能使用贷记卡 传4-限定不能使用花呗传 5-限定不能使用贷记卡+花呗 'extend_params' => '',//[不参与签名][非必填]功能参数域 实名认证域: payerVerificationInfo extend_params={"payerVerificationInfo": {"needCheckFlag":"01",//是否实名 01-实名 02-不实名"name":"张三",//姓名"certNo":"12321321312312321",//证件号"certType":"01"//证件类型-01身份证 }} ]; $paramsAll = array_merge($paramsData,$paramsNo); ksort($paramsAll); $result['data'] = json_encode($paramsAll,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES); //$result['data'] = str_replace('\\','',$result['data']); //echo '
';var_dump($paramsAll);exit;
            /*$data['head'] = [
                'version' => '1.0',
                'method' => 'sandpay.trade.pay',
                'productId' => '00002021',
                'accessType' => '1',
                'mid' => $this->mer_no,
                'plMid' => '',
                'channelType' => '08',//商户的真实应用场景,可选项包括:07-互联网 08-移动端
                'reqTime' => $createTime,
            ];
            $totalAmount = $this->format_money($money);
            $payExtra = [
                'subAppid' => 'wx64e2709ce8095ab6',
                'userId' => '',//微信的 openid
            ];
            $priKey = $this->loadPk12Cert($this->business_private, $this->privateKeyPwd);

            $data['body'] = [
                'orderCode' => 'P23082214483724021874',
                'totalAmount' => $totalAmount,
                'subject' => '充值测试',
                'body' => '充值金币',
                'activityNo' => '',
                'benefitAmount' => '',
                'txnTimeOut' => '',
                'payMode' => 'sand_wx',
                'payExtra' => json_encode($payExtra),
                'clientIp' => $ip,
                'notifyUrl' => 'https://zhiliao.huxiukeji.com/api/sandpay/notify',
                'frontUrl' => '',
                //'storeId' => '',
                //'limitPay' => '',
                //'terminalId' => '',
                //'operatorId' => '',
                //'clearCycle' => '0',
                //'riskRateInfo' => '',
                //'payerVerificationInfo' => '',
                //'bizExtendParams' => '',
                //'merchExtendParams' => '',
                //'accsplitInfo' => '',
                'extend' => '',
            ];
            // step2: 私钥签名
            $sign = $this->sign($data, $priKey);
            // step3: 拼接post数据
            $post = array(
                'charset' => 'utf-8',
                'signType' => '01',
                'data' => json_encode($data),
                'sign' => $sign,
            );
            $url = 'https://smp-uat01.sand.com.cn/gateway/api/order/pay';
            //$url = 'https://caspay.sandpay.com.cn/gateway/api/order/pay';
            $ret = $this->http_post_json($url,$post);
            $sandRes = $this->parseResult($ret);
            // step6: 获取credential
            $dataRes = json_decode($sandRes['data'], true);
            echo '
';var_dump($dataRes);exit;*/
            /* //实例
            $dataRes = [
                'head' => [
                    'respTime' => '20230823150801',
                    'respMsg' => '成功',
                    'version' => '1.0',
                    'respCode' => '000000',
                ],
                'body' => [
                    'totalAmount' => "000000000010",
                    'clearDate' => NULL,
                    'credential' => '{"payMode":"wx_pub","params":"{\"payInfo\":{\"trade_no\":\"weixin://wxpay/bizpayurl?pr=xxxxxx\"}}"}',
                    'tradeNo' => 'P23082214483724021871',
                    'payTime' => NULL,
                    'buyerPayAmount' => NULL,
                    'orderCode' => 'P23082214483724021871',
                    'discAmount' => NULL,
                    'prepay_id' => NULL,
                ],
            ];*/
        } catch (Exception $e) {
            $result['status'] = 0;
            $result['msg'] = $e->getMessage();
        }
        return $result;
    }

    /**
     * 衫德微信收款
     * https://www.yuque.com/sd_cw/xfq1vq/ut7292
     * @return array
     */
    public function wechath5($params=[]){
        $result = [
            'status' => 1,
            'msg' => '',
            'data' => [],
        ];
        try {
            //统一下单参数
            $time = time();
            $createTime = date('YmdHis',$time);
            /*pay_extra支付拓展域为:"resourceAppid":"小程序 AppID""resourceEnv":"云开发环境 ID"*/
            $payExtra = ['resourceAppid'=>'wxd710096818e8f24a','resourceEnv'=>'wxd710096818e8f24a-5dvn9bbdc0aa5'];
            $ip = request()->ip();
            $ipStr = str_replace('.','_',$ip);
            $orderNo = isset($params['order_no']) ? $params['order_no'] : 'P23091214483724021876';
            $goodsName = isset($params['goods_name']) ? $params['goods_name'] : 'test';
            $money = isset($params['money']) ? $params['money'] : "0.1";
            $type  = isset($params['type']) ? $params['type'] : 'gold';//vip=会员,gold=充值
            $extend = json_encode(['type' => $type]);
            $payExtraStr = json_encode($payExtra);
            $url = 'https://sandcash.mixienet.com.cn/pay/h5/applet?';//正式环境
            //$url = 'https://sandcash-uat01.sand.com.cn/pay/h5/applet?';//测试环境
            $dumain = $_SERVER['HTTP_HOST'];
            $notifyUrl = 'https://'.$dumain.'/api/sandpay/notify';
            $paramsData = [
                'version'             => '10',//版本号 默认为10
                'mer_no'              => $this->mer_no,//商户号 商户号是68888开头13位
                'mer_order_no'        => $orderNo,//商户订单号 自定义,最小长度12位 到30位
                'create_time'         => $createTime,//订单创建时间 yyyyMMddHHmmss例 20180813142345
                'order_amt'           => $money,//订单金额 例:"order_amt"="0.11" 单位: 元 //部分产品金额有最小额度限制,建议设置大于0.1元
                'notify_url'          => $notifyUrl,//异步通知地址 例http://sandcash/notify 主动通知商户充转提付、开户签约结果的https路径。通知地址必须为直接可以访问的URL。该地址需向杉德报备。回调地址规则:https://cshall.sandpay.com.cn/knowledge/detail/10390
                //'return_url'          => '',
                'create_ip'           => $ipStr,//客户端IP 用户所在客户端的真实ip其中的“.”替换为“_” 。例192_168_0_1。
                'pay_extra'           => $payExtraStr,//支付扩展域
                'accsplit_flag'       => 'NO',//分账标识 例:NO 无分账:NO;有分账:YES
                'sign_type'           => 'RSA',//签名类型,默认RSA
                'store_id'            => '000000',//门店号 没有就填默认值000000
                //'activity_no'         => '',//[非必填]优惠活动编码
                //'benefit_amount'      => '',//[非必填]优惠金额
                'extend'              => $extend,//[非必填json]扩展域 如上送,在异步通知和查询接口中将返回相同的值 //H5产品URL上需要编码 //此字段云账户产品不支持
                //'merch_extend_params' => '',//[非必填json]商户扩展参数 商户扩展参数,JSON格式:{mchReceiveRemark:S0划款备注}//H5产品URL上需要编码
            ];
            $paramsDataTemp = $this->getSignContent($paramsData);
            $sign = $this->signNew($paramsDataTemp);

            //不参与签名
            $expireTime = date('YmdHis',$time + 60 * 30);
            $metaOption = json_encode([['s'=>'Android','n'=> '','id'=>'','sc'=>''],['s'=>'IOS','n'=> '','id'=>'','sc'=>'']]);
            $paramsNo = [
                //[不参与签名]前台跳转地址 例 http://sandcash/return 支付完成之后的重定向跳转地址,用于返回商户的APP或网页 //02020004、02010005:return_url需传空,且不参与签名,例:"return_url":""
                'expire_time'   => $expireTime,//[不参与签名]订单失效时间 yyyyMMddHHmmss 例20180813142415,建议设置0.5~1小时
                'goods_name'    => $goodsName,//[不参与签名]商品名称 不能含有特殊字符
                'product_code'  => '02010006',//[不参与签名]产品编码 例02010005 APP包装微信小程序02010005
                'clear_cycle'   => '3',//[不参与签名]例 :  "clear_cycle"="3"; 3-D1;0-T1;1-T0;2-D0
                'sign'          => $sign,//[不参与签名]签名结果
                'jump_scheme'   => 'sandcash://scpay',//[不参与签名]跳转scheme 没有就填默认值sandcash://scpay //此参数是安卓支付宝SDK跳转所需参数,如自定义,需要和客户端工程配置保持一致,例:android:scheme = "aaa",android:host = "bbb",jump_scheme 需填“aaa://bbb”。
                'meta_option'   => $metaOption,//[不参与签名]终端/网站参数[{"s":"Android","n":"","id":"","sc":""},{"s":"IOS","n":"","id":"","sc":""}] //本参数填文档示例值就可以
                'limit_pay'     => '',//[不参与签名][非必填]限定支付方式 例 1 微信:传1屏蔽所有信用卡 支付宝:传1-限定不能使用贷记卡 传4-限定不能使用花呗传 5-限定不能使用贷记卡+花呗
                'extend_params' => '',//[不参与签名][非必填]功能参数域 实名认证域: payerVerificationInfo extend_params={"payerVerificationInfo": {"needCheckFlag":"01",//是否实名  01-实名  02-不实名"name":"张三",//姓名"certNo":"12321321312312321",//证件号"certType":"01"//证件类型-01身份证 }}
            ];
            $paramsAll = array_merge($paramsData,$paramsNo);
            if (!empty($paramsAll)) {
                //UrlEncode编码字段:goods_name , notify_url,return_url,pay_extra,meta_option,extend,merch_extend_params,sign
                foreach ($paramsAll as $key => &$value) {
                    if (in_array($key,['goods_name','notify_url','return_url','pay_extra','meta_option','extend','merch_extend_params','sign'])) {
                        $value = urlencode($value);
                    }
                }
            }
            $urlStr = $url.$this->getSignContent($paramsAll);
            $result['data'] = $urlStr;

        } catch (Exception $e) {
            $result['status'] = 0;
            $result['msg'] = $e->getMessage();
        }
        return $result;
    }

    //实时付款接口
    //https://open.sandpay.com.cn/product/detail/43327/43930/
    public function payout($order_no,$money,$remark,$bank,$realname){
        $money = $this->format_money($money);
        $data = [
            'version' => 10,           //默认值10
            'productId' =>  '00000004', //付款对私:00000004 付款对公:00000003
            'tranTime' => date('YmdHis', time()),
            'orderCode' => $order_no,
            'tranAmt' => $money,
            'currencyCode' => '156',
            'accAttr' => '0',//账户属性-0对私(默认)
            'accType' => '4', //2-存折 3-公司账户  4-银行卡 注:accAttr选择对公时,accType选公司账户
            'accNo' => $bank,
            'accName' => $realname,
            'remark' => $remark,
            'extend' => '',
        ];

        $config = [
            'publicKeyPath'  =>  $this->sandpay_public,            // 公钥文件
            'privateKeyPath' =>  $this->business_private,            // 私钥文件
            'privateKeyPwd'  =>  $this->privateKeyPwd,            // 私钥证书密码
            'apiUrl'         =>  'https://caspay.sandpay.com.cn/agent-main/openapi/agentpay',            // 接口地址
            'variable' =>[
                'transCode'     => 'RTPM',     //交易码 https://open.sandpay.com.cn/product/detail/43996//
                'accessType'    => '0',        // 接入类型  	0-商户接入,默认   1-平台接入
                'merId'         => $this->mer_no,
            ],
        ];

        $post = $config['variable'];
        //
        $datalist = [];

        $datalist['body'] = $data;
        // step2: 生成AESKey并使用公钥加密
        $AESKey = $this->aes_generate(16);
        $pubKey = $this->loadX509Cert($config['publicKeyPath']);
        $priKey = $this->loadPk12Cert($config['privateKeyPath'], $config['privateKeyPwd']);
        $encryptKey = $this->RSAEncryptByPub($AESKey, $pubKey);
        // step3: 使用AESKey加密报文
        $encryptData = $this->AESEncrypt($datalist['body'], $AESKey);
        // step4: 使用私钥签名报文
        $sign = $this->sign($datalist['body'], $priKey);
        // step5: 拼接post数据


        $post['sign'] = $sign;
        $post['encryptKey'] = $encryptKey;
        $post['encryptData'] = $encryptData;
        $datalist['head'] = $post;

        $url = $config['apiUrl'];
        $ret = $this->http_post_json($url,$post);
        parse_str($ret, $arr);
        try {
            // step7: 使用私钥解密AESKey
            $decryptAESKey = $this->RSADecryptByPri($arr['encryptKey'], $priKey);
            // step8: 使用解密后的AESKey解密报文
            $decryptPlainText = $this->AESDecrypt($arr['encryptData'], $decryptAESKey);
            // step9: 使用公钥验签报文
            $this->tixian_verify($decryptPlainText, $arr['sign'], $pubKey);

            //返回结果
            //0000 成功
            //0001 银行处理中 请等待银行返回的明确结果 . 需要查询
            //0002 银行返回超时 请等待银行返回的明确结果 . 需要查询
            //其他 需要重新发起
            $decryptPlainText = json_decode($decryptPlainText,true);
            if(is_array($decryptPlainText) && isset($decryptPlainText['respCode']) && $decryptPlainText['respCode'] == '0000'){
                return true;
            }
            if(is_array($decryptPlainText) && isset($decryptPlainText['respCode']) && in_array($decryptPlainText['respCode'],['0001','0002'])){
                return 'wait';
            }
            if(is_array($decryptPlainText) && isset($decryptPlainText['respCode']) && isset($decryptPlainText['respDesc'])){
                return $decryptPlainText['respCode'].':'.$decryptPlainText['respDesc'];
            }
            return '提现失败';

            /*return  json_encode([
                'verify'    => $decryptPlainText,
                'jjson'    => json_encode($datalist['body']),
                'vjson'    => json_encode($datalist['head']),
                'json'     =>  json_encode($arr),
                'url'      => 'https://open.sandpay.com.cn/product/detail/43324/43895/',
            ]);*/
        } catch (\Exception $e) {
            return  json_encode([
                'json'     =>  $e->getMessage(),
                'url'      => 'https://open.sandpay.com.cn/product/detail/43324/43895/',
            ]);
            echo $e->getMessage();
            exit;
        }
    }

    //拉起一键快捷
    public function onekey_dopayment($order_no,$money,$remark,$user_id){
        $data = [
            'version' => 10,           //默认值10
            'mer_no' =>  $this->mer_no, //商户号  深圳市恩特宏云科技有限公司
            'mer_key' => $this->mer_key, // 商户私钥通过安卓APK工具解析出来的KEY1
            'mer_order_no' => $order_no, //商户唯一订单号
            'create_time' => date('YmdHis'),
            'expire_time' => date('YmdHis', time()+30*60),  //订单失效时间
            'order_amt' => ''.$money.'', //订单支付金额 单位元,最低 0.11元
            'notify_url' => $this->domain_url.'/api/sandpay/notify', //订单支付异步通知
            'return_url' => $this->h5_url . '/#/pages/public/paySuc?type=recharge',//支付成功后自动跳转url
            'create_ip' => str_replace('.','_',request()->ip()),
            'goods_name' => $remark,
            'store_id' => '000000',  //没有就填默认值000000
            'product_code' => '05030001', // 产品编码: 云函数h5:02010006;支付宝H5:02020002;微信公众号H5:02010002;
            //一键快捷:05030001;H5快捷:06030001;支付宝扫码:02020005  ;快捷充值:  06030003;
            //电子钱包【云账户】:开通账户并支付product_code应为:04010001;消费(C2C)product_code 为:04010003 ; 我的账户页面 product_code 为:00000001
            'clear_cycle' => '3', //
            'pay_extra' => json_encode(['userId'=>'test'.$user_id]),//resourceAppid:小程序 AppID ;resourceEnv:云开发环境 ID,云函数所需参数,如不清楚请商户群里详问杉德联调人员
            'accsplit_flag' => 'NO', //无分账:NO;有分账:YES
            'jump_scheme' => 'sandcash://scpay',
//            'meta_option' => json_encode([["s" => "Android","n" => "wxDemo","id" => "com.pay.paytypetest","sc" => "com.pay.paytypetest"]]),
            'meta_option' => json_encode([['s'=>'Android','n'=>'','id'=>'','sc'=>''],['s'=>'IOS','n'=>'','id'=>'','sc'=>'']]),
            'sign_type' => 'MD5'
        ];

        $temp = $data;
        unset($temp['goods_name']);
        unset($temp['jump_scheme']);
        unset($temp['expire_time']);
        unset($temp['product_code']);
        unset($temp['clear_cycle']);
        unset($temp['meta_option']);

//        file_put_contents('log.txt', date('Y-m-d H:i:s', time()) . ' 签名串:' . $this->getSignContent($temp)."&key=OfVZ1x+EcLjZYClVhkD9gqlWnO3" . "\r\n", FILE_APPEND); // key对应商户私钥通过安卓APK工具解析出来的MD5KEY

        $sign = strtoupper(md5($this->getSignContent($temp).'&key='.$this->md5key));  // key对应商户私钥通过安卓APK工具解析出来的MD5KEY
        $data['sign'] = $sign;

        $query = http_build_query($data);
        $payurl = "https://sandcash.mixienet.com.cn/pay/h5/fastpayment?".$query;  //          云函数h5:applet;支付宝H5:alipay;微信公众号H5:wechatpay; //一键快捷:fastpayment;H5快捷:unionpayh5;支付宝扫码:alipaycode  ;快捷充值:quicktopup ;电子钱包【云账户】:cloud

        return $payurl; // 返回支付url
    }

    //拉起h5快捷
    public function dopayment($order_no,$money,$remark,$banknum = ''){
        $data = [
            'version' => 10,           //默认值10
            'mer_no' =>  $this->mer_no, //商户号  深圳市恩特宏云科技有限公司
            'mer_key' => $this->mer_key, // 商户私钥通过安卓APK工具解析出来的KEY1
            'mer_order_no' => $order_no, //商户唯一订单号
            'create_time' => date('YmdHis'),
            'expire_time' => date('YmdHis', time()+30*60),  //订单失效时间
            'order_amt' => ''.$money.'', //订单支付金额 单位元,最低 0.11元
            'notify_url' => $this->domain_url.'/api/sandpay/notify', //订单支付异步通知
            'return_url' => $this->domain_url.'/index/sandpay/payreturn', //订单前端页面跳转地址
            'create_ip' => str_replace('.','_',request()->ip()),
            'goods_name' => $remark,
            'store_id' => '000000',  //没有就填默认值000000
            'product_code' => '06030001', // 产品编码: 云函数h5:02010006;支付宝H5:02020002;微信公众号H5:02010002;
            //一键快捷:05030001;H5快捷:06030001;支付宝扫码:02020005  ;快捷充值:  06030003;
            //电子钱包【云账户】:开通账户并支付product_code应为:04010001;消费(C2C)product_code 为:04010003 ; 我的账户页面 product_code 为:00000001
            'clear_cycle' => '3', //
            'pay_extra' => json_encode(['cardNo'=>$banknum]),//resourceAppid:小程序 AppID ;resourceEnv:云开发环境 ID,云函数所需参数,如不清楚请商户群里详问杉德联调人员
            'accsplit_flag' => 'NO', //无分账:NO;有分账:YES
            'jump_scheme' => 'sandcash://scpay',
//            'meta_option' => json_encode([["s" => "Android","n" => "wxDemo","id" => "com.pay.paytypetest","sc" => "com.pay.paytypetest"]]),
            'meta_option' => json_encode([['s'=>'Android','n'=>'','id'=>'','sc'=>''],['s'=>'IOS','n'=>'','id'=>'','sc'=>'']]),
            'sign_type' => 'MD5'
        ];
        if(!$banknum){
            unset($data['pay_extra']);
        }
        $temp = $data;
        unset($temp['goods_name']);
        unset($temp['jump_scheme']);
        unset($temp['expire_time']);
        unset($temp['product_code']);
        unset($temp['clear_cycle']);
        unset($temp['meta_option']);

//        file_put_contents('log.txt', date('Y-m-d H:i:s', time()) . ' 签名串:' . $this->getSignContent($temp)."&key=OfVZ1x+EcLjZYClVhkD9gqlWnO3" . "\r\n", FILE_APPEND); // key对应商户私钥通过安卓APK工具解析出来的MD5KEY

        $sign = strtoupper(md5($this->getSignContent($temp).'&key='.$this->md5key));  // key对应商户私钥通过安卓APK工具解析出来的MD5KEY
        $data['sign'] = $sign;

        $query = http_build_query($data);
        $payurl = "https://sandcash.mixienet.com.cn/pay/h5/unionpayh5?".$query;  //          云函数h5:applet;支付宝H5:alipay;微信公众号H5:wechatpay; //一键快捷:fastpayment;H5快捷:unionpayh5;支付宝扫码:alipaycode  ;快捷充值:quicktopup ;电子钱包【云账户】:cloud

        return $payurl; // 返回支付url
    }

    private function getSignContent($params) {
        ksort($params);

        $stringToBeSigned = "";
        $i = 0;
        foreach ($params as $k => $v) {
            if (false === $this->checkEmpty($v) && "@" != substr($v, 0, 1)) {

                if ($i == 0) {
                    $stringToBeSigned .= "$k" . "=" . "$v";
                } else {
                    $stringToBeSigned .= "&" . "$k" . "=" . "$v";
                }
                $i++;
            }
        }

        unset ($k, $v);
        return $stringToBeSigned;
    }

    private function getSignContentNew($params) {
        ksort($params);

        $stringToBeSigned = "";
        $i = 0;
        foreach ($params as $k => $v) {
            if ("@" != substr($v, 0, 1)) {
                if ($i == 0) {
                    $stringToBeSigned .= "$k" . "=" . "$v";
                } else {
                    $stringToBeSigned .= "&" . "$k" . "=" . "$v";
                }
                $i++;
            }
        }

        unset ($k, $v);
        return $stringToBeSigned;
    }

    private function checkEmpty($value)
    {
        if (!isset($value))
            return true;
        if ($value === null)
            return true;
        if (trim($value) === "")
            return true;

        return false;
    }

    //校验
    public function verify($plainText, $sign)
    {
        $publickey = $this->publicKey();
        if($publickey === false){
            return 0;
        }
        $resource = openssl_pkey_get_public($publickey);
        $result   = openssl_verify($plainText, base64_decode($sign), $resource);
        openssl_free_key($resource);

        return $result;
    }

    public function publicKey()
    {
        try {
            $file = file_get_contents($this->sandpublic);
            if (!$file) {
                throw new \Exception('getPublicKey::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('getPublicKey::openssl_pkey_get_details ERROR');
            }
            return $detail['key'];
        } catch (\Exception $e) {
            throw $e;
        }
    }

//--------------------------------------------end基础参数配置------------------------------------------------
    /**
     * 获取公钥
     * @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 $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 $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;
        }
    }

    function signNew($str) {
        $file = file_get_contents($this->business_private);
        if (!$file) {
            throw new \Exception('loadPk12Cert::file
                    _get_contents');
        }
        if (!openssl_pkcs12_read($file, $cert, $this->privateKeyPwd)) {
            throw new \Exception('loadPk12Cert::openssl_pkcs12_read ERROR');
        }
        $pem = $cert['pkey'];
        openssl_sign($str, $sign, $pem);
        $sign = base64_encode($sign);
        return $sign;
    }

    /**
     * 公钥验签
     * @param $plainText
     * @param $sign
     * @param $path
     * @return int
     * @throws Exception
     */
    function tixian_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;
    }

    /**
     * 公钥加密AESKey
     * @param $plainText
     * @param $puk
     * @return string
     * @throws Exception
     */
    function RSAEncryptByPub($plainText, $puk)
    {
        if (!openssl_public_encrypt($plainText, $cipherText, $puk, OPENSSL_PKCS1_PADDING)) {
            throw new \Exception('AESKey 加密错误');
        }

        return base64_encode($cipherText);
    }

    /**
     * 私钥解密AESKey
     * @param $cipherText
     * @param $prk
     * @return string
     * @throws Exception
     */
    function RSADecryptByPri($cipherText, $prk)
    {
        if (!openssl_private_decrypt(base64_decode($cipherText), $plainText, $prk, OPENSSL_PKCS1_PADDING)) {
            throw new \Exception('AESKey 解密错误');
        }

        return (string)$plainText;
    }

    /**
     * AES加密
     * @param $plainText
     * @param $key
     * @return string
     * @throws \Exception
     */
    function AESEncrypt($plainText, $key)
    {
        $plainText = json_encode($plainText);
        $result = openssl_encrypt($plainText, 'AES-128-ECB', $key, 1);

        if (!$result) {
            throw new \Exception('报文加密错误');
        }

        return base64_encode($result);
    }

    /**
     * AES解密
     * @param $cipherText
     * @param $key
     * @return string
     * @throws \Exception
     */
    function AESDecrypt($cipherText, $key)
    {
        $result = openssl_decrypt(base64_decode($cipherText), 'AES-128-ECB', $key, 1);

        if (!$result) {
            throw new \Exception('报文解密错误', 2003);
        }

        return $result;
    }

    /**
     * 生成AESKey
     * @param $size
     * @return string
     */
    function aes_generate($size)
    {
        $str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
        $arr = array();
        for ($i = 0; $i < $size; $i++) {
            $arr[] = $str[mt_rand(0, 61)];
        }

        return implode('', $arr);
    }

    /**
     * 发送请求
     * @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);

            if (!$data) {
                throw new \Exception('请求出错');
            }

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

    public function format_money($money){
//        $money = 345678.10;
        $money = $money * 100;

        $zero_arr = [
            0 => '000000000000',
            1 => '00000000000',
            2 => '0000000000',
            3 => '000000000',
            4 => '00000000',
            5 => '0000000',
            6 => '000000',
            7 => '00000',
            8 => '0000',
            9 => '000',
            10 => '00',
            11 => '0',
            12 => '',
        ];

        $newmoney = $zero_arr[strlen($money)] . $money;

        return $newmoney;
//        dump($newmoney);
    }



// curl.解析返回数据
    protected function parseResult($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;
    }

}