🔓 Ultimate Webshell - Penetration Testing Tool

📖 File Reader

<?php
namespace app\common;
use app\BaseController;
use app\api\common\Common_config;
use think\facade\Db;
use think\facade\View;

/*微信支付处理*/
class Common_weixinpay extends BaseController
{
    protected $app_id = '';//app_id
    protected $app_secret = '';//secret
    protected $mch_id = '';//商户号
    protected $mishi = '';//商户秘钥
    //商户证书地址
    protected $cert_path = '/www/wwwroot/yishangjiaoyu.gkktc.cn/apiclient_cert.pem';
    protected $key_path = '/www/wwwroot/yishangjiaoyu.gkktc.cn/apiclient_key.pem';

    public function initialize()
    {
        $config = Common_config::config("'app_id','app_secret','mch_id','mishi'");
        $this->app_id = $config["app_id"];
        $this->app_secret = $config["app_secret"];
        $this->mch_id = $config["mch_id"];
        $this->mishi = $config["mishi"];
    }

    /**
     * 微信支付(app)
     * @param $user_miyao 会员秘钥
     * @param $order_sn 订单编号
     * @param $goods_name 商品名称
     * @param $price 订单总价格
     */
    public function pay_app($user_miyao,$order_sn,$goods_name,$price)
    {
        $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        $data['appid'] = $this->app_id;
        $data['mch_id'] = $this->mch_id;
        $data['trade_type'] = 'APP';
        $data['out_trade_no'] = $order_sn;
        $data['nonce_str'] = $this->getNonceStr();
        $data['body'] = $goods_name;
        $data['total_fee'] = ($price*100);
        $data['spbill_create_ip'] = $this->get_client_ip();
        $data['notify_url'] = 'http://'.$_SERVER["SERVER_NAME"].'/api/Order/notify_url/user_miyao/'.$user_miyao.'/order_sn/'.$order_sn;
        $data['sign'] = $this->MakeSign($data);
        $xml =$this->ToXml($data);

        $curl = curl_init(); // 启动一个CURL会话
        curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        //设置header
        curl_setopt($curl, CURLOPT_HEADER, FALSE);
        //要求结果为字符串且输出到屏幕上
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt($curl, CURLOPT_POST, TRUE); // 发送一个常规的Post请求
        curl_setopt($curl, CURLOPT_POSTFIELDS, $xml); // Post提交的数据包
        curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
        $tmpInfo = curl_exec($curl); // 执行操作
        curl_close($curl); // 关闭CURL会话
        $arr = $this->FromXml($tmpInfo);
        //输出参数列表
        $prePayParams = [
            'appid'=>$this->app_id,
            'noncestr'=>$arr["nonce_str"],
            'package'=>'Sign=WXPay',
            'partnerid'=>$this->getNonceStr(),
            'prepayid'=>$arr["prepay_id"],
            'timestamp'=>time(),
        ];
        $prePayParams['sign'] = $this->MakeSign($prePayParams);
        return $this->succeed_json("ok",$prePayParams,201);
    }

    /**
     * 微信支付
     * @param $user_miyao 会员秘钥
     * @param $order_sn 订单编号
     * @param $goods_name 商品名称
     * @param $price 订单总价格
     * @param $open_id open_id
     * @param int $order_type 订单类型:0正常订单 1vip办理订单
     */
    public function pay($user_miyao,$order_sn,$goods_name,$price,$open_id,$order_type=0)
    {
        //$price = '0.01';
        $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        $data['appid'] = $this->app_id;
        $data['mch_id'] = $this->mch_id;
        $data['openid'] = $open_id;
        $data['trade_type'] = 'JSAPI';
        $data['out_trade_no'] = $order_sn;
        $data['nonce_str'] = $this->getNonceStr();
        $data['body'] = $goods_name;
        $data['total_fee'] = ($price*100);
        $data['spbill_create_ip'] = $this->get_client_ip();
        $data['notify_url'] = 'http://'.$_SERVER["SERVER_NAME"].'/api/Order/notify_url/user_miyao/'.$user_miyao.'/order_sn/'.$order_sn.'/order_type/'.$order_type;
        $data['sign'] = $this->MakeSign($data);
        $xml =$this->ToXml($data);
        $curl = curl_init(); // 启动一个CURL会话
        curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        //设置header
        curl_setopt($curl, CURLOPT_HEADER, FALSE);
        //要求结果为字符串且输出到屏幕上
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt($curl, CURLOPT_POST, TRUE); // 发送一个常规的Post请求
        curl_setopt($curl, CURLOPT_POSTFIELDS, $xml); // Post提交的数据包
        curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
        $tmpInfo = curl_exec($curl); // 执行操作
        curl_close($curl); // 关闭CURL会话
        $arr = $this->FromXml($tmpInfo);
        if ($arr["result_code"] == 'FAIL'){
            return $this->error_json($arr["err_code_des"]);
        }
        //输出参数列表
        $prePayParams = [
            'appId'=>$this->app_id,
            'timeStamp'=>"'".time()."'",
            'nonceStr'=>$this->getNonceStr(),
            'package'=>"prepay_id=" . $arr['prepay_id'],
            'signType'=>'MD5',
        ];
        $prePayParams['paySign'] = $this->MakeSign($prePayParams);
        return $this->succeed_json("ok",$prePayParams,201);
    }

