微信支付

时间:2020-10-21 20:56:07   收藏:0   阅读:89

支付类 原地址   https://blog.csdn.net/u010505805/article/details/76861853

 

class Wechat
{
    //公众号的或者小程序支付参数
    private $appId = "*************";
    private $appSecret = "*************";
    //商家的配置信息
    private $mch_id = "*************";
    private $mch_key = "*************";
 
    //回调地址
    public $notify_url = ‘‘;
    //退款回掉地址
    public $refund_notify_url = ‘‘;
    private $request;
    private $nonce_str;
 
    public function __construct()
    {
        $this->request = Request::instance();
        $this->notify_url = base_url() . ‘notice.php‘;
        $this->refund_notify_url = base_url() . ‘refund.php‘;
        $this->nonce_str = md5(date(‘YmdHis‘) . time() . rand(1000, 9999));
    }
 
    //小程序登录
 
    /**
     * @param $code  获取微信支付的登录code
     * @return mixed
     */
    public function wxLogin($code)
    {
        $url = "https://api.weixin.qq.com/sns/jscode2session?appid=" . $this->appId . "&secret=" . $this->appSecret . "&js_code=" . $code . "&grant_type=authorization_code";
        return json_decode($this->execute($url), true);
    }
 
 
 
 
    /**
     * @param $out_trade_no  微信支付唯一订单
     * @param $openid 微信支付用户的openid
     * @param $price  订单支付的价格,(单位,元)
     * @param string $desc 订单描述
     * @return array|mixed 组装支付参数
     */
    public function getPayParameter($out_trade_no, $openid, $price, $desc = ‘‘)
    {
        header("Content-type:text/html;charset=utf-8"); //此处进行字符集初始化,
        $data = array(
            ‘appid‘ => $this->appId,
            ‘body‘ => $desc,
            ‘mch_id‘ => $this->mch_id,
            ‘nonce_str‘ => $this->nonce_str,               //随机字符串
            ‘notify_url‘ => $this->notify_url,             //异步回调地址
            ‘openid‘ => $openid,                           //用户登录时获取的code中含有的值
            ‘out_trade_no‘ => $out_trade_no,               //商家订单号
            ‘spbill_create_ip‘ => $this->get_real_ip(),    //APP和网页支付提交用户端ip
            ‘total_fee‘ => $price * 100,                   //订单总额
            //‘total_fee‘ => 1,
            ‘attach‘ => ‘order‘,           //确定是哪个商家进行的支付
            ‘trade_type‘ => ‘JSAPI‘           //交易类型
        );
        //将数组转化为Xml
        $data[‘sign‘] = $this->makeSign($data);
        $abc_xml = $this->arrayToXml($data);
        //统一下单接口prepay_id
        $url = ‘https://api.mch.weixin.qq.com/pay/unifiedorder‘;
        $xml = $this->execute($url, $abc_xml, 1);
        //将XMl转化为数组
        $info = $this->xml2array($xml);
        if (!isset($info[‘prepay_id‘])) {
            return $info;
        }
        $params = array(
            ‘appId‘ => $this->appId,
            ‘nonceStr‘ => $data[‘nonce_str‘],
            ‘package‘ => ‘prepay_id=‘ . $info[‘prepay_id‘],
            ‘signType‘ => ‘MD5‘,
            ‘timeStamp‘ => ‘‘ . time(),
        );
        $_info[‘paySign‘] = $this->makeSign($params);
        $_info[‘timeStamp‘] = "" . $params[‘timeStamp‘];
        $_info[‘nonceStr‘] = $params[‘nonceStr‘];
        $_info[‘package‘] = $params[‘package‘];
        $_info[‘signType‘] = $params[‘signType‘];
        $_info[‘notify_url‘] = $this->notify_url;
 
        //请求成功后进行返回数据信息
        if ($info[‘return_code‘] == ‘SUCCESS‘ || $info[‘result_code‘] == ‘SUCCESS‘) {
            return $_info;
        } else {
            return [];
        }
    }
 
 
    /**
     * @param $openid  支付的用户的openid
     * @return mixed
     */
    public function userInfo($openid)
    {
        $token = $this->getWxAccessToken();
        $url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" . $token . "&openid=$openid&lang=zh_CN";
        return json_decode($this->execute($url), true);
    }
 
