<?php

namespace app\controller;


use think\facade\Db;
use think\facade\Log;

class WechatReimburse
{
    //微信支付
    const KEY_LENGTH_BYTE = 32;
    const AUTH_TAG_LENGTH_BYTE = 16;

    //用户余额退款
    public function Refund($transaction_id, $openid, $refundAmount, $OriginalOrderAmount)
    { //商户订单号,微信生成的退款订单号 二选一即可
        $file = file_get_contents(__DIR__ . config('wx.apiclientKey'));
        $mch_private_key = openssl_get_privatekey($file);

        $time = time();
        $out_refund_no = $this->generate_tuikuan(6);
        $refundData = [
            'transaction_id' => $transaction_id,
            'out_refund_no' => $out_refund_no,
            'reason' => '余额退款',
            'notify_url' => 'https://' . $_SERVER['HTTP_HOST'] . '/refund_notify',
            'funds_account' => 'AVAILABLE',
            'amount' => [
                'refund' => floor($refundAmount * 100), //退款标价金额，单位为分，可以做部分退款
                'total' => $OriginalOrderAmount * 100, //订单总金额，单位为分
                'currency' => 'CNY'
            ]
        ];
//        if(!$transaction_id){ //商户订单号,微信生成的退款订单号 二选一即可
//            if(!$out_trade_no){
//                return ['code'=>0,'msg'=>'退款订单号不能为空'];
//            }else{
//                $refundData['out_trade_no']=$out_trade_no;
//            }
//        }else{
//            $refundData['transaction_id']=$transaction_id;
//        }
        $url = 'https://api.mch.weixin.qq.com/v3/refund/domestic/refunds';
        $url_parts = parse_url($url); //拆解为：[scheme=>https,host=>api.mch.weixin.qq.com,path=>/v3/pay/transactions/native]
        $mchid = config('wx.merchantId');//商户ID
        $xlid = config('wx.merchantSerialNumber');//证书序列号
        $refundData = json_encode($refundData);
        $nonce = date('YmdHis', time()) . rand(1000, 9999);
        $canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
//        $key = $this->getSign($refundData,$urlarr['path'],$nonce,$time);
        $message = 'POST' . "\n" .
            $canonical_url . "\n" .
            $time . "\n" .
            $nonce . "\n" .
            $refundData . "\n";
        openssl_sign($message, $signature, $mch_private_key, "sha256WithRSAEncryption");
        $sign = base64_encode($signature);
        $schema = 'WECHATPAY2-SHA256-RSA2048';
        $token = sprintf('mchid="%s",serial_no="%s",nonce_str="%s",timestamp="%d",signature="%s"', $mchid, $xlid, $nonce, $time, $sign);
        $header = "Authorization: " . $schema . " " . $token;
//        $header  = array(
//            'Accept: application/json',
//            'Content-Type: application/json',
//            'User-Agent:*/*',
//            'Authorization: WECHATPAY2-SHA256-RSA2048 '.$token
//        );
        $res = $this->http_post($url, $header, $refundData);
         Db::table('charge_logo')->save(['name' => '余额提现', 'mark' => $res]);
        $res_array = json_decode($res, true);
//        dd($res_array);
        if (isset($res_array['status']) && ($res_array['status'] == 'PROCESSING' || $res_array['status'] == 'SUCCESS')) {

            $kk['openid'] = $openid;
            $create_time = $res_array['create_time'];
            $create_time = str_replace('T', ' ', $create_time);
            $create_time = substr($create_time, 0, -6);

            $kk = [
                'openid' => $openid,
                'create_time' => $create_time,
                'out_trade_no' => $res_array['out_trade_no'],
                'out_refund_no' => $res_array['out_refund_no'],
                'refund_id' => $res_array['refund_id'],
                'status' => $res_array['status'],
                'transaction_id' => $res_array['transaction_id'],
                'user_received_account' => $res_array['user_received_account'],
                'refund_total' => $res_array['amount']['refund'],
            ];
            $table = 'zxc_refund';
            $table_recharge = 'zxc_recharge';


            $table_user = 'zxc_user';
            Db::transaction(function () use ($table_recharge, $res_array, $openid, $table_user, $kk, $table) {
                Db::table($table)->save($kk);
                Db::table($table_user)->where('openid', $openid)
                    ->update([
                        'account' => Db::raw('account-' . ($res_array['amount']['refund'] / 100)),
                    ]);


                Db::table($table_recharge)->where('out_trade_no', $res_array['out_trade_no'])->update(['total_used' => Db::raw('total_used+' . ($res_array['amount']['refund']))]);
            });

            return ['code' => 200, 'msg' => '退款受理成功'];
        } else {
            return ['code' => 1, 'msg' => $res_array['message']];
        }
    }

