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; } }