123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848 |
- <?php
- namespace app\common\library;
- use function EasyWeChat\Kernel\data_to_array;
- /**
- * 杉德支付
- */
- class Sandpay
- {
- //账号
- protected $mer_no = '';
- protected $mer_key = '';
- protected $domain_url = '';
- public function __construct(){
- $this->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 '<pre>';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 '<pre>';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;
- }
- }
|