feat(security): 三端闭环加固 + 微信提现打款/订阅消息落地

后端: 身份与归属鉴权收口; 资金安全(结算闸门/支付防篡改/报名费真实扣款/赠金/结算唯一入账/提现打款); 数据泄露与隐私; 登录与密钥安全(默认密钥闸门/登录限流); 可观测性; 启动自检.

微信: 商家转账到零钱提现打款闭环(含回调/查单/失败退回佣金); 订阅消息真实下发闭环与后台模板字段对齐.

后台: 财务/微信支付配置读取失败锁定; 看板/待办/走势去假数据; 打款与测试推送文案修正.

小程序: 请求层错误透传与登录过期提示; 多页失败反馈与乐观回滚; 帮助中心FAQ页面化.

测试: 新增 40+ 回归护栏与真实 MySQL 冒烟(75 套件/599 用例全绿).
这个提交包含在:
xcbyy
2026-10-17 18:00:09 +08:00
父节点 78117bb4e1
当前提交 2599dce315
共有 70 个文件被更改,包括 3806 次插入 和 330 次删除

查看文件

@@ -17,7 +17,7 @@ export function formatActivityData(raw) {
userId: p.userId,
nickname: p.nickname || `搭子_${p.userId || p.id}`,
avatar: p.avatar || 'https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?w=100',
verifyCode: p.verifyCode || '8392',
verifyCode: p.verifyCode || '',
checkedIn: Boolean(p.checkinStatus || p.checkedIn),
payAmount: p.payAmountCents != null ? p.payAmountCents / 100 : (p.payAmount || 0),
}));
@@ -68,7 +68,7 @@ export async function getActivities() {
*/
export async function getActivityDetail(id) {
try {
const detail = await http.get(`/activities/${id}`);
const detail = await http.get(`/activities/${id}?userId=${normalizeUserId()}`);
if (detail) {
return formatActivityData(detail);
}
@@ -83,7 +83,7 @@ export async function getActivityDetail(id) {
*/
export async function createActivity(payload) {
const body = {
creatorId: payload.creatorId || 1001,
creatorId: normalizeUserId(payload.creatorId),
title: payload.title,
gameCategory: payload.game || payload.gameCategory || '美食陪吃',
location: payload.location,
@@ -110,7 +110,7 @@ export async function createActivity(payload) {
*/
export async function joinActivity(activityId, params = {}) {
const body = {
userId: params.userId || 2008,
userId: normalizeUserId(params.userId),
payAmountCents: Math.round((Number(params.payAmount) || 50) * 100),
};
@@ -155,7 +155,7 @@ export async function adjustActivityPrice(activityId, newPriceYuan, operatorId)
*/
export async function cancelActivity(activityId, hostId = 1001, reason = '房主主动解散') {
return http.post(`/activities/${activityId}/cancel`, {
hostId,
hostId: normalizeUserId(hostId),
reason,
});
}
@@ -165,7 +165,7 @@ export async function cancelActivity(activityId, hostId = 1001, reason = '房主
*/
export async function leaveActivity(activityId, userId = 2001) {
return http.post(`/activities/${activityId}/leave`, {
userId,
userId: normalizeUserId(userId),
});
}
@@ -301,7 +301,7 @@ export function formatOrderData(raw) {
*/
export async function getOrders() {
try {
const list = await http.get('/orders');
const list = await http.get(`/orders?userId=${normalizeUserId()}`);
if (Array.isArray(list) && list.length > 0) {
return list.map(formatOrderData);
}
@@ -334,8 +334,9 @@ export async function cancelOrder(orderId) {
return formatOrderData(res);
} catch (err) {
console.warn('[API] 取消订单网络异常:', err.message);
// 写操作失败必须抛出,供调用方提示并阻止"假成功"
throw err;
}
return null;
}
/**
@@ -343,7 +344,7 @@ export async function cancelOrder(orderId) {
*/
export async function payOrder(orderId, payload = {}) {
try {
const res = await http.post(`/orders/${orderId}/pay`, payload);
const res = await http.post(`/orders/${orderId}/pay`, { ...payload, userId: normalizeUserId(payload.userId) });
return formatOrderData(res);
} catch (err) {
console.warn('[API] 支付订单网络异常:', err.message);
@@ -386,8 +387,9 @@ export async function completeOrder(orderId) {
return formatOrderData(res);
} catch (err) {
console.warn('[API] 确认完成网络异常:', err.message);
// 写操作失败必须抛出,供调用方提示并阻止"假成功"
throw err;
}
return null;
}
/**
@@ -421,7 +423,7 @@ export async function submitReport(payload = {}) {
*/
export async function queryCheckinCode(code) {
try {
const res = await http.get(`/verify/query/${code}`);
const res = await http.get(`/verify/query/${code}?userId=${normalizeUserId()}`);
return res;
} catch (err) {
console.warn('[API] 反查核销码失败:', err.message);
@@ -502,7 +504,7 @@ export async function getPosts(category, userId) {
*/
export async function createPost(payload) {
try {
const res = await http.post('/posts', payload);
const res = await http.post('/posts', { ...(payload || {}), userId: normalizeUserId(payload && payload.userId) });
return res;
} catch (err) {
console.warn('[API] 发布动态异常:', err.message);
@@ -524,7 +526,8 @@ export async function likePost(id, action, userId) {
return res;
} catch (err) {
console.warn('[API] 点赞动态异常:', err.message);
return null;
// 点赞是写操作,失败必须向上抛出,避免调用方误以为已落盘
throw err;
}
}
@@ -687,7 +690,7 @@ export async function getOrdersPool() {
*/
export async function claimOrder(orderId, expertData = {}) {
try {
const res = await http.post(`/orders/${orderId}/claim`, expertData);
const res = await http.post(`/orders/${orderId}/claim`, { ...expertData, userId: normalizeUserId(expertData.userId) });
return res;
} catch (err) {
console.warn('[API] 大神抢单异常:', err.message);
@@ -780,7 +783,7 @@ export async function getMarketingCoupons(category) {
*/
export async function submitOrderReview(orderId, reviewData = {}) {
try {
const res = await http.post(`/orders/${orderId}/review`, reviewData);
const res = await http.post(`/orders/${orderId}/review`, { ...reviewData, userId: normalizeUserId(reviewData.userId) });
return res;
} catch (err) {
console.warn('[API] 提交订单评价异常:', err.message);
@@ -836,7 +839,7 @@ export async function addPostComment(postId, commentData = {}) {
*/
export async function applyPostParty(postId, applyData = {}) {
try {
const res = await http.post(`/posts/${postId}/apply`, applyData);
const res = await http.post(`/posts/${postId}/apply`, { ...applyData, applicantId: normalizeUserId(applyData.applicantId) });
return res;
} catch (err) {
console.warn('[API] 申请搭子上车异常:', err.message);
@@ -996,7 +999,7 @@ export async function replyOrderReview(reviewId, replyContent) {
*/
export async function deletePost(postId, userId) {
try {
const uid = userId || uni.getStorageSync('userId') || 1001;
const uid = normalizeUserId(userId);
const res = await http.delete(`/posts/${postId}?userId=${uid}`);
return res;
} catch (err) {
@@ -1129,7 +1132,7 @@ export async function bindInviteCode(userId, inviteCode) {
*/
export async function getPostApplies(postId) {
try {
const res = await http.get(`/posts/${postId}/applies`);
const res = await http.get(`/posts/${postId}/applies?userId=${normalizeUserId()}`);
return res || [];
} catch (err) {
console.warn('[API] 获取搭子上车申请列表异常:', err.message);
@@ -1196,6 +1199,19 @@ export async function getUserSettings(userId) {
};
}
/**
* 获取微信订阅消息模板ID (用于 wx.requestSubscribeMessage 请求用户授权;模板ID非敏感)
*/
export async function getSubscribeTemplates() {
try {
const res = await http.get('/message/subscribe-templates');
return res || { enablePush: false };
} catch (err) {
console.warn('[API] 获取订阅消息模板异常:', err.message);
return { enablePush: false };
}
}
/**
* 保存用户隐私与通知订阅设置 (同步落盘服务端与本地存储)
*/
@@ -1210,12 +1226,9 @@ export async function updateUserSettings(userId, settings = {}) {
try {
const res = await http.post(`/users/${uid}/settings`, settings);
return res;
} catch (_) {
return {
userId: uid,
privacyHidePhone: uni.getStorageSync('privacy_hide_phone') === '1',
noticeSubscribe: uni.getStorageSync('notice_subscribe') !== '0'
};
} catch (err) {
// 写入失败必须向上抛出,避免调用方误以为已保存
throw err;
}
}