文件
jw-beauty/miniprogram/utils/request.js
T
Guoguo 91d5937d8e feat: implement P0 security and reliability improvements
- bcrypt password hashing with auto-migration from SHA-256
- BLE command retry (3 attempts, 500ms delay, skip on disconnect)
- BLE auto-reconnect with service re-discovery on disconnect
- Treatment page disconnect/reconnect event handling
- Token refresh endpoint with 3-day grace period
- Client-side token auto-refresh when <24h remaining
- Single treatment record detail API with ownership check
2026-04-28 18:12:30 -07:00

116 行
3.4 KiB
JavaScript

var config = require('../config/env')
var API_BASE = config.API_BASE
var _refreshing = false
var _refreshQueue = []
function getTokenExpiry() {
return parseInt(wx.getStorageSync('token_expiry') || '0', 10)
}
function shouldRefresh() {
var expiry = getTokenExpiry()
if (!expiry) return false
var remaining = expiry - Math.floor(Date.now() / 1000)
return remaining > 0 && remaining < 86400
}
function refreshToken() {
if (_refreshing) {
return new Promise(function (resolve, reject) {
_refreshQueue.push({ resolve: resolve, reject: reject })
})
}
_refreshing = true
return new Promise(function (resolve, reject) {
var token = wx.getStorageSync('token')
wx.request({
url: API_BASE + '/api/v1/auth/refresh',
method: 'POST',
header: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' },
data: {},
success: function (res) {
if (res.data && res.data.code === 0 && res.data.data && res.data.data.token) {
wx.setStorageSync('token', res.data.data.token)
wx.setStorageSync('token_expiry', String(Math.floor(Date.now() / 1000) + (res.data.data.expires_in || 604800)))
resolve(res.data.data.token)
_refreshQueue.forEach(function (q) { q.resolve(res.data.data.token) })
} else {
resolve(null)
_refreshQueue.forEach(function (q) { q.resolve(null) })
}
_refreshing = false
_refreshQueue = []
},
fail: function () {
resolve(null)
_refreshQueue.forEach(function (q) { q.resolve(null) })
_refreshing = false
_refreshQueue = []
}
})
})
}
function httpRequest(options) {
var doRequest = function () {
var token = wx.getStorageSync('token')
return new Promise(function (resolve, reject) {
wx.request({
url: API_BASE + options.path,
method: options.method || 'GET',
data: options.data || {},
header: Object.assign({
'Authorization': token ? 'Bearer ' + token : '',
'Content-Type': 'application/json',
'X-App-Version': '1.0.0',
'X-Platform': 'wechat'
}, options.header || {}),
success: function (res) {
if (res.data && res.data.code === 0) {
resolve(res.data.data)
} else if (res.data && res.data.code === 1001 || res.data && res.data.code === 1002) {
wx.removeStorageSync('token')
wx.removeStorageSync('token_expiry')
wx.reLaunch({ url: '/pages/login/login' })
reject(res.data)
} else {
reject(res.data || { code: -1, message: '请求失败' })
}
},
fail: function (err) {
reject({ code: 2002, message: err.errMsg || '网络异常' })
}
})
})
}
if (shouldRefresh() && options.path !== '/api/v1/auth/refresh') {
return refreshToken().then(function () { return doRequest() })
}
return doRequest()
}
function request(options) {
return httpRequest(options)
}
function get(path, data) {
return request({ path: path, method: 'GET', data: data })
}
function post(path, data) {
return request({ path: path, method: 'POST', data: data })
}
function put(path, data) {
return request({ path: path, method: 'PUT', data: data })
}
module.exports = {
request: request,
get: get,
post: post,
put: put,
API_BASE: API_BASE
}