微信特约商户进件

/**
     * 特约商户 进件
     * especiallyBusinessApply
     *
     * @param $data
     * @param $uniqid
     *
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @author Tiau Hai
     * @date   2021/11/26 13:49
     */
    public function especiallyBusinessApply($data, $uniqid, $config)
    {
        
        $miniInfo = SystemMemberMiniapp::where(['miniapp_id' => 1])->find();
        
        $configPayment = SystemMemberPayment::config(1, 'wepay'); 
        
        $this->cert_path = Env::get('runtime_path') . 'cert/cert.pem';//证书接口 获取的证书
        $this->key_path  = $configPayment['key_path'];//平台证书 
        
        
        $industryInfo   = db('allwin_industry')->where(['id' => $data['industry_id']])->field('id,name,value,type')->find();
        $contact_name   = $this->getEncrypt($data['id_card_name'], $this->cert_path);
        $id_card_number = $this->getEncrypt($data['id_card_number'], $this->cert_path);
        $service_phone  = $this->getEncrypt($data['service_phone'], $this->cert_path);
        $contact_email  = $this->getEncrypt($data['contact_email'], $this->cert_path);
        //超级管理员 信息
        $contact_info      = [
            'contact_name'      => $contact_name,
            'contact_id_number' => $id_card_number,
            'mobile_phone'      => $service_phone,
            'contact_email'     => $contact_email,
        ];
        $card_period_begin = strtotime($data['card_period_begin']);
        $card_period_begin = date('Y-m-d', $card_period_begin);
        $card_period_end   = strtotime($data['card_period_end']);
        $card_period_end   = empty($card_period_end) ? '长期' : date('Y-m-d', $card_period_end);
        
        if($data['card_period_end'] != '长期')
        {
        
        }
        //主体资料
        $subject_info = [
            'subject_type'          => $data['type'],
            'business_license_info' => [
                'license_copy'   => $data['storeMedia_id'],
                'license_number' => $data['license_number'],
                'merchant_name'  => $data['merchant_name'],
                'legal_person'   => $data['id_card_name'],
            ],
            'identity_info'         => [
                'id_doc_type'  => 'IDENTIFICATION_TYPE_IDCARD',
                'id_card_info' => [
                    'id_card_copy'      => $data['idcardFaceMedia_id'],
                    'id_card_national'  => $data['idcardBackMedia_id'],
                    'id_card_name'      => $this->getEncrypt($data['id_card_name'], $this->cert_path),
                    'id_card_number'    => $this->getEncrypt($data['id_card_number'], $this->cert_path),
                    'card_period_begin' => $card_period_begin,
                    'card_period_end'   => $card_period_end,
                ],
                'owner'        => true
            ],
        
        ];
        
        //经营资料
        $business_info = [
            'merchant_shortname' => $data['merchant_shortname'],
            'service_phone'      => $data['service_phone'],
            'sales_info'         => [
                'sales_scenes_type' => ['SALES_SCENES_MINI_PROGRAM'],//SALES_SCENES_MP 公众号
                /*'mp_info'           => [
                    'mp_appid' => $miniInfo->psp_appid//服务商 公众号appid
                ],*/
                'mini_program_info' => [
                    'mini_program_appid' => $miniInfo->miniapp_appid //服务商 小程序appid
                ]
            ]
        ];
        
        //结算规则
        $settlement_info = [
            'settlement_id'      => json_encode($industryInfo['value']),
            'qualification_type' => $industryInfo['name']
        ];
        $account_name    = $industryInfo['type'] == 'BANK_ACCOUNT_TYPE_PERSONAL' ? $data['id_card_name'] : $data['merchant_name'];
        //结算银行账户
        $bank_account_info = [
            'bank_account_type' => $data['bank_account_type'],
            'account_name'      => $this->getEncrypt($account_name, $this->cert_path),
            'account_bank'      => $data['account_bank'],
            'bank_address_code' => $data['bank_address_code'],
            'bank_name'         => $data['bank_name'],
            'account_number'    => $this->getEncrypt($data['account_number'], $this->cert_path),
        ];
        
        
        $incomingData = [
            'business_code'     => $uniqid,
            'contact_info'      => $contact_info,
            'subject_info'      => $subject_info,
            'business_info'     => $business_info,
            'settlement_info'   => $settlement_info,
            'bank_account_info' => $bank_account_info,
        ];
        $url          = 'https://api.mch.weixin.qq.com/v3/applyment4sub/applyment/';
        
        $mch_private_key = $this->getPrivateKey($this->key_path);
        
        $serial_no = config('serial_no');//证书序列号 商户后台获取
        
        $timestamp = time();
        $nonce     = $this->randomkeys(18);
        $sign      = $this->sign($url, 'POST', $timestamp, $nonce, json_encode($incomingData), $mch_private_key, $config['mch_id'], $serial_no);//进行签名操作
        
        $headers = [
            'Authorization:WECHATPAY2-SHA256-RSA2048 ' . $sign,//签名
            'Accept:application/json',
            'User-Agent:' . $config['mch_id'],//服务商的商户号
            'Content-Type:application/json',
            'Wechatpay-Serial:' . $this->getCertificate($config['mch_id'], $serial_no, $this->key_path)//获取平台证书的序列号,注意:是平台证书,不是上文的商户证书序列号
        ];
        
        $ret = $this->curl($url, json_encode($incomingData), $headers);
        
        return json_decode($ret, true);
        
    }


    /**
     * 上传图片到微信并获取微信的media_id 这里用的是EasyWeChat插件进行上传的 
     * applyMerchant
     *
     * @param $url
     *
     * @return mixed|string
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidSignException
     * @author Tiau Hai
     * @date   2021/11/25 9:59
     */
    public function applyMerchant($url)
    {
        $app      = $this->config();
        $path     = $url;
        $ret      = $app->media->upload($path);//上传到微信服务器的 图片
        $media_id = '';
        if($ret['return_code'] == 'SUCCESS')
        {
            $media_id = $ret['media_id'];//返回成功 获取文件返回的 media_id
        }
        return $media_id;
    }
    
    /**
     * EasyWeChat 微信上传图片配置
     * config
     * @return \EasyWeChat\MicroMerchant\Application
     * @author Tiau Hai
     * @date   2021/11/25 9:59
     */
    public function config()
    {
        $config = SystemMemberPayment::config(1, 'wepay');
        $config = [
            // 必要配置
            'mch_id'        => $config['mch_id'], // 服务商的商户号
            'key'           => $config['key'], // API 密钥
            //'apiv3_key'     => 'APIv3-key-for-signature', // APIv3 密钥
            // API 证书路径(登录商户平台下载 API 证书)
            'cert_path'     => $config['cert_path'], // XXX: 绝对路径!!!!
            'key_path'      => $config['key_path'], // XXX: 绝对路径!!!!
            // 以下两项配置在获取证书接口时可为空,在调用入驻接口前请先调用获取证书接口获取以下两项配置,如果获取过证书可以直接在这里配置,也可参照本文档获取平台证书章节中示例
            // 'serial_no'     => '获取证书接口获取到的平台证书序列号',
            // 'certificate'   => '获取证书接口获取到的证书内容'
            
            // 以下为可选项
            // 指定 API 调用返回结果的类型:array(default)/collection/object/raw/自定义类名
            'response_type' => 'array',
            'appid'         => '*******' // 服务商的公众账号 ID
        ];
        
        $app = Factory::microMerchant($config);
        return $app;
    }
    
   

    
    /**
     * 敏感词 非对称加密
     * getEncrypt
     *
     * @param $str
     *
     * @return string
     * @author Tiau Hai
     * @date   2021/11/25 15:35
     */
    public function getEncrypt($str, $public_key_path)
    {
        
        $public_key = file_get_contents($public_key_path);
        
        $encrypted = '';
        if(openssl_public_encrypt($str, $encrypted, $public_key, OPENSSL_PKCS1_OAEP_PADDING))
        {
            //base64编码
            $sign = base64_encode($encrypted);
        }
        else
        {
            throw new Exception('encrypt failed');
        }
        return $sign;
    }
    
    /**
     * 获取随机数
     * randomkeys
     *
     * @param $length
     *
     * @return string
     * @author Tiau Hai
     * @date   2021/11/25 15:35
     */
    public function randomkeys($length)
    {
        $returnStr = '';
        $pattern   = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        for ($i = 0; $i < $length; $i++)
        {
            $returnStr .= $pattern{mt_rand(0, 61)};
        }
        return $returnStr;
    }
    
   
   
    /**
     * 获取微信加密参数
     * makeSignature
     *
     * @param $args
     * @param $key
     *
     * @return string
     * @author Tiau Hai
     * @date   2021/11/25 15:36
     */
    public function makeSignature($args, $key)
    {
        ksort($args);
        $stringA        = '';
        $stringSignTemp = '';
        foreach ($args as $k => $v)
        {
            $stringA .= $k . '=' . $v . '&';
        }
        $stringSignTemp = $stringA . 'key=' . $key;
        
        $signature = strtoupper(hash_hmac('SHA256', $stringSignTemp, $key));
        return $signature;
    }
    
    /**
     * 微信商户进件加密
     * sign
     *
     * @param $url
     * @param $http_method
     * @param $timestamp
     * @param $nonce
     * @param $body
     * @param $mch_private_key
     * @param $merchant_id
     * @param $serial_no
     *
     * @return string
     * @author Tiau Hai
     * @date   2021/11/25 15:48
     */
    public function sign($url, $http_method, $timestamp, $nonce, $body, $mch_private_key, $merchant_id, $serial_no = null)
    {
        $url_parts     = parse_url($url);
        $canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
        $message       =
            $http_method . "\n" .
            $canonical_url . "\n" .
            $timestamp . "\n" .
            $nonce . "\n" .
            $body . "\n";
        
        openssl_sign($message, $raw_sign, $mch_private_key, 'sha256WithRSAEncryption');
        
        $sign   = base64_encode($raw_sign);
        $schema = 'WECHATPAY2-SHA256-RSA2048';
        $token  = sprintf(
            'mchid="%s",nonce_str="%s",signature="%s",timestamp="%d",serial_no="%s"',
            $merchant_id,
            $nonce,
            $sign,
            $timestamp,
            $serial_no
        );
        return $token;
    }
    
    /**
     *
     * 获取证书接口
     * 先执行此接口 因为所有加密要用到的证书 都是基于此证书 除开签名加密
     * getCertificate
     * @param $merchant_id
     * @param $serial_no
     * @param $mch_private_key
     *
     * @return mixed
     * @author Tiau Hai
     * @date   2021/11/26 14:34
     */
    //public function getzhengshu($merchant_id, $serial_no, $mch_private_key)
    public function getCertificate($merchant_id, $serial_no, $mch_private_key)
    {
        $url       = "https://api.mch.weixin.qq.com/v3/certificates";//获取地址
        $timestamp = time();//时间戳
        $nonce     = $this->randomkeys(16);//获取一个随机字符串
        $body      = "";
        
        $mch_private_key = $this->getPrivateKey($mch_private_key); //调用获取商户私钥方法传证书文件路径进去
        
        
        //$merchant_id = '******'; //服务商商户号
        //$serial_no = '*********'; //服务商证书序列号
        $sign   = $this->sign($url, 'GET', $timestamp, $nonce, $body, $mch_private_key, $merchant_id, $serial_no);
        $header = [
            'Authorization:WECHATPAY2-SHA256-RSA2048 ' . $sign,
            'Accept:application/json',
            'User-Agent:' . $merchant_id
        ];
        
        
        $result = $this->curl($url, '', $header, 'GET');
        
        $result = json_decode($result, true);
        
        $serial_no           = $result['data'][0]['serial_no'];//获取的平台证书序列号
        $encrypt_certificate = $result['data'][0]['encrypt_certificate'];
        
        $sign_key = config('wx_a3');  //APIv3密钥,商户平台API安全中获取
        
        $result = $this->decryptToString($encrypt_certificate['associated_data'], $encrypt_certificate['nonce'], $encrypt_certificate['ciphertext'], $sign_key);
        
        $path = Env::get('runtime_path');
        
        //$path = $path ;//组装 文件日志文件
        file_put_contents($path . 'cert/cert.pem', $result);//获取的文件临时保存到服务器
        
        return $serial_no;//返回平台证书序列号
    }
    
    /**
     * 解密证书
     * decryptToString
     * @param $associatedData
     * @param $nonceStr
     * @param $ciphertext
     * @param $aesKey
     *
     * @return false|string
     * @throws \SodiumException
     * @author Tiau Hai
     * @date   2021/11/26 14:34
     */
    public function decryptToString($associatedData, $nonceStr, $ciphertext, $aesKey)
    {
        $ciphertext = \base64_decode($ciphertext);
        if(function_exists('\sodium_crypto_aead_aes256gcm_is_available') && \sodium_crypto_aead_aes256gcm_is_available())
        {
            return \sodium_crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $aesKey);
        }
        if(PHP_VERSION_ID >= 70100 && in_array('aes-256-gcm', \openssl_get_cipher_methods()))
        {
            $ctext   = substr($ciphertext, 0, -16);
            $authTag = substr($ciphertext, -16);
            return \openssl_decrypt(
                $ctext,
                'aes-256-gcm',
                $aesKey,
                \OPENSSL_RAW_DATA,
                $nonceStr,
                $authTag,
                $associatedData
            );
        }
        throw new \RuntimeException('php7.1');
    }
    
    /**
     * curl
     * @param        $url
     * @param array  $data
     * @param        $header
     * @param string $method
     *
     * @return bool|string
     * @author Tiau Hai
     * @date   2021/11/26 14:34
     */
    public function curl($url, $data = [], $header, $method = 'POST')
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
        curl_setopt($curl, CURLOPT_HEADER, false);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        if($method == "POST")
        {
            curl_setopt($curl, CURLOPT_POST, true);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }
        $result = curl_exec($curl);
        curl_close($curl);
        return $result;
    }
    
    /**
     * getPrivateKey
     *
     * @param $path
     *
     * @return false|resource
     * @author Tiau Hai
     * @date   2021/11/25 16:34
     */
    public static function getPrivateKey($path)
    {
        return openssl_get_privatekey(file_get_contents($path));//商户平台API安全证书中下载,保存到服务器
        
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值