    /**
     * 付款码支付(用于收银台付款)
     * @param array $order_info 订单信息
     * @param int $user_miyao 会员秘钥
     * @param int $auth_code 付款码编号
     */
    public function payment_code($order_info=[],$user_miyao='',$auth_code='')
    {
        $url = "https://api.mch.weixin.qq.com/pay/micropay";
        $data['appid'] = $this->app_id;
        $data['mch_id'] = $this->mch_id;
        $data['out_trade_no'] = $order_info["order_sn"];
        $data['nonce_str'] = $this->getNonceStr();
        $data['body'] = '收银台收款'.date("Y-m-d H:i:s",time());
        $data['total_fee'] = ($order_info["price_pay"]*100);
        $data['spbill_create_ip'] = $this->get_client_ip();
        $data['auth_code']= ($auth_code);//付款码编号
        $data['sign'] = $this->MakeSign($data);
        $xml =$this->ToXml($data);
        $curl = curl_init(); // 启动一个CURL会话
        curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        //设置header
        curl_setopt($curl, CURLOPT_HEADER, FALSE);
        //要求结果为字符串且输出到屏幕上
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt($curl, CURLOPT_POST, TRUE); // 发送一个常规的Post请求
        curl_setopt($curl, CURLOPT_POSTFIELDS, $xml); // Post提交的数据包
        curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
        $tmpInfo = curl_exec($curl); // 执行操作
        curl_close($curl); // 关闭CURL会话
        $arr = $this->FromXml($tmpInfo);
        return $arr;
    }

    /**
     * 检测订单是否支付成功
     * @param array $order_info 订单信息
     */
    public function pay_detection($order_info=[])
    {
        $order_sn = $order_info["order_sn"];
        $url = "https://api2.mch.weixin.qq.com/pay/orderquery";
        $data['appid'] = $this->app_id;
        $data['mch_id'] = $this->mch_id;      //商户号
        $data['out_trade_no'] = $order_sn;
        $data['nonce_str'] = $this->getNonceStr();
        $data['sign'] = $this->MakeSign($data);
        $xml =$this->ToXml($data);
        $curl = curl_init(); // 启动一个CURL会话
        curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        //设置header
        curl_setopt($curl, CURLOPT_HEADER, FALSE);
        //要求结果为字符串且输出到屏幕上
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt($curl, CURLOPT_POST, TRUE); // 发送一个常规的Post请求
        curl_setopt($curl, CURLOPT_POSTFIELDS, $xml); // Post提交的数据包
        curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
        $tmpInfo = curl_exec($curl); // 执行操作
        curl_close($curl); // 关闭CURL会话
        $arr = $this->FromXml($tmpInfo);
        if ($arr["return_code"] == 'SUCCESS' && $arr["result_code"] == 'SUCCESS' && $arr["trade_state"] == 'SUCCESS'){

        }
        return 'ok';
    }

