<?php
namespace app\ais\event;

use app\common\model\SystemMemberPayment;
use EasyWeChat\Factory;

class Micro
{
    protected static $mch_id;   //商户号
    protected static $mch_key;   //32位密钥
    protected static $mch_private_key;  //商户私钥
    protected static $wechat_serial_no;  //  平台证书序列号
    protected static $serial_no = '275E949C1475DFCE8DDBEB5AC195D9DFABF48906';  //  商户证书序列号
    protected static $apiv3_key = '37Qx18rqjVVAWPXnuMSsL7hqbsxMFLSr';  //  APIv3 密钥
    protected static $wechat_cert;  //  平台证书

    //初始化配置
    public static function config(int $miniapp_id,$flag = false){
        $config = SystemMemberPayment::config($miniapp_id,'wepay');
        if(empty($config)) return;
        self::$mch_id = $config['mch_id'];
        self::$mch_key = $config['key'];
        self::$mch_private_key = self::getPrivateKey($config['key_path']);
        //如果需要,ture为获取平台证书
        if($flag){
            $data = [
                // 必要配置
                'mch_id'           => $config['mch_id'], // 服务商的商户号
                'key'              => $config['key'], // API 密钥
                'apiv3_key'        => self::$apiv3_key, // APIv3 密钥
                'cert_path'        => $config['cert_path'], // XXX: 绝对路径！！！！
                'key_path'         => $config['key_path'], // XXX: 绝对路径！！！！
            ];
            $response = Factory::microMerchant($data)->certficates->get();
            self::$wechat_cert = $response['certificates'];
            self::$wechat_serial_no =  $response['serial_no'];
        }
    }

    //获取商户私钥
    public static function getPrivateKey($key){
        return  openssl_get_privatekey(file_get_contents($key));
    }

    //签名
    public static function sign($url,$http_mothod,$timestamp,$nonce,$body,$mch_private_key,$merchant_id,$serial_no){
        $url_parts = parse_url($url);
        $canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
        $message =
            $http_mothod . "\n".
            $canonical_url . "\n".
            $timestamp . "\n".
            $nonce . "\n".
            $body . "\n";
        openssl_sign($message,$raw_sign,$mch_private_key,'sha256WithRSAEncryption');
        $sign = base64_encode($raw_sign);
        $token = sprintf('mchid="%s",nonce_str="%s",signature="%s",timestamp="%d",serial_no="%s"', $merchant_id,$nonce,$sign,$timestamp,$serial_no);
        return $token;
    }

    //发送请求
    protected static function curl($url,$data = [],$sign,$method = "POST"){
        //设置header头
        $header = [
            'Accept:application/json',
            'User-Agent:'.self::$mch_id,
            'Authorization:WECHATPAY2-SHA256-RSA2048 ' . $sign,
            'Content-Type:application/json',
            'Wechatpay-Serial:' . self::$wechat_serial_no ?? self::$serial_no,
        ];
        $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;
    }

    //加密
    private static function getEncrypt($str){
        //$str是待加密字符串
        $encrypted = '';
        if (openssl_public_encrypt($str,$encrypted,self::$wechat_cert,OPENSSL_PKCS1_OAEP_PADDING)) {
            //base64编码
            $sign = base64_encode($encrypted);
        } else {
            throw new \Exception('encrypt failed');
        }
        return $sign;
    }

    //随机字符串
    public static function nonce_str(){
        return date('YmdHis',time().rand(10000,99999));
    }