    //退款回调地址
    public function refund_notify()
    {
        try {
            //code...

            $header = $this->getHeaders(); //读取http头信息  见下文
            $body = file_get_contents('php://input'); //读取微信传过来的信息，是一个json字符串

            if (empty($header) || empty($body)) {
                throw new \Exception('通知参数为空', 2001);
            }

            $timestamp = $header['WECHATPAY-TIMESTAMP'];
            $nonce = $header['WECHATPAY-NONCE'];
            $signature = $header['WECHATPAY-SIGNATURE'];
            $serialNo = $header['WECHATPAY-SERIAL'];
            if (empty($timestamp) || empty($nonce) || empty($signature) || empty($serialNo)) {
                throw new \Exception('通知头参数为空', 2002);
            }
            $cert = $this->getzhengshuDb(1);

            if ($cert != $serialNo) {
                throw new \Exception('验签失败', 2005);
            }
            $message = "$timestamp\n$nonce\n$body\n";

            //校验签名
            if (!$this->verify($message, $signature, __DIR__ . config('wx.pingtai_public_key_path'))) {
                throw new \Exception('验签失败', 2005);
            }

            $decodeBody = json_decode($body, true);
            if (empty($decodeBody) || !isset($decodeBody['resource'])) {
                throw new \Exception('通知参数内容为空', 2003);
            }
            $decodeBodyResource = $decodeBody['resource'];
            $decodeData_res = $this->decryptToString($decodeBodyResource['associated_data'], $decodeBodyResource['nonce'], $decodeBodyResource['ciphertext'], ''); //解密resource
            $decodeData = json_decode($decodeData_res, true);
            Db::table('charge_logo')->save(['name' => '余额提现回调', 'mark' => $decodeData]);
            Log::error('余额提现：        ' . $decodeData);
            //返回结果格式
            //array (
            //   'mchid' => 'xxx',
            //   'appid' => 'xxxxxxx',
            //   'out_trade_no' => '1217752501201407033233368026',
            //   'transaction_id' => '4200001336202201037507057791',
            //   'trade_type' => 'NATIVE',
            //   'trade_state' => 'SUCCESS',
            //   'trade_state_desc' => '支付成功',
            //   'bank_type' => 'OTHERS',
            //   'attach' => '',
            //   'success_time' => '2022-01-03T19:43:05+08:00',
            //   'payer' =>
            //   array (
            //     'openid' => 'ovs326bgwfA4o8jlFQXMEma2JZek',
            //   ),
            //   'amount' =>
            //   array (
            //     'total' => 1,
            //     'payer_total' => 1,
            //     'currency' => 'CNY',
            //     'payer_currency' => 'CNY',
            //   ),
            // )
            //执行自己的代码start
            $out_refund_no = $decodeData['out_refund_no'];
            $openid = Db::table('zxc_refund')->where('out_refund_no', $out_refund_no)->value('openid');

            $table = 'zxc_refund';
            $table_user = 'zxc_user';
            $kk['status'] = $decodeData['refund_status'];
            if ($decodeData['refund_status'] == 'SUCCESS') {
                $success_time = $decodeData['success_time'];
                $success_time = str_replace('T', ' ', $success_time);
                $success_time = substr($success_time, 0, -6);
                $kk['success_time'] = $success_time;
                Db::table($table_user)->where('openid', $openid)->update(['FrozenAccount' => Db::raw('FrozenAccount-' . ($decodeData['amount']['refund'] / 100))]);
            }
            Db::table($table)->where('out_refund_no', $out_refund_no)->save($kk);


            \app\model\User::addMoneyLog($openid, $decodeData['amount']['refund'], 3, '用户提现');

//            $order_info  = Db::table($table)->save($data);
//            Db::table($table_user)->where('openid',$openid)->update(['account'	=>	Db::raw('account+'.($total/100))]);
            //执行自己的代码end

            $arr = array("code" => "SUCCESS", "message" => "");
            echo json_encode($arr);

        } catch (\Exception $e) {
            Log::error($e->getMessage());
            $arr = array("code" => "ERROR", "message" => $e->getMessage());
            echo json_encode($arr);
        }


//        $notifiedData = file_get_contents('php://input');
//        $data = json_decode($notifiedData, true);
//        $nonceStr = $data['resource']['nonce'];
//        $associatedData = $data['resource']['associated_data'];
//        $ciphertext = $data['resource']['ciphertext'];
//        $ciphertext = base64_decode($ciphertext);
//        //php>7.1,为了使用这个扩展，你必须将extension=php_sodium.dll添加到php.ini
//        if (function_exists('\sodium_crypto_aead_aes256gcm_is_available') && \sodium_crypto_aead_aes256gcm_is_available()) {
//            //$APIv3_KEY就是在商户平台后端设置是APIv3秘钥
//            $orderData = \sodium_crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $this->config['apiv3_private_key']);
//            $orderData = json_decode($orderData, true);
//            if ($orderData['refund_status']=='SUCCESS'){
//                $transaction_id=$orderData['transaction_id']; //退款单号
//
//                /*业务处理*/
//                return json(['code'=>'SUCCESS','message'=>'成功']);
//            }
//        }
    }


