Appearance
开发微信公众号遇到的一些坑和过程记录...
开发环境
LeanCloud, Node.js 4.x, express 4 安装命令行工具 npm install -g avoscloud-code
微信公众号开发指南
注册账号
微信公众号分个人订阅号和公司的服务号
- 微信公众平台 注册服务号。
- 微信开放平台 绑定个人测试号,可以测试除了微信支付以外的所有功能。
- 微信商户平台 实现微信支付功能。
- LeanCloud 一站式后端云服务,应用服务器和存储服务器。
- 七牛 用于存储音频并转码 amr 为 mp3。
配置账号
- LeanCloud 新建一个应用并获取
App ID
App Key
Master Key
并设置 Web 主机域名 - 七牛新建一个存储空间和一个多媒体处理资源并获取
Access Key
Secret Key
测试域名
- 公众号后台,
开发
->基本配置
获取App ID
App Secret
- 公众号后台,
开发
->基本配置
->服务器配置
配置相关信息,用户消息将会发送给这里配置的服务器 - 公众号后台,
设置
->公众号设置
->功能设置
设置 JS接口安全域名 - 公众号后台,
开发
->接口权限
->网页授权获取用户基本信息
->修改
设置 授权回调页面域名,用户网页授权之后授权信息会返回到这个域名 - 公众号后台,
微信支付
->开发配置
->公众号支付
设置 支付授权目录 和测试配置 - 商户号后台获取
mch id
partner key
apiclient_cert.p12
- 公众号后台,
功能
->模版消息
添加需要的模版并获取模版 ID
依赖包
wechat
接收和自动回复公众号消息 wechat-oauth
接收 appid 和 appkey 生成网页授权链接 wechat-api
主动调用 api, 发送模版消息 weixin-pay
微信支付相关,公众号支付和企业支付 qiniu
将音频从微信服务器下载到七牛空间并转码
设置公众号菜单
直接 node menu.js
js
// menu.js
var config = require('../../config');
var API = require('wechat-api');
var api = new API(config.appid, config.appsecret);
var menu = JSON.stringify(require('./menu.json'));
api.createMenu(menu, function(err, result) {
console.log(result);
});
js
// menu.json
{
"button": [{
"type": "view",
"name": "主页",
"url": "http://myapp.leanapp.cn"
}, {
"name": "下载应用",
"sub_button": [{
"type": "view",
"name": "Android 版",
"url": "http://myapp.leanapp.cn/app/android"
}, {
"type": "view",
"name": "iOS 版",
"url": "http://myapp.leanapp.cn/app/ios"
}]
}]
}
创建项目
lean new
创建新的 LeanCloud 云引擎项目- 安装依赖:修改
package.json
并npm install -f
npm update <packageName>
更新到最新版本 - 项目根目录新建一个文件夹
secure
把商户号的证书放进去并新建一个config.js
把所有的 ID 和 Key 放进去
json
module.exports = {
"token": "token",
"appid": "appid",
"appsecret": "appsecret",
"encodingAESKey": "encodingAESKey",
"mchid": "mchid",
"partnerKey": "partnerKey",
"hostname": "http://myapp.leanapp.cn",
"qiniuAccessKey": "qiniuAccessKey",
"qiniuSecretKey": "qiniuSecretKey"
};
项目开发
- 编写静态页面:为了测试方便可以把项目的模版引擎先修改为纯 html
- 添加测试数据
- 设计 api:在服务器封装好可以避免密钥泄漏
- 编写路由
routes
- 编写云函数
奇技淫巧
域名问题
微信支付开发的时候需要各种设置域名,甚至要求备案后的域名。 这时候就可以搞一个域名指向本机的 ip,方便调试。为了测试微信支付的回调,可以使用 ngrok 将本地服务器暴露给公网。 因为不同阶段测试的时候需要修改域名,所有将域名放在配置文件中,需要域名的时候直接从配置中读取。
打印请求的 url
js
app.use(function(req, res, next) {
console.log('req: ' + req.ip + '' + req.url);
var d = null;
if (process.domain) {
d = process.domain;
} else {
d = domain.create();
}
d.run(next);
});
使用一个单独的类缓存一些信息
举个🌰使用 auth.js
缓存用户授权信息和登录状态,同时还可以保存一些常用当时获取需要消耗一些计算资源的数据,避免重复获取。还可以缓存 access_token 和 ticket 并定时刷新,不用每次都判断 token 过期的问题。 再举个🌰使用 trade.js
缓存交易信息,在微信支付成功后可以根据商户号获取交易信息进行后续处理。
引入 jquery
html
<script src="//cdn.bootcss.com/jquery/3.0.0/jquery.min.js"></script>
<script>
window.jQuery || document.write('<script src="js/jquery.min.js"><\/script>')
</script>
html
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0">
<link rel="shortcut icon" href="/favicon.ico"/>
LeanCloud 监听文件修改自动重启服务器
默认所有的文件修改都会导致服务器重启,然而一些文件的修改并不需要重启服务器。这时候就可以更目录添加 nodemon 配置文件。
json
{
"restartable": "rs",
"ignore": [
".git",
"node_modules/**/node_modules",
"public",
"views",
"secure",
"others"
],
"verbose": true,
"execMap": {
"js": "node --harmony"
},
"watch": [
"routes",
"app.js",
"server.js"
],
"env": {
"NODE_ENV": "development"
},
"ext": "js json css html"
}
问题记录
问:获取网站的 favicon 答:访问 域名/favicon.ico
问:node 使用 html 作为模版引擎 答:app.engine('html', require('ejs').renderFile);
问:LeanCloud node 版本? 答:在 package.json 配置可选4.x
问:通过 ajax 发起跳转请求会出现,JS 跨域请求问题。 答:不要设置什么 headers 了,没用。直接把链接发给浏览器,让浏览器自己跳转。
问:微信支付,生成订单失败 这里可以把
weixin-pay
的两个文件单独取出来,修改文件添加 log 来调试 答:req.ip
获取的 ip 是 ipv6 的,把 ::ffff:
去掉就OK了
问:微信支付,成功后的回调失败 答:支付成功的回调是由微信服务器发起的,所有我们的服务器要有公网ip,使用 ngrok 可暂时解决;另外一个原因是要设置支付目录。
问:七牛回调问题 答:调用的时候传入一个回调函数
问:LeanCloud AV.Query skip 会出现循环 答:只有 relation 的 query 才会循环 skip。
问:录音音频格式问题 答:微信录音的文件是 amr,Android 版微信可以播放但 iOS 的不行,所以要用七牛转码为 mp3。
问:安卓版微信浏览器不执行 js 答:必然是某个地方语法错了,虽然其他浏览器都没有报错🙄️ 排查之后发现是 for...of
语法不支持。。 检测浏览器对 es6 的支持