| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651 |
- <?php
- namespace app\traits;
- use app\model\sxy\DeclareLog;
- use crmeb\exceptions\AuthException;
- use phpseclib3\Net\SFTP;
- use app\controller\Aes;
- use phpseclib3\Crypt\RSA;
- use think\Exception;
- use think\facade\App;
- use think\facade\Db;
- /**
- * 首信易统一请求API
- * Trait ShouxinyiApiRequest
- * @package app\traits
- */
- trait ShouxinyiApiRequest
- {
- /**
- * 申请商户
- * @return bool|string
- * @author lin
- * @created 2021/5/13 9:15
- * */
- public static function merchantApply($merchant=[]){
- try {
- $url = env('SHOUXINYI.HOSTNAME') . 'serviceprovider/declaration/declare';
- $data = [];
- $data['merchantId'] = env('SHOUXINYI.MERCHANTID'); // 商户编号
- $data['requestId'] = self::getOrderNumber('sxy'); //申请商户订单号
- $data['operationType'] = $merchant['operationType'] ?? 'CREATE';//CREATE 创建 MODIFY 更新
- $data['notifyUrl'] = env('APP_URL') . '/api/notify/createMerchant_5upay';//回调地址
- $data['extendedParameters'] = 'autoReview:FALSE,sendActiveEmail:FALSE';//autoReview 是否跳过流程 TRUE 是, FALSE 否 sendActiveEmail 是否发送激活邮件 TRUE 是, FALSE 否
- //CREATE 创建 MODIFY 更新
- // switch ($merchant['is_again']) {
- // case 1 || 2:
- // $data['operationType'] = 'MODIFY';
- // break;
- // case 0:
- // default:
- // $data['operationType'] = 'CREATE';
- // break;
- // }
- $data['operationType'] = 'CREATE';
- /**
- * 商户签约性质:registerRole
- * INDIVIDUAL_BUSINESS 个体工商户
- * PUBLIC_INSTITUTIONS 事业单位
- * PRIVATE_NON_ENTERPRISE_ORGANIZATIONS 民办非企业组织
- * SOCIAL_ORGANIZATION 社会团体
- * UNINCORPORATED_ENTERPRISE 非法人企业
- * ENTERPRISE_LEGAL_PERSON 企业法人
- * NATURAL_PERSON 自然人
- * GOVERNMENT_AGENCIES 政府机关
- * OTHERS 其他
- * */
- /**
- * 证书类型:cerType
- * UNIFORM_SOCIAL_CREDIT_CODE 统一社会信用代码证
- * PRIVATE_NON_ENTERPRISE_UNIT_REGISTRATION_CERTIFICATE 民办非企业单位登记证书
- * INDIVIDUAL_BUSINESS_LICENCE 个体工商户营业执照
- * CERTIFICATE_OF_REGISTRATION_OF_SOCIAL_GROUP_LEGAL_PERSON 社会团体法人登记证书
- * LEGAL_PERSON_CERTIFICATE_OF_INSTITUTION 事业单位法人证书
- * FUND_LEGAL_PERSON_REGISTRATION_CERTIFICATE 基金法人登记证书
- * ID_CARD 身份证
- * BUSINESS_LICENSE 营业执照
- * OTHERS 其他 (当签约性质不为自然人时必传)
- */
- $data['baseInfo'] = [//商户基本信息
- 'signedType' => $merchant['signedType'] ?? 'BY_SPLIT_BILL',//BY_SPLIT_BILL 被分账方 GENERAL_SUB_MERCHANT 收单子商户
- 'signedName' => $merchant['signedName'],//签约名称
- 'registerRole' => $merchant['registerRole'],//商户签约性质
- 'cerType' => $merchant['cerType'],//证书类型
- 'signedShorthand' => $merchant['signedShorthand'],//商户简称
- 'businessAddressProvince' => $merchant['businessAddressProvince'],//省
- 'businessAddressCity' => $merchant['businessAddressCity'],//市
- 'businessAddressArea' => $merchant['businessAddressArea'],//区
- 'businessAddress' => $merchant['businessAddress'],//详细地址
- 'contactName' => $merchant['contactName'],//联系人姓名
- 'contactEmail' => $merchant['contactEmail'],//联系人邮箱
- 'contactPhone' => $merchant['contactPhone'],//联系人电话
- 'businessClassification' => $merchant['businessClassification'],//业务分类
- 'desireAuth' => $merchant['desireAuth']??'',//开户意愿核实类型
- ];
- $data['bankCardInfo'] = [//结算信息
- 'bankCode' => $merchant['bankCode'],//开户行
- 'bankBranchName' => $merchant['bankBranchName'],//支行名称(结算银行卡属性为对公时必填)
- 'accountName' => $merchant['accountName'],//开户名称
- 'bankCardNo' => $merchant['bankCardNo'],//开户账号
- 'cityCode' => $merchant['cityCode'],//市编码
- 'provinceCode' => $merchant['provinceCode'],//省编码
- 'accountType' => $merchant['accountType'],//结算银行卡属性PUBLIC 对公 PRIVATE 对私 (商户类型为个体工商户时必填,个人默认对私,企业等默认对公)
- 'liquidationType' => $merchant['liquidationType'] ?? 'WITHDRAW',//SETTLE 结算 WITHDRAW 提现 (不传默认结算)
- 'withdrawRateType' => $merchant['withdrawRateType'] ?? 'SINGLE',//SINGLE 单笔 RATE 百分比 (清算方式选择提现时必传)
- 'withdrawRate' => $merchant['withdrawRate'] ?? '1',//(清算方式选择提现时必传)如传小数则限制两位小数,配置此项时校验服务商提现费率,如果服务商是百分比费率配置则此项也必须配置百分比,固定值同样,且此项配置费率不能小于服务商费率
- ];
- $data['desireAuthInfo'] = [//开户意愿核实信息(开户意愿核实类型选择手机短信验证时此项必传)
- 'legalPersonName' => $merchant['legalPersonName'],//法人姓名
- 'legalPersonIdNo' => $merchant['legalPersonIdNo'],//法人身份证号
- 'legalPersonPhoneNo' => $merchant['legalPersonPhoneNo'],//法人手机号
- ];
- /**
- * 法人证件类型:legalPersonIdType
- * IDCARD 身份证
- * PASSPORT 护照
- * OFFICERPASS 军官证
- * ARMEDPOLICE 武警证
- * HM_VISITORPASS 港澳居民往来内地通行证
- * RESIDENCEBOOKLET 户口簿
- * T_VISITORPASS 台湾居民来往大陆通行证
- * FOREIGNESTAYFOREVER 外国人永久居留证
- * OTHER 其它证件号
- */
- $data['certificateInfo'] = [//商户资质信息
- 'legalPersonName' => $merchant['legalPersonName'],//法人姓名
- 'profession' => $merchant['profession'],//法人职业
- 'legalPersonIdType' => $merchant['legalPersonIdType'],//法人证件类型
- 'legalPersonIdNo' => $merchant['legalPersonIdNoSup'],//证件号码
- 'idEffectiveDateStart' => $merchant['idEffectiveDateStart'],//法人证件有效期开始日期
- 'idEffectiveDateEnd' => $merchant['idEffectiveDateEnd'],//法人证件有效期结束日期
- 'cerNoType' => $merchant['cerNoType'],//企业证件类型:SOCIAL_CREDIT_NO 统一社会信用代码 BUSINESS_LICENSE_NO 营业执照号码 (商户类型不为自然人时必传)
- 'cerNo' => $merchant['cerNo'],//资质证书编号
- 'sellingArea' => $merchant['sellingArea'],//营业面积:A 500平米以上 B 200-500平米(含) C 200平米以下 (商户类型不为自然人时必传)
- 'staffSize' => $merchant['staffSize'],//公司员工规模A 100人以上 B 50-100人(含) C 50人以下 (商户类型不为自然人时必传)
- 'tradingScenarios' => $merchant['tradingScenarios'] ?? '',//交易场景说明WEBSITE 网站 APP APP WECHAT_APPLET 公众号/小程序/生活号 (可多选,多选时参数用英文半角逗号隔开,商户类型不为自然人或被分账方时必传)
- 'webSite' => $merchant['webSite'] ?? '',//网站网址 (商户类型不为自然人或被分账方时,如交易场景基于PC网站时必传)
- 'webSiteName' => $merchant['webSiteName'] ?? '',//网站名称 (商户类型不为自然人或被分账方时,如交易场景基于PC网站时必传)
- 'icp' => $merchant['icp'] ?? '',//ICP备案号 (商户类型不为自然人或被分账方时,如交易场景基于PC网站时必传)
- 'appName' => $merchant['appName'] ?? '',//App名称 (商户类型不为自然人或被分账方时,如交易场景基于APP时必传)
- 'wechatAppletName' => $merchant['wechatAppletName'] ?? '',//公众号/小程序/生活号 (商户类型不为自然人或被分账方时,如交易场景基于公众号/小程序/生活号时必传)
- 'testAccountInfo' => $merchant['testAccountInfo'] ?? '',//填写可用于首信易审核人员测试交易全流程的测试账号密码
- 'businessLicensePath' => $merchant['businessLicensePath'] ?? '',//营业执照照片路径 需上传到sftp(商户类型不为自然人时必传,最大不超过50M,格式限制为jpg,jpeg,png,pdf)
- 'openAccountPath' => $merchant['openAccountPath'] ?? '',//开户许可证照片路径 需上传到sftp(商户类型不为自然人及个体工商户时必传,为个体工商户时此项和legalPersonBankCardPath二选一进行传递,最大不超过50M,格式限制为jpg,jpeg,png,pdf)
- 'legalIdCardProsPath' => $merchant['legalIdCardProsPath'] ?? '',//法人证件人像面路径
- 'legalIdCardConsPath' => $merchant['legalIdCardConsPath'] ?? '',//法人证件国徽面路径
- 'desireAuthPath' => $merchant['desireAuthPath'] ?? '',//确认入网意愿视频路径 认证类型选择视频认证时必填
- 'holdingIdCardPath' => $merchant['holdingIdCardPath'] ?? '',//法人手持证件影印件路径 认证类型选择手机验证时必传
- 'webSitePath' => $merchant['webSitePath'] ?? '',//商户网址截图影印件路径 商户类型不为自然人或被分账方时,如交易场景基于PC网站时必传
- 'wechatAppletPath' => $merchant['wechatAppletPath'] ?? '',//公众号/小程序/生活号业务流程截图影印件路径 商户类型不为自然人或被分账方时,如交易场景基于公众号/小程序/生活号时必传
- 'appPath' => $merchant['appPath'] ?? '',//APP首页截图影印件路径 商户类型不为自然人或被分账方时,如交易场景基于APP时必传
- 'legalPersonBankCardPath' => $merchant['legalPersonBankCardPath'] ?? '',//法人银行卡图影印件路径 商户类型为自然人时必传,为个体工商户时此项和openAccountPath二选一进行传递
- 'desireAuthOtherPath' => $merchant['desireAuthOtherPath'] ?? '',//确认入网意愿其他验证方式路径 开户意愿核实类型选择“其他验证方式”的时候必传
- 'otherCerPath' => $merchant['otherCerPath'] ?? '',//其他资质文件路径
- 'legalPersonPhone' => $merchant['legalPersonPhoneNo'],//合同类型为“电子签”时必填;必须为法人的手机号。
- ];
- $data['contractInfo'] = [
- 'contractType' => 'ELECTRON',//ELECTRON 电子签 PAPER 纸质合同 默认为“纸质合同”,选择“电子签”时将授权首信易通过电子签名的方式进行签约,无需邮寄合同。
- ];
- /**
- * 支付方式:paymentMode
- * B2C个人网银
- * B2B企业网银
- * EXPRESSPAY_ISNOTDIRECT_DEBIT快捷支付标准版借记卡
- * EXPRESS_PAY_ISNOTDIRECT_CREDIT快捷支付标准版贷记卡
- * EXPRESS_PAY_ISDIRECT_DEBIT快捷支付专业版借记卡
- * EXPRESS_PAY_ISDIRECT_CREDIT快捷支付专业版_贷记卡
- * ALIPAY_SCANCODE支付宝扫码
- * WEIXIN_OFFICIAL微信公众号
- * WEIXIN_MINIAPPS微信小程序
- * ALIPAY_WAP支付宝wap
- * ALIPAY_OFFICIAL支付宝生活号
- * WEIXIN_EQRCODE易码付-微信
- * ALIPAY_EQRCODE易码付-支付宝(商户入网类型=收单子商户时可传,如不传则按服务商默认费率)
- * */
- //入网记录
- // echo $data['requestId'].$merchant['signedName'].'<br>';
- $log = new DeclareLog();
- // $is = $log -> getValueLog("id",$merchant['m_id']);
- // if($is){
- // $log -> where('m_id',$merchant['m_id']) -> update(array(
- // 'data' =>json_encode($data),
- // 'type'=>'5upay',
- // 'requestId'=>$data['requestId'],
- // 'time'=>time(),
- // ));
- // }else{
- $log -> setLog(array(
- 'data' =>json_encode($data),
- 'type'=>'5upay',
- 'requestId'=>$data['requestId'],
- 'time'=>time(),
- 'm_id'=>$merchant['m_id']
- ));
- // }
- $res = self::request($data, $url);
- $log -> updateDe(array(
- 'status' => $res['status'] ?? '',
- 'message' => $res['errorMessage']??'',
- 'requestId'=>$data['requestId']
- ));
- return $res;
- }catch (Exception $exception){
- Db::name("log")->insert(array('data'=>$exception->getFile().':'.$exception->getLine().'【'.$exception->getMessage().'】'));//日志记录
- }
- }
- /**
- * 入网查询
- * @author lin
- * @created 2021/5/14
- */
- public function merchantQuery($requestId){
- $url = env('SHOUXINYI.HOSTNAME') . 'serviceprovider/declaration/query';
- $data['merchantId'] = env('SHOUXINYI.MERCHANTID'); // 商户编号
- // $data['subMerchantId'] = (string)$subMerchantId;// 二级商户编号
- $data['requestId'] = $requestId; //请求订单号
- return self::request($data,$url);
- }
- /**
- * 上传图片到sftp
- * @param string $path 远程文件夹
- * @param string $file 远程路径含文件名
- * @param string $file1 本地文件路径
- * @return bool
- */
- public static function uploadSFtp($path,string $file, string $file1): bool
- {
- $sftp = new SFTP(env('SHOUXINYI.SFTPHOST'),env('SHOUXINYI.SFTPPORT'));
- $login = $sftp->login('899104033', RSA::load(file_get_contents(App::getRootPath()."pkey/5upay/899104033")));
- if (!$login) {
- Db::name("log")->insert(array('data'=>'sftp登录失败'));//日志记录
- }
- $sftp -> mkdir($path);
- return $sftp -> put($file,file_get_contents($file1));
- }
- /**
- * 境内收单
- * @param array $datas
- * @return
- *
- */
- public static function onlinePay($datas){
- $url = 'https://apis.5upay.com/onlinePay/order';
- /*
- * SCANCODE-ALI_PAY-P2P 支付宝扫码(需要传入clientIp,接收返回的base64编码并解析成二维码图片)
- * ALIPAY-WAP-P2P 支付宝H5支付
- * ALIPAY-OFFICIAL 支付宝生活号支付
- * MINIAPPS-WEIXIN_PAY-P2P 微信小程序 需要IP、openid 传小程序商编
- * WECHAT-OFFICIAL_PAY 微信公众号 传公众号商编 需要openid
- * SCANCODE-EQRCODE_PAY 易码付 传公众号商编
- * */
- try {
- $data['merchantId'] = env('SHOUXINYI.MERCHANTID'); // 商户编号
- $data['requestId'] = $datas['requestId'];//订单号
- $data['orderAmount'] = $datas['orderAmount'];//金额。单位分
- $data['orderCurrency'] = 'CNY';//交易币种默认CNY(人民币)
- // $data['notifyUrl'] = env('APP_URL') . '/api/notify/pay_5upay';//回调地址;//通知地址
- $data['notifyUrl'] = env('APP_URL') . $datas['notifyUrl'];//回调地址;//通知地址
- $data['callbackUrl'] = $datas['callbackUrl'];//同步地址
- $data['remark'] = $datas['remark'] ?? '1';// 备注,通过支付结果返回商户
- $data['paymentModeCode'] = $datas['paymentModeCode'];//支付方式编码
- switch ($data['paymentModeCode']){
- case "MINIAPPS-WEIXIN_PAY-P2P": //微信小程序 需要IP、openid 传小程序商编
- $data['appId'] = env('WECHAT_MP.APPID');//小程序appId
- $data['reportSerialNo'] = env('SHOUXINYI.REPORT_SREIAL_MP_NO1');//报备序列号
- break;
- case "SCANCODE-EQRCODE_PAY"://易码付
- case "WECHAT-OFFICIAL_PAY"://微信公众号 传公众号商编 需要openid
- case "WECHAT-OFFICIAL_PAY-P2P"://微信公众号 传公众号商编 需要openid
- $data['appId'] = env('WECHAT.APPID');//微信appId
- $data['reportSerialNo'] = env('SHOUXINYI.REPORT_SREIAL_NO1');//报备序列号
- break;
- }
- $data['openId'] = $datas['openId'] ?? '';//微信openId,或者支付宝的buyer_id或者用户的钱包ID,或者微包服务号的openid
- $data['productDetails'] = $datas['productDetails'];//商品信息
- $data['splitMark'] = $datas['splitMark'] ?? 'DO_SPLIT';//DO_SPLIT 分账,NOT_DO_SPLIT 不分帐 默认分账
- $data['payer'] = ['name'=>''];//此json可空,但是不可将此参数整个去掉,需以以下格式传入接口: “payer”:{}
- $data['clientIp'] = $datas['clientIp'] ?? '';//客户端外网IP
- return self::request($data, $url);
- }catch (Exception $exception){
- Db::name("log")->insert(array('data'=>$exception->getFile().':'.$exception->getLine().'【'.$exception->getMessage().'】'));//日志记录
- return $exception->getFile().':'.$exception->getLine().'【'.$exception->getMessage().'】';
- }
- }
- /**
- * 订单查询
- * @param array $datas
- * @return
- */
- public static function onlinePay_query($datas){
- $url = "https://apis.5upay.com/onlinePay/query";
- $data['merchantId'] = env('SHOUXINYI.MERCHANTID'); // 商户编号
- $data['requestId'] = $datas['requestId']; //订单号要查询的订单号
- return self::request($data, $url);
- }
- /**
- * 分账
- * @param array $datas
- * @return
- */
- public static function split($datas){
- $url = "https://apis.5upay.com/split/order";
- $data['merchantId'] = env('SHOUXINYI.MERCHANTID'); // 商户编号
- $data['notifyUrl'] = env('APP_URL') . '/api/notify/pay_split_5upay';//回调地址
- $data['requestId'] = $datas['requestId']; //订单号
- $data['orderId'] = $datas['orderId'];//交易订单的订单号
- $data['totalSplitAmount'] = $datas['totalSplitAmount'];//分账金额
- $data['splitDetails'] = $datas['splitDetails'];//分账信息
- /*
- * splitDetails 分账信息:
- * subSplitRequestId: 分账明细订单号
- * splitAccType: 分账类型 MERCHANT_ACC 商户;WALLET_ACC 钱包
- * splitAccId: 分账类型为商户时此参数传商户的merchantId(可传主商户商编),分账类型为钱包时此参数传用户的walletId
- * splitAmount: 分账明细订单金额
- * remark: 备注
- * */
- return self::request($data, $url);
- }
- /**
- * 提现
- * @param array $datas
- * @return
- */
- public static function withdrawal($datas){
- $url = "https://apis.5upay.com/wallet/withdraw";
- $data['partnerId'] = env('SHOUXINYI.MERCHANTID'); // 主商户编号
- $data['merchantId'] = $datas['merchantId']; // 商户编号
- $data['requestId'] = $datas['requestId']; // 订单编号
- $data['withdrawAmount'] = $datas['withdrawAmount']; // 提现金额 分为单位,不带小数点
- $data['notifyUrl'] = env('APP_URL') . '/api/notify/withdrawal_5upay';//回调地址
- return self::request($data, $url);
- }
- /**
- * 提现查询
- * @param array $datas
- * @return
- */
- public static function withdrawQuery($datas){
- $url = "https://apis.5upay.com/wallet/withdrawQuery";
- $data['partnerId'] = env('SHOUXINYI.MERCHANTID'); // 主商户编号
- $data['merchantId'] = $datas['merchantId']; // 商户编号
- $data['requestId'] = $datas['requestId']; // 订单编号
- return self::request($data, $url);
- }
- /**
- * 查询可提现金额
- * @param array $datas
- * @return
- */
- public static function balanceQuery($datas){
- $url = "https://apis.5upay.com/member/balanceQuery";
- $data['partnerId'] = env('SHOUXINYI.MERCHANTID'); // 主商户编号
- $data['merchantId'] = $datas['merchantId']; // 商户编号
- $data['requestId'] = $datas['requestId']; // 订单编号
- $data['currency'] = $datas['currency']; // 查询币种
- $data['dateTime'] = $datas['dateTime']; // 时间戳
- $data['accountType'] = $datas['accountType']; // 账户类型
- return self::request($data, $url);
- }
- /**
- * 修改银行信息
- * @param array $datas
- * @return
- */
- public static function modifyBankCard($datas){
- $url = "https://apis.5upay.com/serviceprovider/declaration/modifyBankCard";
- $data['merchantId'] = $datas['merchantId']; // 主商户编号
- $data['subMerchantId'] = $datas['subMerchantId']; // 二级商户编号
- $data['requestId'] = $datas['requestId']; // 订单号
- $data['bankCode'] = $datas['bankCode']; // 开户行
- $data['bankBranchName'] = $datas['bankBranchName']; // 支行名称
- $data['bankCardNo'] = $datas['bankCardNo']; // 开户账号
- $data['cityCode'] = $datas['cityCode']; // 市编码
- $data['provinceCode'] = $datas['provinceCode']; // 省编码
- return self::request($data, $url);
- }
- /**
- * 退款
- * @param array $datas
- * @return
- */
- public static function refund($datas,$type=1){
- $url = "https://apis.5upay.com/onlinePay/refund";
- try {
- $data['merchantId'] = env('SHOUXINYI.MERCHANTID'); // 商户编号
- $data['notifyUrl'] = env('APP_URL') . '/api/notify/pay_refund_5upay';//回调地址
- $data['requestId'] = $datas['requestId']; //订单号
- $data['orderId'] = $datas['orderId'];//原交易订单的流水号
- $data['amount'] = $datas['amount'];//退款金额
- $data['remark'] = '备注';
- if($type==1) {
- $data['isCollect'] = $datas['isCollect'];
- $data['refundCollectDetail'] = $datas['refundCollectDetail'];//归集信息
- }
- return self::request($data, $url);
- }catch (Exception $exception){
- Db::name("log")->insert(array('data'=>$exception->getFile().':'.$exception->getLine().'【'.$exception->getMessage().'】'));//日志记录
- return $exception->getFile().':'.$exception->getLine().'【'.$exception->getMessage().'】';
- }
- }
- /**
- * 签名
- * @param $data
- * @param int $type 1:其他接口。2:提现接口
- * test2
- * @return array|bool
- * @author lin
- * @created 2021/5/13 17:54
- */
- public static function getSign($data){
- //第一步键名首字母排序
- //第二步sha1签名
- //第三步私钥签名
- //第四步生成十六位aes密钥
- //第五步data用AES加密
- //第六步.公钥加密.加密的数据是第四步生成的AES密钥,防止AES密钥泄露
- try {
- $sort = self::sortArray($data);//第一步键名首字母排序
- $sha1=sha1($sort, true);//第二步sha1签名
- $data['hmac'] = self::rsaPrivateSign($sha1,App::getRootPath(). 'pkey/5upay/private.pfx','IDajxBO5');//第三步CFCA私钥签名
- $randStr = self::getRandStr(16);//第四步生成十六位aes密钥
- $json = json_encode($data);
- $body = Aes::encrypt7($json,$randStr);//第五步AES加密
- //header
- // $header_partnerId = $data['partnerId'];//服务商id.如果业务没有服务商id的话可不传此参数
- $headerArray = array(
- "Content-type:application/vnd.5upay-v3.0+json",
- "merchantId:".$data['merchantId'],//商户编号
- "requestId:".$data['requestId'],//商户订单号
- "encryptKey:".self::rsaPublicEncode(App::getRootPath(). 'pkey/5upay/test.cer',$randStr)//第六步.CFCA公钥加密.加密的数据是第四步生成的AES密钥,防止AES密钥泄露
- );
- if(isset($data['partnerId'])){
- array_push($headerArray,"partnerId:".$data['partnerId']);
- }
- return array('body'=>$body,'header'=>$headerArray,'data'=>json_encode($data));
- }catch (Exception $exception){
- Db::name("log")->insert(array('data'=>$exception->getFile().':'.$exception->getLine().'【'.$exception->getMessage().'】'));//日志记录
- return false;
- }
- }
- /**
- * CFCA公钥加密
- */
- public static function rsaPublicEncode($public_key,$rands): string
- {
- $encryptKey=file_get_contents($public_key);
- $pem = chunk_split(base64_encode($encryptKey),64,"\n");//转换为pem格式的公钥
- $public_key = "-----BEGIN CERTIFICATE-----\n".$pem."-----END CERTIFICATE-----\n";
- $pu_key = openssl_pkey_get_public($public_key);//这个函数可用来判断公钥是否是可用的
- openssl_public_encrypt($rands,$encryptKey,$pu_key);//公钥加密
- $encryptKey = base64_encode($encryptKey);
- return $encryptKey;
- }
- /**
- * CFCA私钥签名
- */
- public static function rsaPrivateSign($data,$path='',$password=''){
- $pubKey = file_get_contents($path);
- $results=array();
- openssl_pkcs12_read($pubKey,$results,$password);
- $private_key=$results['pkey'];
- $pi_key = openssl_pkey_get_private($private_key);//这个函数可用来判断私钥是否是可用的,可用返回资源id Resource id
- openssl_sign($data, $signature,$private_key,"md5");
- $signature=base64_encode($signature);
- return $signature;
- }
- /**
- * 随机字符串
- */
- public static function getRandStr($length){
- //字符组合
- $str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
- $len = strlen($str)-1;
- $randstr = '';
- for ($i=0;$i<$length;$i++) {
- $num=mt_rand(0,$len);
- $randstr .= $str[$num];
- }
- return $randstr;
- }
- /**
- * 统一请求
- * @return bool|string
- * @author php迷途小书童
- * @created 2021/5/13 9:15
- */
- public static function request($data,$url){
- try {
- $data = self::getSign($data);//签名
- Db::name("log")->insert(array('data'=>json_encode($data)));//日志记录
- if(!$data) return false;
- $postUrl = self::posturl($url,$data['body'],$data['header'],$data['data']);
- return self::returnDecode($postUrl);
- } catch (\Throwable $e) {
- return $e->getMessage();
- }
- }
- /**
- * 返回数据解密
- * */
- public static function returnDecode($postUrl){
- //一、CFCA私钥解密
- $res = self::rsaPrivateDecode($postUrl['encryptKey'],App::getRootPath(). 'pkey/5upay/private.pfx','IDajxBO5');//CFCA私钥解密
- //二、AES解密
- $getInfo = Aes::decrypt7($postUrl['data'],$res);
- Db::name("log")->insert(array('data'=>json_encode($getInfo)));//日志记录
- return $getInfo;
- }
- /**
- * CFCA 私钥解密
- * */
- public static function rsaPrivateDecode($encryptKey,$private_key,$password){
- $prikey=file_get_contents($private_key);
- $results=array();
- openssl_pkcs12_read($prikey,$results,$password);
- $private_key=$results['pkey'];
- $pi_key = openssl_pkey_get_public($private_key);
- openssl_private_decrypt(base64_decode($encryptKey),$decrypted,$private_key);
- return $decrypted;
- }
- /**
- * 字符排序
- * @return string
- * @author lin
- * @created 2021/5/13 17:50
- */
- public static function sortArray($para=null)
- {
- // $vars = $para ? '' : get_object_vars($this);
- // unset($vars['response_hmac_fields']);
- $data = array();
- foreach ($para as $k => $var) {
- if (is_scalar($var) && $var !== '' && $var !== null) {
- $data[$k] = $var;
- } else if (is_object($var)) {
- $data[$k] = array_filter((array)$var);
- } else if (is_array($var)) {
- $data[$k] = array_filter($var);
- }
- if (empty($data[$k])) {
- unset($data[$k]);
- }
- }
- ksort($data);
- $hmacSource = '';
- foreach($data as $key => $value){
- if (is_array($value)) {
- ksort($value);
- foreach ($value as $key2 => $value2) {
- if (is_object($value2)) {
- $value2 = array_filter((array)$value2);
- ksort($value2);
- foreach ($value2 as $oKey => $oValue) {
- $oValue .= '#';
- $hmacSource .= trim($oValue);
- }
- } else if(is_array($value2)){
- ksort($value2);
- foreach ($value2 as $key3 => $value3) {
- if (is_object($value3)) {
- $value3 = array_filter((array)$value3);
- ksort($value3);
- foreach ($value3 as $oKey => $oValue) {
- $oValue .= '#';
- $hmacSource .= trim($oValue);
- }
- } else{
- $value3 .= '#';
- $hmacSource .= trim($value3);
- }
- }
- } else{
- $value2 .= '#';
- $hmacSource .= trim($value2);
- }
- }
- } else {
- $value .= '#';
- $hmacSource .= trim($value);
- }
- }
- return $hmacSource;
- }
- public static function getOrderNumber($type){
- list($msec, $sec) = explode(' ', microtime());
- $msectime = number_format((floatval($msec) + floatval($sec)) * 1000, 0, '', '');
- return $type . '_' . $msectime . mt_rand(10000, max(intval($msec * 10000) + 10000, 98369));
- }
- /**
- * @return array
- */
- public static function posturl($url,$body,$headerArray,$data){
- // $json = json_encode($data, JSON_UNESCAPED_UNICODE);
- $num = md5(time().rand(100,1000));
- Db::name("log")->insert(array('data'=>'【'.$url.'】data:'.$data));//日志记录
- Db::name("log")->insert(array('data'=>'【'.$url.'】body:'.json_encode($body)));//日志记录
- Db::name("log")->insert(array('data'=>'【'.$url.'】headerArray:'.json_encode($headerArray)));//日志记录
- $curl = curl_init();
- curl_setopt($curl, CURLOPT_URL, $url);
- curl_setopt($curl,CURLOPT_HEADER, 1 ); // 过滤HTTP头
- curl_setopt($curl,CURLOPT_HTTPHEADER,$headerArray);
- curl_setopt($curl,CURLOPT_RETURNTRANSFER, 1);// 显示输出结果
- curl_setopt($curl,CURLOPT_POST,true); // post传输数据
- curl_setopt($curl,CURLOPT_POSTFIELDS,$body);// post传输数据
- curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);//SSL证书认证
- curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);//严格认证
- $output = curl_exec($curl);
- curl_close($curl);
- Db::name("log")->insert(array('data'=>json_encode($output)));//日志记录
- preg_match_all('/(encryptKey|merchantId|data"):(\s+|")([^"\s]+)/s',$output,$m);
- list($encryptKey, $merchantId, $data) = $m[3];
- $responsedata = array("data" =>$data,"encryptKey"=>$encryptKey,"merchantId"=>$merchantId);
- return $responsedata;
- }
- }
|