    //    预充电余额退款
    public function Refund2($charge_id, $openid, $refundAmount, $OriginalOrderAmount, $out_trade_no)
    { //商户订单号,微信生成的退款订单号 二选一即可
        $file = file_get_contents(__DIR__ . config('wx.apiclientKey'));
        $mch_private_key = openssl_get_privatekey($file);

        $time = time();
        $out_refund_no = $this->generate_tuikuan(6);
        $refundData = [
            'out_trade_no' => $out_trade_no,
            'out_refund_no' => $out_refund_no,
            'reason' => '预充电余额退款',
            'notify_url' => 'https://' . $_SERVER['HTTP_HOST'] . '/refund_notify2',
            'funds_account' => 'AVAILABLE',
            'amount' => [
                'refund' => floor($refundAmount * 100), //退款标价金额，单位为分，可以做部分退款
                'total' => $OriginalOrderAmount * 100, //订单总金额，单位为分
                'currency' => 'CNY'
            ]
        ];

        $url = 'https://api.mch.weixin.qq.com/v3/refund/domestic/refunds';
        $url_parts = parse_url($url); //拆解为：[scheme=>https,host=>api.mch.weixin.qq.com,path=>/v3/pay/transactions/native]
        $mchid = config('wx.merchantId');//商户ID
        $xlid = config('wx.merchantSerialNumber');//证书序列号
        $refundData = json_encode($refundData);
        $nonce = date('YmdHis', time()) . rand(1000, 9999);
        $canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
//        $key = $this->getSign($refundData,$urlarr['path'],$nonce,$time);
        $message = 'POST' . "\n" .
            $canonical_url . "\n" .
            $time . "\n" .
            $nonce . "\n" .
            $refundData . "\n";
        openssl_sign($message, $signature, $mch_private_key, "sha256WithRSAEncryption");
        $sign = base64_encode($signature);
        $schema = 'WECHATPAY2-SHA256-RSA2048';
        $token = sprintf('mchid="%s",serial_no="%s",nonce_str="%s",timestamp="%d",signature="%s"', $mchid, $xlid, $nonce, $time, $sign);
        $header = "Authorization: " . $schema . " " . $token;

        $res = $this->http_post($url, $header, $refundData);
        $res_array = json_decode($res, true);


        if (isset($res_array['status']) && ($res_array['status'] == 'PROCESSING' || $res_array['status'] == 'SUCCESS')) {

            $info = Db::table('zxc_charge_order')
                ->where('order_id', $charge_id)->where('is_wind', 0)->find();
            if ($info) {
                Db::table('zxc_charge_order')
                    ->where('order_id', $charge_id)
                    ->update([
                        'directly_refund_no' => $out_refund_no,
                        'directly_refund_status' => 1,
                        'directly_refund_amount' => $res_array['amount']['refund'],
                        'directly_refund_time' => time(),
                        'is_wind' => 1
                    ]);
                    
                    
                    $create_time = $res_array['create_time'];
                    $create_time = str_replace('T', ' ', $create_time);
                    $create_time = substr($create_time, 0, -6);
                    Db::table('zxc_refund')
                        ->save([
                            'openid' => $openid,
                            'create_time' => $create_time,
                            'out_trade_no' => $res_array['out_trade_no'],
                            'out_refund_no' => $res_array['out_refund_no'],
                            'refund_id' => $res_array['refund_id'],
                            'status' => $res_array['status'],
                            'transaction_id' => $res_array['transaction_id'],
                            'user_received_account' => $res_array['user_received_account'],
                            'refund_total' => $res_array['amount']['refund'],
                        ]);
                    

                \app\model\User::addMoneyLog($openid, $res_array['amount']['refund']/100, 3, '用户使用即充即退-退款');
            }

            return ['code' => 200, 'msg' => '退款受理成功'];
        } else {
            return ['code' => 1, 'msg' => $res_array['message']];
        }
    }

