这是我在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