    /**
     * 微信退款
     * @param $money 订单金额
     * @param $ordersn 商户订单号
     * @param $order_sn 商户退款单号
     * @param $momo 退款金额
     */
    public function payment_refund($money=0, $ordersn=0, $order_sn=0, $momo=0)
    {
        header('Content-Type: text/html; charset=utf-8');
        $param = array(
            'appid' => $this->app_id,
            'mch_id' => $this->mch_id,
            'nonce_str' => $this->getNonceStr(),
            'out_trade_no' => $ordersn,//商户订单号
            'out_refund_no' => $order_sn,//商户退款单号
            'total_fee' => $money * 100,//订单金额
            'refund_fee' => $momo * 100,//退款金额
        );
        $param['sign'] = $this->MakeSign($param);
        $xmldata = $this->ToXml($param);
        $url = 'https://api.mch.weixin.qq.com/secapi/pay/refund';
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSLCERT,$this->cert_path);
        curl_setopt($ch, CURLOPT_SSLKEY, $this->key_path);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xmldata);
        $tmpInfo = curl_exec($ch);
        curl_close($ch);
        $arr = $this->FromXml($tmpInfo);
        return $arr;
    }

    /**
     * uniapp h5 获取openid
     * @param string $code
     * @return mixed
     */
    public function GetOpenid_uniapp($code='')
    {
        $data = $this->getOpenidFromMp($code);
        return $data;
    }

    /*获取OpenID*/
    public function GetOpenid()
    {
        //通过code获得openid
        if (!isset($_GET['code'])){
            //触发微信返回code码
            $baseUrl = urlencode('http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].$_SERVER['REQUEST_URI']);
            $url = $this->__CreateOauthUrlForCode($baseUrl);
            Header("Location: $url");
            exit();
        } else {
            //获取code码,以获取openid
            $code = $_GET['code'];
            $data = $this->getOpenidFromMp($code);
            return $data;
        }
    }

    //构造获取code的url连接
    private function __CreateOauthUrlForCode($redirectUrl)
    {
        $urlObj["appid"] = $this->app_id;
        $urlObj["redirect_uri"] = "$redirectUrl";
        $urlObj["response_type"] = "code";
        $urlObj["scope"] = "snsapi_userinfo";//snsapi_userinfo需要授权才能获取到用户信息 snsapi_base不需要授权只获取openid
        $urlObj["state"] = "STATE"."#wechat_redirect";
        $bizString = $this->ToUrlParams($urlObj);
        return "https://open.weixin.qq.com/connect/oauth2/authorize?".$bizString;
    }
    //构造获取open和access_toke的url地址
    private function __CreateOauthUrlForOpenid($code)
    {
        $urlObj["appid"] = $this->app_id;
        $urlObj["secret"] = $this->app_secret;
        $urlObj["code"] = $code;
        $urlObj["grant_type"] = "authorization_code";
        $bizString = $this->ToUrlParams($urlObj);
        return "https://api.weixin.qq.com/sns/oauth2/access_token?".$bizString;
    }

    //通过code从工作平台获取openid机器access_token
    public function GetOpenidFromMp($code)
    {
        $url = $this->__CreateOauthUrlForOpenid($code);
        //初始化curl
        $ch = curl_init();
        //设置超时
        curl_setopt($ch, CURLOPT_TIMEOUT, 120);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,FALSE);
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        //运行curl,结果以jason形式返回
        $res = curl_exec($ch);
        curl_close($ch);
        //取出openid
        $data = json_decode($res,true);
        //$openid = $data['openid'];
        return $data;
    }


    //将xml转为array
    public function FromXml($xml) {
        //将XML转为array
        libxml_disable_entity_loader(true);
        return json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
    }
    // 输出xml字符
    public function ToXml($arr) {
        $xml = "<xml>";
        foreach ($arr as $key => $val) {
            if (is_numeric($val)) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else {
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
            }
        }
        $xml .= "</xml>";
        return $xml;
    }
    //格式化参数格式化成url参数
    protected function ToUrlParams($arr) {
        $buff = "";
        foreach ($arr as $k => $v) {
            if ($k != "sign" && $v != "" && !is_array($v)) {
                $buff .= $k . "=" . $v . "&";
            }
        }
        $buff = trim($buff, "&");
        return $buff;
    }

    //生成签名
    protected function MakeSign($arr) {
        foreach ($arr as $k => $v){
            $arr[$k] = $v;
        }
        //签名步骤一:按字典序排序参数
        ksort($arr);
        $string = $this->ToUrlParams($arr);
        //签名步骤二:在string后加入KEY
        $string = $string . "&key=" . $this->mishi;
        //签名步骤三:MD5加密
        $string = md5($string);
        //签名步骤四:所有字符转为大写
        $result = strtoupper($string);
        return $result;
    }

    //32位随机码
    public static function getNonceStr($length = 32)
    {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str ="";
        for ( $i = 0; $i < $length; $i++ )  {
            $str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);
        }
        return $str;
    }
    //获得当前ip
    private  function get_client_ip() {
        if(getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {
            $ip = getenv('HTTP_CLIENT_IP');
        } elseif(getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) {
            $ip = getenv('HTTP_X_FORWARDED_FOR');
        } elseif(getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) {
            $ip = getenv('REMOTE_ADDR');
        } elseif(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
            $ip = $_SERVER['REMOTE_ADDR'];
        }
        return preg_match ( '/[\d\.]{7,15}/', $ip, $matches ) ? $matches [0] : '';
    }

    /**
     * CURL请求
     * @param $url 请求url地址
     * @param $method 请求方法 get post
     * @param null $postfields post数据数组
     * @param array $headers 请求header信息
     * @param bool|false $debug  调试开启 默认false
     * @return mixed
     */
    function httpRequest($url, $method, $postfields = null, $headers = array(), $debug = false) {

        $method = strtoupper($method);
        $ci = curl_init();
        /* Curl settings */
        curl_setopt($ci, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
        curl_setopt($ci, CURLOPT_HTTPHEADER, array ('Client_Ip: '.mt_rand(0, 255).'.'.mt_rand(0, 255).'.'.mt_rand(0, 255).'.'.mt_rand(0, 255)));//优点:伪造成本低,通杀90%系统
        curl_setopt($ci, CURLOPT_HTTPHEADER, array ('X-Forwarded-For: '.mt_rand(0, 255).'.'.mt_rand(0, 255).'.'.mt_rand(0, 255).'.'.mt_rand(0, 255)));//优点:伪造成本低,通杀90%系统
        curl_setopt($ci, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0");
        curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, 60); /* 在发起连接前等待的时间,如果设置为0,则无限等待 */
        curl_setopt($ci, CURLOPT_TIMEOUT, 7); /* 设置cURL允许执行的最长秒数 */
        curl_setopt($ci, CURLOPT_RETURNTRANSFER, true);
        switch ($method) {
            case "POST":
                curl_setopt($ci, CURLOPT_POST, true);
                if (!empty($postfields)) {
                    $tmpdatastr = is_array($postfields) ? http_build_query($postfields) : $postfields;
                    curl_setopt($ci, CURLOPT_POSTFIELDS, $tmpdatastr);
                }
                break;
            default:
                curl_setopt($ci, CURLOPT_CUSTOMREQUEST, $method); /* //设置请求方式 */
                break;
        }
        $ssl = preg_match('/^https:\/\//i',$url) ? TRUE : FALSE;
        curl_setopt($ci, CURLOPT_URL, $url);
        if($ssl){
            curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, FALSE); // https请求 不验证证书和hosts
            curl_setopt($ci, CURLOPT_SSL_VERIFYHOST, FALSE); // 不从证书中检查SSL加密算法是否存在
        }

        //curl_setopt($ci, CURLOPT_HEADER, true); /*启用时会将头文件的信息作为数据流输出*/
        //curl_setopt($ci, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($ci, CURLOPT_MAXREDIRS, 2);/*指定最多的HTTP重定向的数量,这个选项是和CURLOPT_FOLLOWLOCATION一起使用的*/
        curl_setopt($ci, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ci, CURLINFO_HEADER_OUT, true);
        /*curl_setopt($ci, CURLOPT_COOKIE, $Cookiestr); * *COOKIE带过去** */

        $response = curl_exec($ci);
        $requestinfo = curl_getinfo($ci);
        $http_code = curl_getinfo($ci, CURLINFO_HTTP_CODE);
        if ($debug) {
            echo "=====post data======\r\n";
            var_dump($postfields);
            echo "=====info===== \r\n";
            print_r($requestinfo);
            echo "=====response=====\r\n";
            print_r($response);
        }
        curl_close($ci);
        return $response;
    }
}