微信支付之openid获取

一、说明

如果用户在微信客户端中访问第三方网页,公众号可以通过微信网页授权机制,来获取用户基本信息,进而实现支付等业务逻辑。

1.网页授权的两种scope的区别

· 以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx520c15f417810387&redirect_uri=https%3A%2F%2Fchong.qq.com%2Fphp%2Findex.php%3Fd%3D%26c%3DwxAdapter%26m%3DmobileDeal%26showwxpaytitle%3D1%26vb2ctag%3D4_2030_5_1194_60&response_type=code&scope=snsapi_base&state=123#wechat_redirect

· 以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。但这种授权需要用户手动同意。

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxf0e81c3bee622d60&redirect_uri=http%3A%2F%2Fnba.bluewebgame.com%2Foauth_response.php&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect

1.参数说明

参数 是否必须 说明
appid 公众号的唯一标识
redirect_uri 授权后重定向的回调链接地址, 请使用 urlEncode 对链接进行处理
response_type 返回类型,请填写code
scope 应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息 )
state 重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节
#wechat_redirect 无论直接打开还是做页面302重定向时候,必须带此参数

更多内容参考微信开发文档:

https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html

二、实现(只讨论snsapi_base方式获取openid)

1.第一步,重定向获取code(前端页面)

· 以当前打开页面重定向到它本身为例

// 储存记录 code 值var code;// 记录用户的 openidvar openid;// 获取 code 的重定向链接var redirect_uri;// 公众号 idvar wx_appid;// 组合后的获取 code 的微信链接var wx_code_uri;// 本页重定向链接var me_uri;    //窗口导入事件window.onload = function () {
        code = getUrlParam('code') || sessionStorage.code;
        openid = sessionStorage.openid;
        redirect_uri = encodeURIComponent('http://searts.art/');
        wx_appid = 'wx9eca9c23127678f1';
        wx_code_uri = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=' + wx_appid + '&redirect_uri=' + redirect_uri + '&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect';
        me_uri = 'http://searts.art/';document.getElementById("dialogs").innerText = wx_code_uri;var ua = navigator.userAgent.toLowerCase();if (ua.match(/MicroMessenger/i) == "micromessenger") {//判断是否为微信浏览器内getOpenIDAndCode();
        } else {//其他浏览器}
    }
· 如果用户同意授权,页面将跳转至:
redirect_uri链接 + /?code=CODE&state=STATE
如:http://searts.art/?code=CODE&state=STATE

· 页面打开时,将通过 getUrlParam('code')方法或浏览器缓存sessionStorage获取code值, getUrlParam()方法如下:

/**
     * 提取链接中的字段值
     * @param {String} name 待搜索的字段名
     * @param {String} url 被检索的链接,默认为当前网页路径
     * @param {Boolean} raw 是否直接返回取得的结果(即不进行解码操作)
     * @return 对应的字段值,如果该值没有,则返回空串
     */function getUrlParam(name, url, raw) {if (!url) {
            url = window.location.search;
        }if (!name || !url) {return '';
        }var param = '';var reg = new RegExp('(^|&|\\?)' + name + '=([^&#]*)(&|$|#)', 'i');var ret = url.match(reg);if (ret) {
            param = raw ? ret[2] : decodeURIComponent(ret[2]);
        }return param;
    };

· 通过 getOpenIDAndCode() 方法,判断浏览器缓存sessionStorage内是否已经存在code或openid,如果存在code,那么通过post请求将code传给后端接口换取openid等数据,本例使用的自定义post方法为  getOpenIDpost()

//判断openID和codefunction getOpenIDAndCode() {if (!openid) {if (!code) {window.location.replace(wx_code_uri).then(getOpenIDpost());
            } else if (!sessionStorage.code) {
                sessionStorage.code = code;window.location.replace(me_uri).then(getOpenIDpost());
            } else {
                getOpenIDpost();
            }
        }
    }

2.第二步,通过code换取网页授权openid、access_token等数据(服务器端)

· 获取code后,请求以下链接获取openid、access_token等:

https://api.weixin.qq.com/sns/oauth2/access_token?appid={公众号的APPID}&secret={公众号的32位appsecret}&code={前端传入的CODE值}&grant_type=authorization_code

· 后端post接口代码示例如下:

// 获取 openidapp.post('/getopenid', function (req, res) {const code = req.body.code;
    console.log(code);const access_token_url = `https://api.weixin.qq.com/sns/oauth2/access_token?appid=${config.app_id}&secret=${config.app_secret}&code=${code}&grant_type=authorization_code`;request.post({url: access_token_url}, function (error, response, body) {if (error) {
            res.json({error: body});
        } else if (response.statusCode === 200) {if (body.errcode === 40029) {
                res.json({error: body});
            } else {
                body = JSON.parse(body);
                res.json({data: body});
            }
        } else {
            res.json({error: -1});
        }
    });
});
正确返回值body内容如下:
{  "access_token":"ACCESS_TOKEN",//网页授权接口调用凭证
  "expires_in":7200,            //access_token接口调用凭证超时时间,单位(秒)
  "refresh_token":"REFRESH_TOKEN",//用户刷新access_token
  "openid":"OPENID",//用户唯一标识
  "scope":"SCOPE" //用户授权的作用域,使用逗号(,)分隔}

· 至此,openid值已获取到。

(0)

相关推荐