微信小程序 - 获取用户session_key, openid - 后端为nodejs, Koa2框架

这是我在csdn的第一篇文章,看了那么多别人的文章,是时候要来贡献一下了。


最近在写小程序,零Nodejs基础上来就写,踩了巨多坑,以后再也不干这种事了。

我的小程序用的是微信的Koa2框架,新建项目的时候开发者工具给的demo。小程序需要获取用户的openid来建立一个数据库。由于自己不会造轮子,那就上网找找别人造的轮子咯。这是我找到的一个合适的(博主名字:意外金喜):点击打开链接。说白了就是抄这位波束的代码啦...这里面有两个坑,我分开来讲。如果有人遇到同样的情况的话,希望我写的东西帮到你们。


第一,wx.request的一个bug。

(也有可能不是bug而是我不会写而已)使用wx.request把用户的登录凭证code发到后端,来换取用户的openid。这是微信给的demo:

wx.request({
  url: 'test.php', //仅为示例,并非真实的接口地址
  data: {
     x: '' ,
     y: ''
  },
  header: {
      'content-type': 'application/json' // 默认值
  },
  success: function(res) {
    console.log(res.data)
  }
})

但是,我的后端接收不到数据!我启动单步调试,用console.log()来看我传了些什么数据,发现根本没有data这个参数。无可奈何,摸索了一番后,我发现可以把code藏在header里面,后端代码读取headers里面的参数来完成传参(如果知道正确的写法,还望不吝赐教)。以下是我的代码(client/utils/wechat.js):

    static request(url, params, method = "POST", type = "application/x-www-form-urlencoded") {
        console.log("向后端传递的参数", params);
        return new Promise((resolve, reject) => {
            let opts = {
                url: url,
                method: method,
                header: { 
                    'Content-Type': type,
                    'accept': params,  
                    },
                success: resolve,
                fail: reject
            }
            console.log("请求的URL", opts.url);
            wx.request(opts);
        });
    };

第二,框架不同语法不同。

由于意外金喜用的是Express框架,跟小程序的Koa有一点点不同,就是这一点点不同卡了我好久(多久就不讲了说出来丢人),直到刚刚看廖雪峰老师的教程才发现(点击打开链接)。这个故事告诉我们,如果要debug,官方文档或者阅读框架的源码是很有用的。

下面是意外金喜的代码(新增的路由):

router.post("/openid", async (req, res) => {
  const Ut = require("../common/utils");
  try {
    console.log(req.body);
    let appId = "wx70xxxxxxbed01b";
    let secret = "5ec6exxxxxx49bf161a79dd4";
    let { js_code } = req.body;
    let opts = {
      url: `https://api.weixin.qq.com/sns/jscode2session?appid=${appId}&secret=${secret}&js_code=${js_code}&grant_type=authorization_code`
    }
    let r1 = await Ut.promiseReq(opts);
    r1 = JSON.parse(r1);
    console.log(r1);
    res.json(r1);
  }
  catch (e) {
    console.log(e);
    res.json('');
  }
})
问题出在 async(req, res) 这里。这是express的写法,但是在Koa,这里的参数是不同的。Koa的写法是 async(req, res) 
其中,参数ctx是由koa传入的封装了request和response的变量,我们可以通过它访问request和response,next是koa传入的将要处理的下一个异步函数。

上面这句数是廖雪峰老师写的。当我照搬意外金喜的代码的时候,就会报错"res.json is not a function",因为res.json是express的东西,在Koa里面是不存在的!

于是我把路由的代码改了一下(server/routers/index.js):

router.post("/openid", async function (ctx, next) {
    const Ut = require("../common/utils");
    console.log('ctx.response: ', ctx.response)
    console.log('ctx.request: ', ctx.request)
    try {
        let grant_type = 'authorization_code'
        let appid = config.appId
        let secret = config.appSecret
        let code = ctx.accept.headers.accept
        console.log('req code: ', code);
        let opts = {
            url: 'https://api.weixin.qq.com/sns/jscode2session?appid=' + appid + '&secret=' + secret + '&js_code=' + code + '&grant_type=' + grant_type
        }
        let r1 = await Ut.promiseReq(opts);
        r1 = JSON.parse(r1);
        console.log('r1 is:', r1);
        openid = r1.openid
        ctx.response.body = openid
    }
    catch (e) {
        console.log(e);
        ctx.response.status = 403
    }
})

把res.json改成ctx.response.body就可以了。

运行结果如下:

login接口获取的code: 061iT8Hv1VtW0b07dWHv1m3SGv1iT8Hj
appservice?t=1530270757816:1084 Fri Jun 29 2018 19:12:42 GMT+0800 (China Standard Time) 接口调整
wechat.js? [sm]:59 getUserInfo接口 {errMsg: "getUserInfo:ok", rawData: "{"nickName":"大大大濤濤","gender":1,"language":"en","ci…rkwjS4R0jca8z8mMXGZ7fwFd9DXsfZY9podNmKh3gGQ/132"}", userInfo: {…}, signature: "a6ea2264b97da6813dff42d6f7ea24969e68490b", encryptedData: "cCrJ0XjJhmmqJWQ0ry3vqebd7Hv6Ixx2p8DMaUwW0YFMGWFqK7…48onyskBK8jwRzGdakk9naOmLXd1paEWYGebEtwldjbTyg/Q=", …}
wechat.js? [sm]:29 向后端传递的参数:  061iT8Hv1VtW0b07dWHv1m3SGv1iT8Hj
wechat.js? [sm]:42 请求的URL:  https://cevgpypz.qcloud.la/weapp/openid
index.js? [sm]:102 从后端获取的openid:  ovvsAxxxxxp9blJ-XvmOxxxxxu2c

你可能感兴趣的:(微信小程序 - 获取用户session_key, openid - 后端为nodejs, Koa2框架)