ThinkPay最新微信支付公众号支付驱动分享
下面分享个ThinkPay的微信支付驱动,便于大家使用,如有疑问加QQ群讨论105108204<?php <br />
// +----------------------------------------------------------------------<br>
// | 零云 [ 简单 高效 卓越 ]<br>
// +----------------------------------------------------------------------<br>
// | Copyright (c) 2016 http://www.lingyun.net All rights reserved.<br>
// +----------------------------------------------------------------------<br>
// | Author: jry <br>
// +----------------------------------------------------------------------<br>
namespace Addons\Pay\ThinkPay\Pay\Driver;<br><br>
/**<br>
 * 微信支付驱动<br>
 */<br>
class Wxpay extends \Addons\Pay\ThinkPay\Pay\Pay<br>
{<br>
    protected $gateway    = 'https://api.mch.weixin.qq.com/pay/unifiedorder';<br>
    protected $orderquery = 'https://api.mch.weixin.qq.com/pay/orderquery';<br>
    protected $config     = array(<br>
        'appid'     => '',<br>
        'appsecret' => '',<br>
        'mchid'     => '',<br>
        'key'       => '',<br>
    );<br><br>
    public function check()<br>
    {<br>
        if (!$this->config['appid'] || !$this->config['appsecret'] || !$this->config['mchid'] || !$this->config['key']) {<br>
            E("微信支付设置有误!");<br>
        }<br>
        return true;<br>
    }<br><br>
    public function buildRequestForm($pay_data)<br>
    {<br>
        // APP支付<br>
        if (C('IS_API')) {<br>
            $param = array(<br>
                'appid'            => $this->config['appid'],<br>
                'mch_id'           => $this->config['mchid'],<br>
                'nonce_str'        => $this->getNonceStr(),<br>
                'body'             => $pay_data['body'],<br>
                'out_trade_no'     => $pay_data['out_trade_no'],<br>
                'total_fee'        => $pay_data['money'] * 100,<br>
                'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],<br>
                'notify_url'       => $this->config['notify_url'],<br>
                'trade_type'       => 'APP',<br>
            );<br><br>
            // 签名<br>
            $param['sign'] = $this->MakeSign($param);<br>
            $xml_param     = $this->ToXml($param);<br>
            $result        = $this->FromXml($this->postXmlCurl($xml_param, $this->gateway));<br>
            if ($result['return_code'] === 'SUCCESS') {<br>
                if ($this->CheckSign($result)) {<br>
                    // 统一下单接口返回正常的prepay_id,再按签名规范重新生成签名后,将数据传输给APP。<br>
                    // 参与签名的字段名为appId,partnerId,prepayId,nonceStr,timeStamp,package。注意:package的值格式为Sign=WXPay<br>
                    $prepayparams              = array();<br>
                    $prepayparams['appid']     = $result['appid'];<br>
                    $prepayparams['partnerid'] = $result['mch_id'];<br>
                    $prepayparams['prepayid']  = $result['prepay_id'];<br>
                    $prepayparams['noncestr']  = $result['nonce_str'];<br>
                    $prepayparams['package']   = 'Sign=WXPay';<br>
                    $prepayparams['timestamp'] = time();<br>
                    $prepayparams['sign']      = $this->MakeSign($prepayparams); // 签名<br>
                    $return['json']            = json_encode($prepayparams);<br>
                    return $return;<br>
                }<br>
            }<br>
        } else {<br>
            // 获取用户openId,微信公众号JSAPI支付必须<br>
            $openId = $this->GetOpenid();<br>
            $param  = array(<br>
                'appid'            => $this->config['appid'],<br>
                'mch_id'           => $this->config['mchid'],<br>
                'nonce_str'        => $this->getNonceStr(),<br>
                'body'             => $pay_data['body'],<br>
                'out_trade_no'     => $pay_data['out_trade_no'],<br>
                'total_fee'        => $pay_data['money'] * 100,<br>
                'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],<br>
                'notify_url'       => $this->config['notify_url'],<br>
                'trade_type'       => 'JSAPI',<br>
                'openid'           => $openId,<br>
            );<br><br>
            // 签名<br>
            $param['sign'] = $this->MakeSign($param);<br>
            $xml_param     = $this->ToXml($param);<br>
            $result        = $this->FromXml($this->postXmlCurl($xml_param, $this->gateway));<br>
            if ($result['return_code'] === 'SUCCESS') {<br>
                if ($this->CheckSign($result)) {<br>
                    // 获取JSAPI所需参数<br>
                    $jsApiParameters = $this->GetJsApiParameters($result);<br>
                    $pay_page        = 
                        <br>
                            <br>
                                <meta>
<br>
                                <meta>
<br>
                                <title>微信支付</title>
<br>
                                <script><br />
                                //调用微信JS api 支付<br />
                                function jsApiCall()<br />
                                {<br />
                                    WeixinJSBridge.invoke(<br />
                                        'getBrandWCPayRequest',<br />
                                        {$jsApiParameters},<br />
                                        function(res){<br />
                                            WeixinJSBridge.log(res.err_msg);<br />
                                            //alert(res.err_code+res.err_desc+res.err_msg);<br />
                                        }<br />
                                    );<br />
                                }<br />
<br />
                                function callpay()<br />
                                {<br />
                                    if (typeof WeixinJSBridge == "undefined"){<br />
                                        if( document.addEventListener ){<br />
                                            document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);<br />
                                        }else if (document.attachEvent){<br />
                                            document.attachEvent('WeixinJSBridgeReady', jsApiCall);<br />
                                            document.attachEvent('onWeixinJSBridgeReady', jsApiCall);<br />
                                        }<br />
                                    }else{<br />
                                        jsApiCall();<br />
                                    }<br />
                                }<br />
                                </script><br>
                            <br>
                            <br>
                                <br><br>
                                <font><b>该笔订单支付金额为<span>{$pay_data['money']}</span>元</b></font><br><br><br>
                                <div>
<br>
                                    <button>立即支付</button><br>
                                </div>
<br>
                            <br>
                            <br>
EOF;<br>
                    return $pay_page;<br>
                }<br>
            } else {<br>
                E("微信订单错误!" . $result['return_msg']);<br>
            }<br>
        }<br>
    }<br><br>
    /**<br>
     * 异步通知验证<br>
     */<br>
    public function verifyNotify($notify)<br>
    {<br>
        //获取通知的数据<br>
        if ($notify['return_code'] === 'SUCCESS') {<br>
            if (!array_key_exists("transaction_id", $notify)) {<br>
                E("输入参数不正确!");<br>
            }<br>
            $param['transaction_id'] = $notify["transaction_id"];<br>
            $param['appid']          = $this->config['appid'];<br>
            $param['mch_id']         = $this->config['mchid'];<br>
            $param['nonce_str']      = $this->getNonceStr();<br>
            $param['sign']           = $this->MakeSign($param);<br>
            $xml_param               = $this->ToXml($param);<br>
            $result                  = $this->FromXml($this->postXmlCurl($xml_param, $this->orderquery));<br>
            if ($this->CheckSign($result)) {<br>
                $result['status'] = ($result['result_code'] == 'SUCCESS') ? true : false;<br>
                $result['money']  = $result['total_fee'] / 100;<br>
                $this->info       = $result;<br>
                return true;<br>
            }<br>
        } else {<br>
            E('通知错误');<br>
        }<br>
    }<br><br>
    /**<br>
     *<br>
     * 获取jsapi支付的参数<br>
     * @param array $UnifiedOrderResult 统一支付接口返回的数据<br>
     * @throws WxPayException<br>
     *<br>
     * @return json数据,可直接填入js函数作为参数<br>
     */<br>
    public function GetJsApiParameters($UnifiedOrderResult)<br>
    {<br>
        if (!array_key_exists("appid", $UnifiedOrderResult)<br>
            || !array_key_exists("prepay_id", $UnifiedOrderResult)<br>
            || $UnifiedOrderResult['prepay_id'] == "") {<br>
            E("参数错误");<br>
        }<br>
        $jsapi['appId']     = $UnifiedOrderResult["appid"];<br>
        $jsapi['timeStamp'] = (string) time();<br>
        $jsapi['nonceStr']  = $this->getNonceStr();<br>
        $jsapi['appId']     = $UnifiedOrderResult["appid"];<br>
        $jsapi['package']   = "prepay_id=" . $UnifiedOrderResult['prepay_id'];<br>
        $jsapi['signType']  = 'MD5';<br>
        $jsapi['paySign']   = $this->MakeSign($jsapi);<br>
        $parameters         = json_encode($jsapi);<br>
        return $parameters;<br>
    }<br><br>
    /**<br>
     * 以post方式提交xml到对应的接口url<br>
     *<br>
     * @param string $xml  需要post的xml数据<br>
     * @param string $url  url<br>
     * @param bool $useCert 是否需要证书,默认不需要<br>
     * @param int $second   url执行超时时间,默认30s<br>
     * @throws WxPayException<br>
     */<br>
    private static function postXmlCurl($xml, $url, $useCert = false, $second = 30)<br>
    {<br>
        $ch = curl_init();<br>
        //设置超时<br>
        curl_setopt($ch, CURLOPT_TIMEOUT, $second);<br><br>
        //如果有配置代理这里就设置代理<br>
        // if(WxPayConfig::CURL_PROXY_HOST != "0.0.0.0"<br>
        //             && WxPayConfig::CURL_PROXY_PORT != 0){<br>
        //             curl_setopt($ch,CURLOPT_PROXY, WxPayConfig::CURL_PROXY_HOST);<br>
        //             curl_setopt($ch,CURLOPT_PROXYPORT, WxPayConfig::CURL_PROXY_PORT);<br>
        //         }<br>
        curl_setopt($ch, CURLOPT_URL, $url);<br>
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);<br>
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); //严格校验<br>
        //设置header<br>
        curl_setopt($ch, CURLOPT_HEADER, false);<br>
        //要求结果为字符串且输出到屏幕上<br>
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);<br><br>
        if ($useCert == true) {<br>
            //设置证书<br>
            //使用证书:cert 与 key 分别属于两个.pem文件<br>
            curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');<br>
            curl_setopt($ch, CURLOPT_SSLCERT, WxPayConfig::SSLCERT_PATH);<br>
            curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');<br>
            curl_setopt($ch, CURLOPT_SSLKEY, WxPayConfig::SSLKEY_PATH);<br>
        }<br>
        //post提交方式<br>
        curl_setopt($ch, CURLOPT_POST, true);<br>
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);<br>
        //运行curl<br>
        $data = curl_exec($ch);<br>
        //返回结果<br>
        if ($data) {<br>
            curl_close($ch);<br>
            return $data;<br>
        } else {<br>
            $error = curl_errno($ch);<br>
            curl_close($ch);<br>
            E("curl出错,错误码:$error");<br>
        }<br>
    }<br><br>
    /*<br>
     * 产生随机字符串,不长于32位<br>
     * @param int $length<br>
     * @return 产生的随机字符串<br>
     */<br>
    public static function getNonceStr($length = 32)<br>
    {<br>
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";<br>
        $str   = "";<br>
        for ($i = 0; $i 
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);<br>
        }<br>
        return $str;<br>
    }<br><br>
    /**<br>
     * 生成签名<br>
     * @return 签名,本函数不覆盖sign成员变量,如要设置签名需要调用SetSign方法赋值<br>
     */<br>
    public function MakeSign($param)<br>
    {<br>
        //签名步骤一:按字典序排序参数<br>
        ksort($param);<br>
        $string = $this->ToUrlParams($param);<br>
        //签名步骤二:在string后加入KEY<br>
        $string = $string . "&key=" . $this->config['key'];<br>
        //签名步骤三:MD5加密<br>
        $string = md5($string);<br>
        //签名步骤四:所有字符转为大写<br>
        $result = strtoupper($string);<br>
        return $result;<br>
    }<br><br>
    /**<br>
     *<br>
     * 检测签名<br>
     */<br>
    public function CheckSign($param)<br>
    {<br>
        $sign = $this->MakeSign($param);<br>
        if ($param['sign'] == $sign) {<br>
            return true;<br>
        } else {<br>
            E("签名错误!");<br>
        }<br>
    }<br><br>
    /**<br>
     *<br>
     * 拼接签名字符串<br>
     * @param array $urlObj<br>
     *<br>
     * @return 返回已经拼接好的字符串<br>
     */<br>
    public function ToUrlParams($param)<br>
    {<br>
        $buff = "";<br>
        foreach ($param as $k => $v) {<br>
            if ($k != "sign" && $v != "" && !is_array($v)) {<br>
                $buff .= $k . "=" . $v . "&";<br>
            }<br>
        }<br><br>
        $buff = trim($buff, "&");<br>
        return $buff;<br>
    }<br><br>
    /**<br>
     * 输出xml字符<br>
     * @throws WxPayException<br>
     **/<br>
    public function ToXml($param)<br>
    {<br>
        if (!is_array($param)<br>
            || count($param) 
            E("数组数据异常!");<br>
        }<br><br>
        $xml = "<xml>";<br>
        foreach ($param as $key => $val) {<br>
            if (is_numeric($val)) {<br>
                $xml .= "" . $val . "" . $key . ">";<br>
            } else {<br>
                $xml .= "" . $key . ">";<br>
            }<br>
        }<br>
        $xml .= "</xml>";<br>
        return $xml;<br>
    }<br><br>
    /**<br>
     * 将xml转为array<br>
     * @param string $xml<br>
     * @throws WxPayException<br>
     */<br>
    public function FromXml($xml)<br>
    {<br>
        if (!$xml) {<br>
            E("xml数据异常!");<br>
        }<br>
        //将XML转为array<br>
        //禁止引用外部xml实体<br>
        libxml_disable_entity_loader(true);<br>
        $this->values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);<br>
        return $this->values;<br>
    }<br><br>
    /**<br>
     *<br>
     * 通过跳转获取用户的openid,跳转流程如下:<br>
     * 1、设置自己需要调回的url及其其他参数,跳转到微信服务器https://open.weixin.qq.com/connect/oauth2/authorize<br>
     * 2、微信服务处理完成之后会跳转回用户redirect_uri地址,此时会带上一些参数,如:code<br>
     *<br>
     * @return 用户的openid<br>
     */<br>
    public function GetOpenid()<br>
    {<br>
        //通过code获得openid<br>
        if (!isset($_GET['code'])) {<br>
            //触发微信返回code码<br>
            $baseUrl = urlencode('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);<br>
            $url     = $this->__CreateOauthUrlForCode($baseUrl);<br>
            Header("Location: $url");<br>
            exit();<br>
        } else {<br>
            //获取code码,以获取openid<br>
            $code   = $_GET['code'];<br>
            $openid = $this->getOpenidFromMp($code);<br>
            return $openid;<br>
        }<br>
    }<br><br>
    /**<br>
     *<br>
     * 通过code从工作平台获取openid机器access_token<br>
     * @param string $code 微信跳转回来带上的code<br>
     *<br>
     * @return openid<br>
     */<br>
    public function GetOpenidFromMp($code)<br>
    {<br>
        $url = $this->__CreateOauthUrlForOpenid($code);<br>
        //初始化curl<br>
        $ch = curl_init();<br>
        //设置超时<br>
        curl_setopt($ch, CURLOPT_TIMEOUT, $this->curl_timeout);<br>
        curl_setopt($ch, CURLOPT_URL, $url);<br>
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);<br>
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);<br>
        curl_setopt($ch, CURLOPT_HEADER, false);<br>
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);<br>
        // if(WxPayConfig::CURL_PROXY_HOST != "0.0.0.0"<br>
        //             && WxPayConfig::CURL_PROXY_PORT != 0){<br>
        //             curl_setopt($ch,CURLOPT_PROXY, WxPayConfig::CURL_PROXY_HOST);<br>
        //             curl_setopt($ch,CURLOPT_PROXYPORT, WxPayConfig::CURL_PROXY_PORT);<br>
        //         }<br>
        //运行curl,结果以jason形式返回<br>
        $res = curl_exec($ch);<br>
        curl_close($ch);<br>
        //取出openid<br>
        $data       = json_decode($res, true);<br>
        $this->data = $data;<br>
        $openid     = $data['openid'];<br>
        return $openid;<br>
    }<br><br>
    /**<br>
     *<br>
     * 构造获取code的url连接<br>
     * @param string $redirectUrl 微信服务器回跳的url,需要url编码<br>
     *<br>
     * @return 返回构造好的url<br>
     */<br>
    private function __CreateOauthUrlForCode($redirectUrl)<br>
    {<br>
        $urlObj["appid"]         = $this->config['appid'];<br>
        $urlObj["redirect_uri"]  = "$redirectUrl";<br>
        $urlObj["response_type"] = "code";<br>
        $urlObj["scope"]         = "snsapi_base";<br>
        $urlObj["state"]         = "#wechat_redirect";<br>
        $bizString               = $this->ToUrlParams($urlObj);<br>
        return "https://open.weixin.qq.com/connect/oauth2/authorize?" . $bizString;<br>
    }<br><br>
    /**<br>
     *<br>
     * 构造获取open和access_toke的url地址<br>
     * @param string $code,微信跳转带回的code<br>
     *<br>
     * @return 请求的url<br>
     */<br>
    private function __CreateOauthUrlForOpenid($code)<br>
    {<br>
        $urlObj["appid"]      = $this->config['appid'];<br>
        $urlObj["secret"]     = $this->config['appsecret'];<br>
        $urlObj["code"]       = $code;<br>
        $urlObj["grant_type"] = "authorization_code";<br>
        $bizString            = $this->ToUrlParams($urlObj);<br>
        return "https://api.weixin.qq.com/sns/oauth2/access_token?" . $bizString;<br>
    }<br>
}		
 
                        
                        微信是一款手机通信软件,支持通过手机网络发送语音短信、视频、图片和文字。微信可以单聊及群聊,还能根据地理位置找到附近的人,带给大家全新的移动沟通体验,有需要的小伙伴快来保存下载体验吧!
 
                Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号