    //退款回调地址
    public function refund_notify2()
    {
        try {
            //code...

            $header = $this->getHeaders(); //读取http头信息  见下文
            $body = file_get_contents('php://input'); //读取微信传过来的信息，是一个json字符串

            if (empty($header) || empty($body)) {
                throw new \Exception('通知参数为空', 2001);
            }

            $timestamp = $header['WECHATPAY-TIMESTAMP'];
            $nonce = $header['WECHATPAY-NONCE'];
            $signature = $header['WECHATPAY-SIGNATURE'];
            $serialNo = $header['WECHATPAY-SERIAL'];
            if (empty($timestamp) || empty($nonce) || empty($signature) || empty($serialNo)) {
                throw new \Exception('通知头参数为空', 2002);
            }
            $cert = $this->getzhengshuDb(1);

            if ($cert != $serialNo) {
                throw new \Exception('验签失败', 2005);
            }
            $message = "$timestamp\n$nonce\n$body\n";

            //校验签名
            if (!$this->verify($message, $signature, __DIR__ . config('wx.pingtai_public_key_path'))) { //$this->pingtai_public_key_path是获取平台证书序列号$this->getzhengshuDb()时保存下来的平台公钥文件
                throw new \Exception('验签失败', 2005);
            }

            $decodeBody = json_decode($body, true);
            if (empty($decodeBody) || !isset($decodeBody['resource'])) {
                throw new \Exception('通知参数内容为空', 2003);
            }
            $decodeBodyResource = $decodeBody['resource'];
            $decodeData_res = $this->decryptToString($decodeBodyResource['associated_data'], $decodeBodyResource['nonce'], $decodeBodyResource['ciphertext'], ''); //解密resource
            $decodeData = json_decode($decodeData_res, true);
            Log::error('用户使用即充即退退款：           ' . $decodeData_res);
            //返回结果格式
            //array (
            //   'mchid' => 'xxx',
            //   'appid' => 'xxxxxxx',
            //   'out_trade_no' => '1217752501201407033233368026',
            //   'transaction_id' => '4200001336202201037507057791',
            //   'trade_type' => 'NATIVE',
            //   'trade_state' => 'SUCCESS',
            //   'trade_state_desc' => '支付成功',
            //   'bank_type' => 'OTHERS',
            //   'attach' => '',
            //   'success_time' => '2022-01-03T19:43:05+08:00',
            //   'payer' =>
            //   array (
            //     'openid' => 'ovs326bgwfA4o8jlFQXMEma2JZek',
            //   ),
            //   'amount' =>
            //   array (
            //     'total' => 1,
            //     'payer_total' => 1,
            //     'currency' => 'CNY',
            //     'payer_currency' => 'CNY',
            //   ),
            // )
            //执行自己的代码start
            $out_refund_no = $decodeData['out_refund_no'];


           

            $arr = array("code" => "SUCCESS", "message" => "");
            echo json_encode($arr);

        } catch (\Exception $e) {
            Log::error($e->getMessage());
            $arr = array("code" => "ERROR", "message" => $e->getMessage());
            echo json_encode($arr);
        }

    }


    private function verify($message, $signature, $merchantPublicKey)
    {
        if (!in_array('sha256WithRSAEncryption', \openssl_get_md_methods(true))) {
            throw new \RuntimeException("当前PHP环境不支持SHA256withRSA");
        }
        $signature = base64_decode($signature);
        $a = openssl_verify($message, $signature, $this->getWxPublicKey($merchantPublicKey), 'sha256WithRSAEncryption');
        return $a;
    }

    public function getNonceStr()
    {
        $strs = "QWERTYUIOPASDFGHJKLZXCVBNM1234567890";
        $name = substr(str_shuffle($strs), mt_rand(0, strlen($strs) - 11), 32);
        return $name;
    }

