文件
jw-beauty/server/src/lib/wechat.js
T

77 行
2.9 KiB
JavaScript

const https = require('https')
const config = require('../config')
function requestJson(url) {
return new Promise((resolve, reject) => {
https.get(url, res => {
let raw = ''
res.on('data', chunk => { raw += chunk })
res.on('end', () => {
try { resolve(JSON.parse(raw)) } catch (err) { reject(err) }
})
}).on('error', reject)
})
}
function postJson(url, body) {
return new Promise((resolve, reject) => {
const data = JSON.stringify(body || {})
const req = https.request(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(data)
}
}, res => {
let raw = ''
res.on('data', chunk => { raw += chunk })
res.on('end', () => {
try { resolve(JSON.parse(raw)) } catch (err) { reject(err) }
})
})
req.on('error', reject)
req.write(data)
req.end()
})
}
let accessTokenCache = null
async function getAccessToken() {
if (accessTokenCache && accessTokenCache.expiresAt > Date.now() + 60000) return accessTokenCache.token
if (!config.wechat.appid || !config.wechat.secret) throw new Error('WECHAT_APPID or WECHAT_SECRET is not configured')
const url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' + encodeURIComponent(config.wechat.appid) + '&secret=' + encodeURIComponent(config.wechat.secret)
const data = await requestJson(url)
if (!data.access_token) throw new Error(data.errmsg || 'wechat access_token failed')
accessTokenCache = {
token: data.access_token,
expiresAt: Date.now() + (Number(data.expires_in || 7200) * 1000)
}
return accessTokenCache.token
}
async function code2Session(code) {
if (config.nodeEnv === 'development' && (!code || code === 'local' || String(code).indexOf('dev_') === 0)) {
return { openid: 'dev_openid_' + String(code || 'local').slice(-8) }
}
if (!config.wechat.appid || !config.wechat.secret) {
if (config.nodeEnv === 'development') return { openid: 'dev_openid_' + String(code || 'local').slice(-8) }
throw new Error('WECHAT_APPID or WECHAT_SECRET is not configured')
}
const url = 'https://api.weixin.qq.com/sns/jscode2session?appid=' + encodeURIComponent(config.wechat.appid) + '&secret=' + encodeURIComponent(config.wechat.secret) + '&js_code=' + encodeURIComponent(code) + '&grant_type=authorization_code'
const data = await requestJson(url)
if (!data.openid) throw new Error(data.errmsg || 'wechat login failed')
return data
}
async function getPhoneNumber(code) {
if (!code) throw new Error('phone code required')
const token = await getAccessToken()
const url = 'https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=' + encodeURIComponent(token)
const data = await postJson(url, { code })
if (data.errcode) throw new Error(data.errmsg || 'get phone number failed')
return data.phone_info || null
}
module.exports = { code2Session, getPhoneNumber }