hookehuyr

feat(环境配置): 根据环境变量动态设置BASE_URL并优化页面配置

refactor(API): 移除mock接口,使用真实API调用
docs: 添加微信小程序发布审核指南文档
1 +# 微信小程序发布审核指南(实战版)
2 +
3 +目标:减少“代码审核不通过/反复驳回/二审时间变长”的概率,把风险点提前清掉。
4 +
5 +本文聚焦两类信息:
6 +- 官方明确写在规则/指南里的硬性红线与提审要求
7 +- 开发者高频踩坑(审核员常用驳回口径、容易被机器识别的文案/路径)
8 +
9 +## 1. 提审流程要点(别在流程上翻车)
10 +
11 +### 1.1 提审信息填写
12 +- 服务类目必须与实际功能一致,且“类目对应页面”可直接体验(不隐藏、不多次跳转)
13 +- 简介要写清楚功能点,避免“提高体验/提升效率”等空话,且与名称、功能一致
14 +- 若存在登录/付费/受限功能:必须提供可用测试账号/测试路径/说明,否则按“不可用/不完整”驳回
15 +
16 +官方参考:
17 +- 小程序平台常见拒绝情形(含类目、基本信息、功能完整性等)https://developers.weixin.qq.com/minigame/product/reject
18 +
19 +### 1.2 审核可用性(审核员常用检查方式)
20 +- 从首页出发:两次点击内能到达所有核心功能页(尤其是你在提审页选择的类目对应页面)
21 +- 新用户体验:无缓存/无登录态打开不报错,不出现空白页/死循环 loading
22 +- 弱网/断网:不要直接白屏或无限 toast;至少给明确提示或离线降级
23 +
24 +## 2. 最容易被拒的“写法/文案/入口”
25 +
26 +### 2.1 诱导分享/诱导关注(机器+人工都很敏感)
27 +高风险特征(建议彻底避免):
28 +- “分享/转发/朋友圈/群/邀请” + “奖励/积分/解锁/才能继续”
29 +- “关注公众号/关注后继续/关注领取/关注获取福利”
30 +- 用红点/强提示/遮罩引导用户点击分享
31 +
32 +官方参考(诱导行为规则与处罚):
33 +- 运营规范/诱导分享相关条款(开放文档)https://developers.weixin.qq.com/minigame/product/index.html
34 +- 开放社区:滥用分享违规说明(含深度互动/利益诱导等示例)https://developers.weixin.qq.com/community/business/doc/0000441e234178e10d3d49fe45180d
35 +
36 +### 2.2 外链/跳转到非业务域名(尤其 web-view)
37 +高风险特征:
38 +- 在小程序内直接引导去 H5 付费/登录/完成核心流程
39 +- web-view 打开未配置的业务域名,或用于绕过平台能力限制
40 +
41 +建议:
42 +- 能用小程序原生能力就别用 web-view 承担核心流程
43 +- 如果必须 web-view:业务域名在公众平台“开发-开发设置-业务域名”配置并校验
44 +
45 +### 2.3 “虚拟支付”相关展示(iOS 特别敏感)
46 +典型驳回口径:小程序涉及虚拟产品购买,iOS 不支持,任何引导到支付流程的路径/文案都可能被拒(包含价格展示、购买按钮、引导去公众号/H5/外链付费等)。
47 +
48 +官方/社区案例参考:
49 +- 开放社区驳回示例(含 iOS 虚拟支付常见口径)https://developers.weixin.qq.com/community/develop/doc/000082c5c882c8e25e297442a51400
50 +
51 +注意:
52 +- 这里的“虚拟支付”主要指非实物/数字内容类;线下服务、门票等通常走正常微信支付更常见,但仍要避免“引导去外部支付”这类写法
53 +
54 +## 3. 隐私合规与权限(2023+ 强制门槛,缺了直接拦截)
55 +
56 +### 3.1 必做:配置《用户隐私保护指引》
57 +- 在小程序管理后台按实际情况声明:你收集哪些信息、用途、保存期限、共享对象等
58 +- 若代码调用了微信“隐私接口/组件”,但后台未声明,会直接报无权限(也可能导致提审拦截)
59 +
60 +官方参考:
61 +- 用户隐私保护指引填写说明 https://developers.weixin.qq.com/miniprogram/dev/framework/user-privacy/
62 +- 隐私协议开发指南(含 open-type=agreePrivacyAuthorization 等)https://developers.weixin.qq.com/miniprogram/dev/framework/user-privacy/PrivacyAuthorize.html
63 +
64 +### 3.2 隐私接口/组件常见清单(用到就要声明+授权同步)
65 +常见触发隐私合规校验的能力包括(举例):
66 +- 获取手机号(getPhoneNumber / getRealtimePhoneNumber)
67 +- 获取用户昵称头像组件(如 input type="nickname" 等)
68 +- 位置、相册、摄像头、通讯录、运动步数等相关能力(以官方隐私指引映射为准)
69 +
70 +开发建议:
71 +- 权限申请必须由用户主动触发(按钮点击等),不要在 onLoad/onShow 自动弹授权
72 +- 只申请“用得到的最小权限”,并在 UI 上解释用途(更利于审核员理解)
73 +
74 +## 4. 容易被忽略但会驳回的工程类问题
75 +
76 +### 4.1 “测试页/演示页/调试入口”进入生产包
77 +常见后果:
78 +- 被认定为“功能不完整/不可用/与类目不一致”
79 +- 审核员进入测试页看到“模拟/开发调试/仅开发者工具可用”等字样,直接扣分
80 +
81 +建议:
82 +- 测试页不要出现在生产 pages 列表里(开发环境可保留)
83 +- 不要在正式 UI 中暴露“模拟支付/测试按钮/开发入口”
84 +
85 +### 4.2 空白页、死循环、错误弹窗
86 +常见后果:按“可用性和完整性不符合规则”驳回。
87 +
88 +建议:
89 +- 核心流程必须能走通:预约->提交->支付->成功/失败->订单/二维码展示
90 +- 网络错误要有兜底页或明确提示,避免无限 loading/toast
91 +
92 +## 5. 提交前自检清单(可直接照抄做发布门禁)
93 +
94 +### 5.1 功能可用性
95 +- 新用户冷启动:首页可见内容不空白,不要求先手动操作才能看到任何内容
96 +- 登录/授权:失败有明确提示,且不会无限跳转
97 +- 支付(如有):成功/失败/取消都能回到可理解的状态;无“引导去外部付费”
98 +
99 +### 5.2 合规与文案
100 +- 无“诱导分享/诱导关注/诱导下载/诱导抽奖”的强引导文案或图标
101 +- 无“朋友圈”强指向文案(更建议用“分享给好友”“保存图片”这类中性表述)
102 +- 若涉及用户信息(身份证/手机号等):在产品侧能让用户查看隐私政策入口,后台隐私指引已按实际填写并通过
103 +
104 +### 5.3 生产包清洁度
105 +- pages 列表不包含 demo/test/nfc 等测试页面
106 +- console/error 日志不输出敏感信息(身份证号、手机号、session 等)
107 +
108 +## 6. 发生驳回后的处理套路(提效)
109 +- 严格按驳回点改:只改一类问题,避免一次性改太多导致定位困难
110 +- 截图/录屏给审核员“可复现路径”:从首页点击到具体页,展示已整改
111 +- 不建议频繁撤回重提:重排队成本高;除非重大 bug 才撤回
112 +
113 +社区经验参考(审核节奏、加急等):
114 +- 微信小程序过审指南(经验总结)https://github.com/lingziyao115/miniprogram
1 /* 1 /*
2 * @Date: 2023-08-24 09:42:27 2 * @Date: 2023-08-24 09:42:27
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2026-01-13 18:30:30 4 + * @LastEditTime: 2026-01-13 20:55:13
5 * @FilePath: /xyxBooking-weapp/src/api/index.js 5 * @FilePath: /xyxBooking-weapp/src/api/index.js
6 * @Description: 文件描述 6 * @Description: 文件描述
7 */ 7 */
...@@ -28,6 +28,7 @@ const Api = { ...@@ -28,6 +28,7 @@ const Api = {
28 QUERY_QR_CODE: '/srv/?a=api&t=id_number_query_qr_code', 28 QUERY_QR_CODE: '/srv/?a=api&t=id_number_query_qr_code',
29 ICBC_ORDER_QRY: '/srv/?a=icbc_orderqry', 29 ICBC_ORDER_QRY: '/srv/?a=icbc_orderqry',
30 WX_PAY: '/srv/?a=icbc_pay_wxamp', 30 WX_PAY: '/srv/?a=icbc_pay_wxamp',
31 + // TODO: 3个关于核销的接口都是假的, 等待真实接口
31 VOLUNTEER_LOGIN: '/srv/?a=api&t=volunteer_login', 32 VOLUNTEER_LOGIN: '/srv/?a=api&t=volunteer_login',
32 VERIFY_TICKET: '/srv/?a=api&t=verify_ticket', 33 VERIFY_TICKET: '/srv/?a=api&t=verify_ticket',
33 GET_USER_INFO: '/srv/?a=api&t=get_user_info', 34 GET_USER_INFO: '/srv/?a=api&t=get_user_info',
...@@ -37,51 +38,21 @@ const Api = { ...@@ -37,51 +38,21 @@ const Api = {
37 * @description: 获取用户信息 (Mock) 38 * @description: 获取用户信息 (Mock)
38 */ 39 */
39 export const getUserInfoAPI = () => { 40 export const getUserInfoAPI = () => {
40 - return new Promise((resolve) => { 41 + return fn(fetch.get(Api.GET_USER_INFO));
41 - setTimeout(() => {
42 - // 模拟返回义工信息
43 - resolve({
44 - code: 1,
45 - data: {
46 - id: 'v_001',
47 - name: '义工管理员',
48 - role: 'volunteer',
49 - avatar: 'https://img12.360buyimg.com/imagetools/jfs/t1/196130/38/13621/2930/60c73831E00c07f30/526e068832877520.png'
50 - },
51 - msg: '获取成功'
52 - });
53 - }, 300);
54 - });
55 - // 实际对接后应使用: return fn(fetch.get(Api.GET_USER_INFO));
56 }; 42 };
57 43
58 /** 44 /**
59 * @description: 义工登录 (Mock) 45 * @description: 义工登录 (Mock)
60 */ 46 */
61 export const volunteerLoginAPI = (params) => { 47 export const volunteerLoginAPI = (params) => {
62 - return new Promise((resolve) => { 48 + return fn(fetch.post(Api.VOLUNTEER_LOGIN, params));
63 - setTimeout(() => {
64 - // 简单模拟: 任意非空账号密码即成功,或者指定 admin/123456
65 - if (params.username && params.password) {
66 - resolve({ code: 1, data: { token: 'mock_token' }, msg: '登录成功' });
67 - } else {
68 - resolve({ code: 0, data: null, msg: '账号或密码错误' });
69 - }
70 - }, 500);
71 - });
72 - // 实际对接后应使用: return fn(fetch.post(Api.VOLUNTEER_LOGIN, params));
73 }; 49 };
74 50
75 /** 51 /**
76 * @description: 核销门票 (Mock) 52 * @description: 核销门票 (Mock)
77 */ 53 */
78 -export const verifyTicketAPI = () => { 54 +export const verifyTicketAPI = (params) => {
79 - return new Promise((resolve) => { 55 + return fn(fetch.post(Api.VERIFY_TICKET, params));
80 - setTimeout(() => {
81 - resolve({ code: 1, data: { status: 'success' }, msg: '核销成功' });
82 - }, 500);
83 - });
84 - // 实际对接后应使用: return fn(fetch.post(Api.VERIFY_TICKET, params));
85 }; 56 };
86 57
87 /** 58 /**
......
...@@ -5,8 +5,7 @@ ...@@ -5,8 +5,7 @@
5 * @FilePath: /xyxBooking-weapp/src/app.config.js 5 * @FilePath: /xyxBooking-weapp/src/app.config.js
6 * @Description: 小程序配置文件 6 * @Description: 小程序配置文件
7 */ 7 */
8 -export default { 8 +const pages = [
9 - pages: [
10 'pages/index/index', 9 'pages/index/index',
11 'pages/auth/index', 10 'pages/auth/index',
12 'pages/notice/index', 11 'pages/notice/index',
...@@ -28,19 +27,29 @@ export default { ...@@ -28,19 +27,29 @@ export default {
28 'pages/offlineBookingCode/index', 27 'pages/offlineBookingCode/index',
29 'pages/offlineBookingList/index', 28 'pages/offlineBookingList/index',
30 'pages/offlineBookingDetail/index', 29 'pages/offlineBookingDetail/index',
31 - 'pages/nfcTest/index', 30 +]
32 - 'pages/tailwindTest/index', 31 +
33 - ], 32 +if (process.env.NODE_ENV === 'development') {
34 - subpackages: [ // 配置在tabBar中的页面不能分包写到subpackages中去 33 + pages.push('pages/nfcTest/index')
34 + pages.push('pages/tailwindTest/index')
35 +}
36 +
37 +const subpackages = process.env.NODE_ENV === 'development'
38 + ? [
35 { 39 {
36 root: 'pages/demo', 40 root: 'pages/demo',
37 pages: ['index'], 41 pages: ['index'],
38 }, 42 },
39 - ], 43 + ]
44 + : []
45 +
46 +export default {
47 + pages,
48 + subpackages,
40 window: { 49 window: {
41 backgroundTextStyle: 'light', 50 backgroundTextStyle: 'light',
42 navigationBarBackgroundColor: '#fff', 51 navigationBarBackgroundColor: '#fff',
43 navigationBarTitleText: '西园寺预约', 52 navigationBarTitleText: '西园寺预约',
44 - navigationBarTextStyle: 'black' 53 + navigationBarTextStyle: 'black',
45 - } 54 + },
46 } 55 }
......
1 /* 1 /*
2 * @Date: 2022-09-19 14:11:06 2 * @Date: 2022-09-19 14:11:06
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2026-01-08 16:42:38 4 + * @LastEditTime: 2026-01-13 20:49:09
5 * @FilePath: /xyxBooking-weapp/src/utils/config.js 5 * @FilePath: /xyxBooking-weapp/src/utils/config.js
6 * @Description: 文件描述 6 * @Description: 文件描述
7 */ 7 */
8 // TAG:服务器环境配置 8 // TAG:服务器环境配置
9 -const BASE_URL = "https://oa-dev.onwall.cn"; // 测试服务器 9 +const BASE_URL = process.env.NODE_ENV === 'production'
10 -// const BASE_URL = "https://oa.onwall.cn"; // 正式服务器 10 + ? 'https://oa.onwall.cn'
11 + : 'https://oa-dev.onwall.cn'
11 12
12 /** 13 /**
13 * 接口默认公共参数(避免在多个文件里硬编码) 14 * 接口默认公共参数(避免在多个文件里硬编码)
......