    /**
     * 上传图片到微信服务器
     * @param integer $appid   来源小程序
     * @return void
     */
    public static function uploadMedia(int $miniapp_id,string $filename){
        self::config($miniapp_id);
        $url = 'https://api.mch.weixin.qq.com/v3/merchant/media/upload';
        $fi = new \finfo(FILEINFO_MIME_TYPE);
        $mime_type = $fi->file($filename);
        $data['filename'] = pathinfo($filename, PATHINFO_BASENAME);
        $meta['filename'] = pathinfo($filename, PATHINFO_BASENAME);
        $meta['sha256'] = hash_file('sha256', $filename);
        $boundary = uniqid(); //分割符号
        $sign = self::sign($url,'POST',time(),self::nonce_str(),json_encode($meta),self::$mch_private_key,self::$mch_id,self::$serial_no);//$http_method要大写
        $header[] = 'User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36';
        $header[] = 'Accept:application/json';
        $header[] = 'Authorization:WECHATPAY2-SHA256-RSA2048 '.$sign;
        $header[] = 'Content-Type:multipart/form-data;boundary='.$boundary;
        $boundaryStr = "--{$boundary}\r\n";
        $out = $boundaryStr;
        $out .= 'Content-Disposition: form-data; name="meta"'."\r\n";
        $out .= 'Content-Type: application/json'."\r\n";
        $out .= "\r\n";
        $out .= json_encode($meta)."\r\n";
        $out .=  $boundaryStr;
        $out .= 'Content-Disposition: form-data; name="file"; filename="'.$data['filename'].'"'."\r\n";
        $out .= 'Content-Type: '.$mime_type.';'."\r\n";
        $out .= "\r\n";
        $out .= file_get_contents($filename)."\r\n";
        $out .= "--{$boundary}--\r\n";
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        //避免https 的ssl验证
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSLVERSION, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $out);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        // 模拟来源
        curl_setopt($ch, CURLOPT_REFERER, "");
        $response = curl_exec($ch);
        if ($error = curl_error($ch)) {
            return $error;
        }
        curl_close($ch);
        return $response;
    }
    //进件
    public static function submit($miniapp_id,$params){
        self::config($miniapp_id,true);
        $params['contact_info']['contact_name'] = self::getEncrypt($params['contact_info']['contact_name']);
        $params['contact_info']['contact_id_number'] = self::getEncrypt($params['contact_info']['contact_id_number']);
        $params['contact_info']['mobile_phone'] = self::getEncrypt($params['contact_info']['mobile_phone']);
        $params['contact_info']['contact_email'] = self::getEncrypt($params['contact_info']['contact_email']);
        $params['bank_account_info']['account_number'] = self::getEncrypt($params['bank_account_info']['account_number']);
        $params['bank_account_info']['account_name'] = self::getEncrypt($params['bank_account_info']['account_name']);
        $params['subject_info']['identity_info']['id_card_info']['id_card_name'] = self::getEncrypt($params['subject_info']['identity_info']['id_card_info']['id_card_name']);
        $params['subject_info']['identity_info']['id_card_info']['id_card_number'] = self::getEncrypt($params['subject_info']['identity_info']['id_card_info']['id_card_number']);
        if($params['subject_info']['identity_info']['owner'] == 1){
            $params['subject_info']['identity_info']['owner'] = true;
        }else{
            $params['subject_info']['identity_info']['owner'] = false;
        }
        $url    = 'https://api.mch.weixin.qq.com/v3/applyment4sub/applyment/';
        $sign   = self::sign($url, 'POST', time(), self::nonce_str(), json_encode($params), self::$mch_private_key, self::$mch_id, self::$serial_no);
        $result = self::curl($url, json_encode($params), $sign);
        return json_decode($result,true);
    }

    //查询进件
    public static function query($miniapp_id,$no){
        self::config($miniapp_id);
        $url    = 'https://api.mch.weixin.qq.com/v3/applyment4sub/applyment/business_code/' . $no;
        $sign   = self::sign($url, 'GET', time(), self::nonce_str(), '', self::$mch_private_key, self::$mch_id, self::$serial_no);
        $result = self::curl($url, '', $sign, 'GET');
        return json_decode($result,true);
    }

    //修改结算帐号
    public static function modify($miniapp_id,$params){
        self::config($miniapp_id,true);
        $params['account_number'] = self::getEncrypt($params['account_number']);
        $url    = sprintf('https://api.mch.weixin.qq.com/v3/apply4sub/sub_merchants/%s/modify-settlement', $params['sub_mchid']);
        $sign   = self::sign($url, 'POST', time(), self::nonce_str(), json_encode($params), self::$mch_private_key, self::$mch_id, self::$serial_no);
        $result = self::curl($url, json_encode($params), $sign);
        return json_decode($result,true);
    }

    //查询结算账户
    public static function settlement($miniapp_id,$sub_mchid){
        self::config($miniapp_id);
        $url    = sprintf('https://api.mch.weixin.qq.com/v3/apply4sub/sub_merchants/%s/settlement', $sub_mchid);
        $sign   = self::sign($url, 'GET', time(), self::nonce_str(), '', self::$mch_private_key, self::$mch_id, self::$serial_no);
        $result = self::curl($url, '', $sign, 'GET');
        return json_decode($result,true);
    }
}