微信公众号支付

微信公众号 公众号支付 公众号登录
创建于:2019年09月17日 更新于:2019年10月10日

微信支付官方文档

本地调试微信登录可以修改hosts文件把微信回调域名映射到127.0.0.1上,并在本地搭建代码环境,通过域名可以正常访问到程序

登录公众号

function login(){

    $redirect_uri = '';// 登录展示页面地址
    $appId = '';

    //1.准备scope为snsapi_base网页授权页面
    $redirect_uri = urlencode($redirect_uri);
    $snsapi_base_url = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid='.$appId.'&redirect_uri='.$redirect_uri.'&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect';

    //2.静默授权,获取code
    //页面跳转至redirect_uri/?code=CODE&state=STATE
    header('Location:'.$snsapi_base_url);
}


// login方法里$redirect_uri定向的地址
function index(){

    $code = $_GET['code'];
    $appId = '';
    $secret = '';

    $url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid='.$code.'&secret='.$secret.'&code='.$code.'&grant_type=authorization_code';

    $content = getCurl($url); // 获取access_token和openid,换取微信用户信息

    $content = json_decode($content, true);

    $weChatUserinfo = getCurl("https://api.weixin.qq.com/sns/userinfo?access_token={$content['access_token']}&openid={$content['openid']}&lang=zh_CN");

    $weChatUserinfo = json_decode($weChatUserinfo, true);

    /**
    * $weChatUserinfo数据

    Array
(
    [openid] => xxxxxx
    [nickname] => 早上七八点钟的太阳
    [sex] => 1
    [language] => zh_CN
    [city] => 合肥
    [province] => 安徽
    [country] => 中国
    [headimgurl] => http://thirdwx.qlogo.cn/mmopen/vi_32/DtfUiaYkxDhRq7QUcyvZyNkiag0GCKjKv5dCHmHXjRQpxl4lU3DCPlKPBsAbMiaz9IK7yo7bbviafkTnibjwmT97uhA/132
    [privilege] => Array
        (
        )

    [unionid] => xxxxxxxx
)
    */
}

后端

前端支付请求调用接口

function payment(){

    $param = [
            'appid' => '',//微信公众平台appId
            'mch_id' => '',// 商户号
            'nonce_str' => md5(uniqid()), // 随机字符串、最大长度32位
            'body' => '',// 商品信息
            'out_trade_no' => '', // 商户订单号,唯一
            'total_fee' => 1,//支付金额,单位分
            'spbill_create_ip' => '',// IP地址
            'notify_url' => '', // 回调地址
            'trade_type' => 'JSAPI', // 公众号支付
            'openid' => $_POST['openid'] // 微信用户openid,在公众号登录时就已获取
        ];
        $param['sign'] = $this->sign($param);

        $xml = arrayToXml($param);
        $response = postXmlCurl($xml, $url);
        $data = xmlToArray($response);
        if(isset($data['return_code']) && $data['return_code'] == 'SUCCESS'){
            $result = [
                'nonce_str' => $data['nonce_str'],
                'appId' => $data['appid'],
                'timeStamp' => time(),
                'package' => 'prepay_id='.$data['prepay_id'],
                'signType' => 'MD5',
                'paySign' => $data['sign'],
            ];
            echo json_encode($result);
        }else{
            echo json_encode(['msg' => 'fail']);
        }
}

PHP数组转XML

function arrayToXml($arr){
    $xml = "<xml>";
    foreach ($arr as $key=>$val){
        if(is_array($val)){
            $xml.="<".$key.">".arrayToXml($val)."</".$key.">";
        }else{
            $xml.="<".$key.">".$val."</".$key.">";
        }
    }
    $xml.="</xml>";
    return $xml;
}

PHP XML转数组

function xmlToArray($xml){

    //禁止引用外部xml实体

    libxml_disable_entity_loader(true);

    $xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);

    $val = json_decode(json_encode($xmlstring),true);

    return $val;

}

微信签名函数

function sign($data)
{
    ksort($data);
    $stringA = '';
    foreach ($data as $key => $value) {
        if (!$value || $key == 'sign') continue;
        if ($stringA) $stringA .= '&' . $key . "=" . $value;
        else $stringA = $key . "=" . $value;
    }
    $wx_key = 'xxxxxx';//申请支付后有给予一个商户账号和密码,登陆后自己设置key
    $stringSignTemp = $stringA . '&key=' . $wx_key;
    return strtoupper(md5($stringSignTemp));
}
/**
     * 以post方式提交xml到对应的接口url
     * @param string $xml  需要post的xml数据
     * @param string $url  url
     * @param int $second   url执行超时时间,默认30s
     */
    function postXmlCurl($xml, $url, $second = 30)
    {
        $ch = curl_init();
        $curlVersion = curl_version();
        $m_id = '';//商户号
        $ua = "WXPaySDK/3.0.10 (".PHP_OS.") PHP/".PHP_VERSION." CURL/".$curlVersion['version']." ".$m_id;

        //设置超时
        curl_setopt($ch, CURLOPT_TIMEOUT, $second);

        curl_setopt($ch,CURLOPT_URL, $url);
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE); // 微信DEMO中,此处为TRUE,但使用中会报错
        // curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//严格校验
        curl_setopt($ch,CURLOPT_USERAGENT, $ua);
        //设置header
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        //要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);

        //post提交方式
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        //运行curl
        $data = curl_exec($ch);
        //返回结果
        if($data){
            curl_close($ch);
            return $data;
        } else {
            $error = curl_errno($ch);
            curl_close($ch);
            exit("curl出错,错误码:$error");
        }
    }

GET请求

function getCurl($url) {
    $curl = curl_init($url);
    curl_setopt($curl, CURLOPT_HEADER, 0 ); // 过滤HTTP头
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);// 显示输出结果
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
    // curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);//严格认证
    $responseText = curl_exec($curl);
    curl_close($curl);

    return $responseText;
}

前端

点击支付按钮返回支付数据后调用此函数

payment: function(){
    if (typeof WeixinJSBridge == "undefined"){
        if( document.addEventListener ){
            document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
        }else if (document.attachEvent){
            document.attachEvent('WeixinJSBridgeReady', jsApiCall);
            document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
        }
    }else{
        this.jsApiCall();
    }
}

jsApiCall: function(){
    WeixinJSBridge.invoke(
        'getBrandWCPayRequest',
            { // 此处数据为后端请求微信下单接口正确返回的数据处理后传入
            "appId":"xxxxxx",     //公众号名称,由商户传入     
            "timeStamp":"1395712654",         //时间戳,自1970年以来的秒数     
            "nonceStr":"e61463f8efa94090b1f366cccfbbb444", //随机串     
            "package":"prepay_id=u802345jgfjsdfgsdg888",     
            "signType":"MD5",         //微信签名方式:     
            "paySign":"70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名 
            },
            function(res){
                WeixinJSBridge.log(res.err_msg);
                alert(res.err_code+res.err_desc+res.err_msg);
            }
    ;
}