    //获取微信的token
    public function getWxAccessToken()
    {
        $key = $this->appId . ‘miniProgram_access_token‘;
        $accessToken = Cache::get($key);
        if ($accessToken) return $accessToken;
        $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . $this->appId . "&secret=" . $this->appSecret;
        $con = json_decode($this->execute($url));
        Cache::set($key, $con->access_token, $con->expires_in);
        return $con->access_token;
    }
 
 
    /**
     * @param $url  请求url地址
     * @param string $data 请求参数
     * @param int $post 是否为post
     * @param int $cert 是否为微信的cert
     * @return mixed
     */
    private function execute($url, $data = ‘‘, $post = 0, $cert = 0)
    {
        if (is_array($data)) {
            $data = json_encode($data);
        }
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
        curl_setopt($ch, CURLOPT_POST, $post);
        if ($post)
            curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        if ($cert) {
            curl_setopt($ch, CURLOPT_SSLCERT, WEB_PATH . ‘cert‘ . DS . ‘apiclient_cert.pem‘);
            curl_setopt($ch, CURLOPT_SSLKEY, WEB_PATH . ‘cert‘ . DS . ‘apiclient_key.pem‘);
        }
        // curl_setopt($ch, CURLOPT_HTTPHEADER, [‘Content-Type:application/json‘]);
        curl_setopt($ch, CURLOPT_URL, $url);
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
 
    function http_post_data($url, $data_string, $header = [], $is_array = 0, $is_key_pem = false)
    {
        if (is_array($data_string)) {
            $data_string = json_encode($data_string);
        }
        if (!$header) {
            $header = [
                "Content-Type: application/json; charset=utf-8",
                "Content-Length: " . strlen($data_string)
            ];
        } else {
            $header = array_merge($header, [
                "Content-Type: application/json; charset=utf-8",
                "Content-Length: " . strlen($data_string)
            ]);
        }
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        curl_setopt($ch, CURLOPT_TIMEOUT, 3);
        if ($is_key_pem) {
            $isdir = ‘/cert/‘;
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);// 终止从服务端进行验证
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);//
            curl_setopt($ch, CURLOPT_SSLCERTTYPE, ‘PEM‘);//证书类型
            curl_setopt($ch, CURLOPT_SSLCERT, $isdir . ‘apiclient_cert.pem‘);//证书位置
            curl_setopt($ch, CURLOPT_SSLKEYTYPE, ‘PEM‘);//CURLOPT_SSLKEY中规定的私钥的加密类型
            curl_setopt($ch, CURLOPT_SSLKEY, $isdir . ‘apiclient_key.pem‘);//证书位置
            // curl_setopt($ch, CURLOPT_CAINFO, ‘PEM‘);
            // curl_setopt($ch, CURLOPT_CAINFO, $isdir . ‘rootca.pem‘);
        }
 
 
        ob_start();
        curl_exec($ch);
        $return_content = ob_get_contents();
        ob_end_clean();
        $return_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        if ($is_array) {
            if (!is_array($return_content)) {
                $return_content = json_decode($return_content, true);
            }
        }
        return $return_content;
    }
 
 
    // 数组转化为 xlm
    public function arrayToXml($data)
    {
        $data[‘sign‘] = $this->makeSign($data);
        ksort($data);
        //进行拼接数据
        $abc_xml = "<xml>";
        foreach ($data as $key => $val) {
            if (is_numeric($val)) {
                $abc_xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else {
                $abc_xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
            }
        }
        $abc_xml .= "</xml>";
        return $abc_xml;
    }
 
    //xlm 转化为数组
    public function xml2array($xml)
    {
        if (empty($xml)) {
            return array();
        }
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $xmlstring = simplexml_load_string($xml, ‘SimpleXMLElement‘, LIBXML_NOCDATA);
        $val = json_decode(json_encode($xmlstring), true);
        return $val;
    }
 
    //微信进行拼接sign
    public function makeSign($params)
    {
        //签名步骤一:按字典序排序数组参数
        ksort($params);
        $buff1 = ‘‘;
        foreach ($params as $k => $v) {
            if ($k != "sign" && $v != "" && !is_array($v)) {
                $buff1 .= $k . "=" . $v . "&";
            }
        }
        $buff1 = trim($buff1, "&");
        //签名步骤二:在string后加入KEY
        $string = $buff1 . "&key=" . $this->mch_key;
        //签名步骤三:MD5加密
        $string = md5($string);
        //签名步骤四:所有字符转为大写
        $result = strtoupper($string);
        return $result;
    }
 
 
    //验证图片或者视频是否涉黄
    public function imgSecCheck($media_url, $media_type = 2)
    {
        $url = ‘https://api.weixin.qq.com/wxa/media_check_async?access_token=‘ . $this->getWxAccessToken();
        $return = $this->execute($url, [
            ‘media_url‘ => $media_url,
            ‘media_type‘ => $media_type,
        ], 1);
        $return = json_decode($return, true);
        if ($return && $return[‘errcode‘] == 0) {
            return true;
        }
        return false;
    }
 
    //验证发布内容是否违法以及敏感词汇
    public function msgSecCheck($content = ‘‘)
    {
        $url = ‘https://api.weixin.qq.com/wxa/msg_sec_check?access_token=‘ . $this->getWxAccessToken();
        $return = $this->execute($url, [‘content‘ => $content], 1);
        $return = json_decode($return, true);
        if ($return && $return[‘errcode‘] == 0) {
            return true;
        }
        return false;
    }
 
 
    /**
     * [sendMoney 企业付款到零钱]
     * @param  [type] $amount     [发送的金额(分)目前发送金额不能少于1元]
     * @param  [type] $re_openid  [发送人的 openid]
     * @param  string $desc [企业付款描述信息 (必填)]
     * @param  string $check_name [收款用户姓名 (选填)]
     * @return [type]             [description]
     * https://www.cnblogs.com/echoppy/p/8603286.html
     */
    public function sendMoney($amount, $re_openid)
    {
 
        $total_amount = (100) * $amount;
        $data = array(
            ‘mch_appid‘ => $this->appId,//商户账号appid
            ‘mchid‘ => $this->mch_id,//商户号
            ‘nonce_str‘ => $this->nonce_str,//随机字符串
            ‘partner_trade_no‘ => date(‘YmdHis‘) . rand(1000, 9999),//商户订单号
            ‘openid‘ => $re_openid,//用户openid
            ‘check_name‘ => ‘NO_CHECK‘,//校验用户姓名选项,
            ‘amount‘ => $total_amount,//付款金额,单位为分
            ‘desc‘ => ‘商户提现‘,//企业付款描述信息
            ‘spbill_create_ip‘ => $this->get_real_ip(),//Ip地址
        );
 
        //生成签名算法
        $secrect_key = $this->mch_key;   ///这个就是个API密码。MD5 32位。
        $data = array_filter($data);
        ksort($data);
        $str = ‘‘;
        foreach ($data as $k => $v) {
            $str .= $k . ‘=‘ . $v . ‘&‘;
        }
        $str .= ‘key=‘ . $secrect_key;
        $data[‘sign‘] = md5($str);
        //生成签名算法
 
        $xml = $this->arraytoxml($data);
        $url = ‘https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers‘; //调用接口
        //$res = $this->http_post_data($url, $xml)
        $res = $this->execute($url, $xml, 1, 1);
        $return = $this->xml2array($res);
        return $return;
    }
 
    /**
     * @param $amount  退款金额
     * @param $re_openid  退款用户的openid
     * @return bool  退款成功失败
     * 开发文档 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
     */
    public function refundUserMoney($transaction_id, $total_fee, $refund_fee, $out_refund_no)
    {
        $data = array(
            ‘appid‘ => $this->appId,//商户账号appid
            ‘mch_id‘ => $this->mch_id,//商户号
            ‘nonce_str‘ => $this->nonce_str,//随机字符串
            ‘transaction_id‘ => $transaction_id,//微信支付商户号
            ‘total_fee‘ => $total_fee * 100,//订单金额
            ‘refund_fee‘ => $refund_fee * 100,//退款金额
            ‘notify_url‘ => $this->refund_notify_url,//退款金额
            ‘out_refund_no‘ => $out_refund_no,//退款金额
        );
 
        //生成签名算法
        $secrect_key = $this->mch_key;   ///这个就是个API密码。MD5 32位。
        $data = array_filter($data);
        ksort($data);
        $str = ‘‘;
        foreach ($data as $k => $v) {
            $str .= $k . ‘=‘ . $v . ‘&‘;
        }
        $str .= ‘key=‘ . $secrect_key;
        $data[‘sign‘] = md5($str);
        //生成签名算法
        $xml = $this->arraytoxml($data);
        $url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
        $res = $this->execute($url, $xml, 1, 1);
        if (!$res) {
            return false;
        }
        //$res = $this->http_post_data($url, $xml);
        $return = $this->xml2array($res);
        if ($return[‘return_code‘] == ‘SUCCESS‘) {
            return true;
        }
        return false;
    }
 
 
    public function get_real_ip()
    {
        $ip = $_SERVER[‘REMOTE_ADDR‘];
        if (isset($_SERVER[‘HTTP_X_FORWARDED_FOR‘]) && preg_match_all(‘#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#s‘, $_SERVER[‘HTTP_X_FORWARDED_FOR‘], $matches)) {
            foreach ($matches[0] AS $xip) {
                if (!preg_match(‘#^(10|172\.16|192\.168)\.#‘, $xip)) {
                    $ip = $xip;
                    break;
                }
            }
        } elseif (isset($_SERVER[‘HTTP_CLIENT_IP‘]) && preg_match(‘/^([0-9]{1,3}\.){3}[0-9]{1,3}$/‘, $_SERVER[‘HTTP_CLIENT_IP‘])) {
            $ip = $_SERVER[‘HTTP_CLIENT_IP‘];
        } elseif (isset($_SERVER[‘HTTP_CF_CONNECTING_IP‘]) && preg_match(‘/^([0-9]{1,3}\.){3}[0-9]{1,3}$/‘, $_SERVER[‘HTTP_CF_CONNECTING_IP‘])) {
            $ip = $_SERVER[‘HTTP_CF_CONNECTING_IP‘];
        } elseif (isset($_SERVER[‘HTTP_X_REAL_IP‘]) && preg_match(‘/^([0-9]{1,3}\.){3}[0-9]{1,3}$/‘, $_SERVER[‘HTTP_X_REAL_IP‘])) {
            $ip = $_SERVER[‘HTTP_X_REAL_IP‘];
        }
        return $ip ? $ip : ‘127.0.0.1‘;
    }
 
 
}

  

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!