    private function getzhengshuDb($getNew = 0)
    {
        if ($getNew !== 1) {
            dump(file_get_contents(__DIR__ . config('wx.pingtai_public_key_path')));
        }
        $url = "https://api.mch.weixin.qq.com/v3/certificates";
        $timestamp = time(); //时间戳
        $nonce = $this->nonce_str(); //获取一个随机数
        $body = "";
        $mch_private_key = $this->getPrivateKey(); //读取商户api证书私钥
        $merchant_id = config('wx.merchantId'); //服务商商户号
        $serial_no = config('wx.merchantSerialNumber'); //在API安全中获取
        $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'];
        file_put_contents(__DIR__ . '/../../Secret/tuikuan/serial_no.txt', $serial_no);


        $encrypt_certificate = $result['data'][0]['encrypt_certificate'];
        $sign_key = config('wx.apiV3key'); //在API安全中设置
        $result = $this->decryptToString($encrypt_certificate['associated_data'], $encrypt_certificate['nonce'], $encrypt_certificate['ciphertext'], $sign_key); //解密

        file_put_contents(__DIR__ . config('wx.pingtai_public_key_path'), $result);

        return $serial_no;
    }

    private function getHeaders()
    {
        $header = array();
        foreach ($_SERVER as $key => $value) {
            if ('HTTP_' == substr($key, 0, 5)) {
                $header[str_replace('_', '-', substr($key, 5))] = $value;
            }
            if (isset($_SERVER['PHP_AUTH_DIGEST'])) {
                $header['AUTHORIZATION'] = $_SERVER['PHP_AUTH_DIGEST'];
            } elseif (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) {
                $header['AUTHORIZATION'] = base64_encode($_SERVER['PHP_AUTH_USER'] . ':' . $_SERVER['PHP_AUTH_PW']);
            }
            if (isset($_SERVER['CONTENT_LENGTH'])) {
                $header['CONTENT-LENGTH'] = $_SERVER['CONTENT_LENGTH'];
            }
            if (isset($_SERVER['CONTENT_TYPE'])) {
                $header['CONTENT-TYPE'] = $_SERVER['CONTENT_TYPE'];
            }
        }
        return $header;
    }

    private function decryptToString($associatedData, $nonceStr, $ciphertext, $aesKey = '')
    {
        if (empty($aesKey)) {
            $aesKey = config('wx.apiV3key'); //微信商户平台 api安全中设置获取
        }
        $ciphertext = \base64_decode($ciphertext);
        if (strlen($ciphertext) <= self::AUTH_TAG_LENGTH_BYTE) {
            return false;
        }
        // ext-sodium (default installed on >= PHP 7.2)
        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);
        }

        // ext-libsodium (need install libsodium-php 1.x via pecl)
        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);
        }

        // openssl (PHP >= 7.1 support AEAD)
        if (PHP_VERSION_ID >= 70100 && in_array('aes-256-gcm', \openssl_get_cipher_methods())) {
            $ctext = substr($ciphertext, 0, -self::AUTH_TAG_LENGTH_BYTE);
            $authTag = substr($ciphertext, -self::AUTH_TAG_LENGTH_BYTE);

            return \openssl_decrypt(
                $ctext,
                'aes-256-gcm',
                $aesKey,
                \OPENSSL_RAW_DATA,
                $nonceStr,
                $authTag,
                $associatedData
            );
        }

        throw new \RuntimeException('AEAD_AES_256_GCM需要PHP 7.1以上或者安装libsodium-php');
    }

    private function http_post($url, $header, $data)
    {
        $headers[] = "Accept:application/json";
        $headers[] = "Content-Type:application/json";
        $headers[] = "User-Agent:application/json";
        $headers[] = $header;

        $curl = curl_init(); // 启动一个CURL会话
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_HEADER, 0);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // 跳过证书检查
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);  // 从证书中检查SSL加密算法是否存在
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        $tmpInfo = curl_exec($curl);
        //关闭URL请求
        curl_close($curl);
        return $tmpInfo;
    }

    //生成随机字符串
    public function nonce_str($length = 32)
    {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }

    //读取商户api证书私钥
    public function getPrivateKey()
    {
        return openssl_get_privatekey(file_get_contents(__DIR__ . config('wx.apiclientKey'))); //微信商户平台中下载下来，保存到服务器直接读取

    }

    //签名
    public function sign($url, $http_method, $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_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;
    }

    //curl提交
    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;
    }

    protected function generate_tuikuan($length)
    {
        $chars = '0123456789';
        $time = time();
        $password = 'DZZS' . $time . 'TK';
        for ($i = 0; $i < $length; $i++) {
            $password .= $chars[mt_rand(0, strlen($chars) - 1)];
        }
        return $password;
    }

    protected function getWxPublicKey($key)
    {
        $public_content = file_get_contents($key);
        $a = openssl_get_publickey($public_content);
        return $a;
    }

}