⚠️ MVP 阶段说明
本项目为全新项目,尚未上线,当前处于 MVP(最小可行产品)阶段。
本文档描述的是 MVP 版本的接口定义,后续会根据业务需求持续迭代。版本:v1.1-MVP | 更新日期:2026-07-01 | 状态:开发中
Base URL:http://localhost:8080
| Header | 说明 |
|---|---|
| Content-Type | application/json |
| Authorization | Bearer {accessToken}(需认证接口) |
{
"code": 200,
"message": "success",
"data": {}
}
| code | 说明 |
|---|---|
| 200 | 成功 |
| 400 | 参数错误 |
| 401 | 未认证 |
| 403 | 无权限 |
| 404 | 资源不存在 |
| 429 | 请求过于频繁 |
| 500 | 服务器内部错误 |
所有列表查询接口使用统一的分页响应格式:
{
"code": 200,
"message": "success",
"data": {
"total": 100,
"page": 1,
"size": 20,
"records": [
{...}
]
}
}
| 字段 | 类型 | 说明 |
|---|---|---|
| total | Integer | 总记录数 |
| page | Integer | 当前页码(从1开始) |
| size | Integer | 每页数量 |
| records | Array | 当前页的数据列表 |
参数错误:
{
"code": 400,
"message": "手机号格式不正确",
"data": null
}
配额不足:
{
"code": 400,
"message": "每日配额已用完,请升级会员或等待明天",
"data": null
}
资源不存在:
{
"code": 404,
"message": "未找到该平台的绑定记录",
"data": null
}
未认证:
{
"code": 401,
"message": "Token已过期,请重新登录",
"data": null
}
无权限:
{
"code": 403,
"message": "需要管理员权限",
"data": null
}
POST /api/auth/sms/send
请求体:
{
"phone": "13800138000"
}
响应:
{ "code": 200, "message": "success", "data": null }
POST /api/auth/sms/login
请求体:
{
"phone": "13800138000",
"code": "123456",
"inviteCode": "ABC123" // 可选,邀请码
}
响应:
{
"code": 200,
"data": {
"accessToken": "eyJhbGciOi...",
"refreshToken": "eyJhbGciOi...",
"userId": 1,
"nickname": "用户138****0000",
"avatar": null,
"phone": "13800138000",
"newUser": false
}
}
GET /api/auth/wechat/url?state=login
响应:
{
"code": 200,
"data": "https://open.weixin.qq.com/connect/qrconnect?appid=xxx&redirect_uri=xxx"
}
POST /api/auth/wechat/login
请求体:
{
"code": "wx_auth_code_xxx",
"state": "login"
}
响应: 同 1.2
POST /api/auth/wechat/bind
请求体:
{
"wechatCode": "wx_auth_code_xxx",
"phone": "13800138000",
"smsCode": "123456",
"inviteCode": "ABC123" // 可选
}
响应: 同 1.2
GET /api/auth/wechat/callback?code=xxx&state=xxx
响应:
{ "code": 200, "data": "https://your-domain.com/wechat-login?code=xxx" }
POST /api/auth/refresh
请求体: refreshToken字符串
响应: 同 1.2
GET /api/auth/user/info
需要认证
响应:
{
"code": 200,
"message": "success",
"data": {
"userId": 1,
"phone": "13800138000",
"nickname": "用户138****0000",
"avatar": null,
"levelName": "普通用户",
"levelCode": "NORMAL",
"pharmacyName": "XX大药房",
"loginSource": "WINDOWS",
"lastLoginDevice": "Windows 10 - WebView2",
"configVersionId": 1,
"version": "v1.0"
}
}
字段说明:
pharmacyName: 药店名称(可选)loginSource: 登录来源(WINDOWS/MINIAPP/ANDROID/IOS/WECHAT)lastLoginDevice: 最后登录设备信息configVersionId: 当前使用的等级配置版本IDversion: 当前使用的等级配置版本号GET /api/crawler/status
需要认证
响应:
{
"code": 200,
"data": {
"levelName": "普通会员",
"levelCode": "PLUS",
"todayUsed": 2,
"todayQuota": 15,
"todayRemaining": 13,
"monthUsed": 30,
"monthQuota": 315,
"monthRemaining": 285,
"yearUsed": 100,
"yearQuota": 3665,
"yearRemaining": 3565,
"baseDailyQuota": 10,
"baseMonthlyQuota": 300,
"baseYearlyQuota": 3650,
"extraQuota": 5,
"extraQuotaBreakdown": [
{
"sourceType": "INVITE",
"sourceName": "邀请奖励",
"available": 3,
"total": 5,
"used": 2
},
{
"sourceType": "ADMIN",
"sourceName": "运营发放",
"available": 2,
"total": 10,
"used": 8
}
],
"maxConcurrent": 1,
"hasCoupon": true,
"availableCouponCount": 2
}
}
字段说明:
levelName/levelCode: 当前用户会员等级名称和编码todayUsed/todayQuota/todayRemaining: 今日已用/总配额/剩余monthUsed/monthQuota/monthRemaining: 本月已用/总配额/剩余yearUsed/yearQuota/yearRemaining: 本年已用/总配额/剩余(无年配额时为null)baseDailyQuota/baseMonthlyQuota/baseYearlyQuota: 等级基础配额(不含额外配额)extraQuota: 额外配额总额(邀请+运营+购买三种来源之和)extraQuotaBreakdown: 额外配额来源明细maxConcurrent: 最大并发数hasCoupon/availableCouponCount: 是否有可用优惠券 / 可用数量POST /api/crawler/consume
需要认证
业务场景: 药店采购人员搜索药品后,选择多个医药B2B平台进行比价,系统爬取各平台价格并生成采购链接。
请求体:
{
"count": 1,
"useCouponFirst": false,
"platform": "yaoshibang"
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| count | Integer | 是 | 消耗次数(至少为1) |
| useCouponFirst | Boolean | 否 | 是否优先使用优惠券,默认false |
| platform | String | 否 | 爬取平台代码(见下方平台列表) |
支持的医药平台列表:
✅ MVP启用的3个核心平台:
yaoshibang - 药师帮(国内领先医药B2B平台)yaobangmang - 药帮忙(医药B2B采购平台)yiyaocheng - 1药城(B2B医药批发平台)🚀 后续扩展平台(Phase 2-6):
B2B批发平台(12个):
yaojingcai - 药京采、jianzhijia - 健之佳、kangaiduoduo - 康爱多alihealth - 阿里健康、sinopharm - 国药控股、jointown - 九州通zhencheng - 珍诚医药、yaoyitong - 药易通、hezong - 合纵药易购yicaotang - 宜草堂、yaodu - 药都在线、yaocaiying - 药材盈B2C零售平台(8个):
dingdang - 叮当快药、quanyuantang - 泉源堂、dashenlin - 大参林laobaixing - 老百姓大药房、yixintang - 一心堂、yifeng - 益丰大药房haiwang - 海王星辰、guoda - 国大药房综合电商医药频道(7个):
jd_health - 京东健康、tmall_pharma - 天猫医药、pdd_pharma - 拼多多医药douyin_pharma - 抖音医药、kuaishou_pharma - 快手医药meituan_pharma - 美团买药、eleme_pharma - 饿了么医药垂直医药平台(4个):
weyi - 微医、pingan_good - 平安好医生chunyu - 春雨医生、haodf - 好大夫在线其他:
other - 其他平台说明:MVP阶段仅启用前3个B2B平台,其他平台将在后续版本中逐步开放。
响应:
{ "code": 200, "data": true }
支持的医药平台列表(34个全渠道):
B2B批发平台(15个 - 药店主要采购渠道):
yaoshibang - 药师帮(国内最大医药B2B平台)yaojingcai - 药京采(京东健康旗下医药B2B)jianzhijia - 健之佳(云南健之佳医药B2B)1yao - 1药网(B2B医药批发平台)kangaiduoduo - 康爱多(医药电商B2B)alihealth - 阿里健康(天猫医药馆B2B)sinopharm - 国药控股(国药集团B2B平台)jointown - 九州通(九州通医药B2B)zhencheng - 珍诚医药(浙江地区知名医药B2B)yaoyitong - 药易通(西南地区医药B2B平台)hezong - 合纵药易购(四川地区医药B2B)yicaotang - 宜草堂(华中地区医药B2B)yaodu - 药都在线(安徽亳州药材市场B2B)yaocaiying - 药材盈(中药材B2B交易平台)B2C零售平台(8个 - 小批量采购/急单):
dingdang - 叮当快药(O2O即时配送,适合急单)quanyuantang - 泉源堂(连锁药店B2C平台)dashenlin - 大参林(广东连锁药店B2C)laobaixing - 老百姓大药房(全国连锁B2C)yixintang - 一心堂(云南连锁药店B2C)yifeng - 益丰大药房(华中连锁药店B2C)haiwang - 海王星辰(全国连锁药店B2C)guoda - 国大药房(国药旗下连锁药店B2C)综合电商医药频道(7个 - 价格参考):
jd_health - 京东健康tmall_pharma - 天猫医药pdd_pharma - 拼多多医药douyin_pharma - 抖音医药kuaishou_pharma - 快手医药meituan_pharma - 美团买药eleme_pharma - 饿了么医药垂直医药平台(4个 - 特色渠道):
weyi - 微医(互联网医院+药品销售)pingan_good - 平安好医生(平安集团医疗健康平台)chunyu - 春雨医生(在线问诊+药品销售)haodf - 好大夫在线(医疗服务平台)
other - 其他平台
GET /api/crawler/logs?days=7
需要认证
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| days | int | 7 | 查询最近N天 |
响应:
{
"code": 200,
"data": [
{
"id": 1,
"userId": 1,
"usageDate": "2026-06-16",
"usageCount": 3,
"platform": "yaoshibang",
"source": "QUOTA",
"remark": null,
"createTime": "2026-06-16T10:30:00"
}
]
}
字段说明:
platform: 爬取平台(yaoshibang/yaojingcai/jianzhijia等医药B2B平台)source: 消耗来源(QUOTA-配额、COUPON-优惠券、MIXED-混合)remark: 备注信息业务价值:
GET /api/invite/code
需要认证
响应:
{
"code": 200,
"data": {
"code": "ABC123",
"inviteLink": "https://app.zhijiayun.com/invite/ABC123",
"maxUses": -1,
"usedCount": 5,
"clickCount": 12,
"expireTime": "2026-07-16T00:00:00",
"status": 1,
"createTime": "2026-06-16T10:00:00",
// 分享相关字段
"shareTitle": "邀请你加入智价云(药店版)",
"shareDescription": "高效商品数据采集工具",
"copyText": "邀请你加入智价云(药店版)\n高效商品数据采集工具\n邀请码:ABC123\n点击链接下载:\nhttps://app.zhijiayun.com/invite/ABC123",
"rewardDescription": "注册即送5次爬虫额度"
}
}
字段说明:
copyText: 一键复制文本,包含标题、描述、邀请码和链接,用户可直接复制到微信分享shareTitle: 微信分享时的标题shareDescription: 微信分享时的描述rewardDescription: 奖励说明,用于展示给被邀请人GET /api/invite/stats
需要认证
响应:
{
"code": 200,
"data": {
"invitedCount": 5,
"registeredCount": 3,
"clickedCount": 12,
"totalRewardQuota": 21,
"summaryText": "已邀请5人,3人注册 +21次",
"inviteLink": "https://your-domain.com/invite/ABC123"
}
}
GET /api/invite/rewards
需要认证
响应:
{
"code": 200,
"data": [
{
"inviteeId": 2,
"inviteeNickname": "用户139****1111",
"rewardQuota": 5,
"registered": true,
"registeredText": "已注册",
"createTime": "2026-06-10T10:00:00"
}
]
}
GET /api/invite/extra-quota
需要认证
响应:
{ "code": 200, "data": 15 }
GET /api/invite/page/{code}?channel=app
无需认证
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| code | String | 是 | 邀请码 |
| channel | String | 否 | 渠道:app/wechat/miniapp/dingtalk/feishu,默认app |
响应:
{
"code": 200,
"data": {
"inviterNickname": "用户138****0000",
"inviterAvatar": "https://...",
"inviteCode": "ABC123",
"downloadUrl": "https://download.example.com/app.exe",
"landingTitle": "邀请你加入智价云(药店版)",
"landingDesc": "高效商品数据采集工具",
"appName": "智价云(药店版)",
"channel": "app",
"openType": "download",
"miniappPath": null,
"miniappId": null,
"wechatRedirectUrl": null,
"rewardPerRegister": 5,
// 客户端自动填入支持
"autoFillSupported": true,
"urlScheme": "zhijiayun://invite?code=ABC123",
"deepLink": "https://app.zhijiayun.com/invite/ABC123?autoFill=true",
"instructionText": "下载安装后,在注册页面输入邀请码:智价云(药店版) 或点击链接自动填入"
}
}
字段说明:
urlScheme: URL Scheme,用于唤醒已安装的客户端并自动填入邀请码(如 zhijiayun://invite?code=ABC123)deepLink: 通用深度链接,iOS/Android都支持instructionText: 操作提示文案,根据渠道动态生成autoFillSupported: 是否支持自动填入(始终为true)使用场景:
urlScheme 唤醒客户端POST /api/invite/click/{code}
无需认证
响应:
{ "code": 200, "data": null }
POST /api/coupon/issue
请求体:
{
"couponId": 1,
"userIds": [1, 2, 3],
"validDays": 30
}
响应:
{ "code": 200, "data": 3 }
GET /api/coupon/my?status=0
需要认证
| 参数 | 类型 | 说明 |
|---|---|---|
| status | Integer | 可选,0-未使用 1-已使用 2-已过期 |
响应:
{
"code": 200,
"data": [
{
"id": 1,
"couponName": "爬虫次数+10",
"type": "CRAWLER",
"value": 10,
"status": 0,
"expireTime": "2026-07-16T00:00:00",
"source": "ISSUE"
}
]
}
GET /api/coupon/my/available?type=CRAWLER
需要认证
GET /api/level/list
响应:
{
"code": 200,
"data": [
{
"id": 1,
"levelName": "普通用户",
"levelCode": "NORMAL",
"crawlerQuota": 5,
"monthlyQuota": 100,
"maxConcurrent": 1,
"description": "每日5次爬虫,每月100次"
}
]
}
GET /api/level/{id}
GET /api/level/my
需要认证
PUT /api/level/user/{userId}?levelId=2
GET /api/admin/invite/config
PUT /api/admin/invite/config
请求体:
{
"rewardCrawlerCount": 5,
"maxDailyReward": 50,
"inviteCodeExpireDays": 30,
"maxInvitePerDay": 10,
"appDownloadUrl": "https://download.example.com/app.exe",
"miniappPath": "/pages/download/index",
"miniappId": "wx1234567890",
"wechatRedirectUrl": "https://mp.weixin.qq.com/xxx",
"dingtalkAppId": "dingxxx",
"feishuAppId": "feishuxxx",
"landingTitle": "邀请你加入智价云(药店版)",
"landingDesc": "高效商品数据采集工具",
"appName": "智价云(药店版)"
}
GET /api/admin/invite/configs
POST /api/admin/crawler/grant
请求体:
{
"userId": 1,
"quotaCount": 50,
"expireDays": 30,
"remark": "VIP升级奖励"
}
GET /api/admin/crawler/grants?userId=1&grantType=ADMIN
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| userId | Long | 否 | 指定用户 |
| grantType | String | 否 | INVITE/PURCHASE/ADMIN |
GET /api/admin/invite/rewards?userId=1
GET /api/admin/crawler/user-detail?userId=1
需要认证
响应:
{
"code": 200,
"data": {
"userId": 1,
"nickname": "测试药店",
"phone": "138****8000",
"todayTotalUsage": 5,
"monthlyTotalUsage": 30,
"platformStats": [
{
"platformCode": "yaoshibang",
"platformName": "药师帮",
"todayUsage": 3,
"monthlyUsage": 15,
"totalUsage": 50
},
{
"platformCode": "yaojingcai",
"platformName": "药京采",
"todayUsage": 2,
"monthlyUsage": 10,
"totalUsage": 30
}
]
}
}
支持的医药平台(34个全渠道):
B2B批发平台: yaoshibang, yaojingcai, jianzhijia, 1yao, kangaiduoduo, alihealth, sinopharm, jointown, zhencheng, yaoyitong, hezong, yicaotang, yaodu, yaocaiying
B2C零售平台: dingdang, quanyuantang, dashenlin, laobaixing, yixintang, yifeng, haiwang, guoda
综合电商医药频道: jd_health, tmall_pharma, pdd_pharma, douyin_pharma, kuaishou_pharma, meituan_pharma, eleme_pharma
垂直医药平台: weyi, pingan_good, chunyu, haodf
业务价值:
GET /api/admin/invite/conversion-stats?userId=1
需要认证
响应:
{
"code": 200,
"data": {
"inviteCode": "ABC123",
"clickedCount": 50,
"totalInvited": 10,
"registeredCount": 8,
"pendingCount": 2,
"conversionRate": 16.0,
"totalReward": 40
}
}
字段说明:
clickedCount: 邀请链接被打开次数totalInvited: 总邀请人数(点击后访问落地页的人数)registeredCount: 已注册人数pendingCount: 待注册人数(点击但未注册)conversionRate: 注册转化率(百分比,计算公式:已注册人数 / 点击次数 × 100%)totalReward: 累计奖励爬虫次数POST /api/platform-account/bind
需要认证
请求体:
{
"platformCode": "yaoshibang",
"platformName": "药师帮",
"account": "13800138000",
"password": "your_password"
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| platformCode | String | 是 | 平台代码(yaoshibang/yaobangmang/yiyaocheng) |
| platformName | String | 是 | 平台名称 |
| account | String | 是 | 平台账号(手机号或用户名) |
| password | String | 是 | 平台密码(服务端AES-256加密存储) |
响应:
{ "code": 200, "message": "success", "data": null }
注意事项:
说明:
DELETE /api/platform-account/unbind/{platformCode}
需要认证
路径参数:
platformCode: 平台代码(如:yaoshibang)响应:
{ "code": 200, "message": "success", "data": null }
GET /api/platform-account/list
需要认证
响应:
{
"code": 200,
"data": [
{
"id": 1,
"platformCode": "yaoshibang",
"platformName": "药师帮",
"account": "138****8000",
"enabled": true,
"verifyStatus": "SUCCESS",
"lastVerifyTime": "2026-06-16T10:30:00",
"failReason": null,
"createTime": "2026-06-15T09:00:00"
}
]
}
字段说明:
account: 脱敏后的账号(前3位+****+后4位)verifyStatus: PENDING-待验证 / SUCCESS-成功 / FAILED-失败POST /api/platform-account/verify/{platformCode}
需要认证
路径参数:
platformCode: 平台代码响应:
{ "code": 200, "message": "success", "data": null }
说明:
POST /api/business-license/upload
需要认证
请求体:
{
"licenseImageUrl": "https://oss.example.com/license/xxx.jpg",
"creditCode": "91110000XXXXXXXXXX",
"pharmacyName": "XX大药房",
"legalPerson": "张三"
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| licenseImageUrl | String | 是 | 营业执照图片URL(需先上传到OSS) |
| creditCode | String | 是 | 统一社会信用代码(18位) |
| pharmacyName | String | 是 | 药店名称 |
| legalPerson | String | 否 | 法人姓名 |
响应:
{ "code": 200, "message": "success", "data": null }
注意事项:
GET /api/business-license/info
需要认证
响应:
{
"code": 200,
"data": {
"id": 1,
"licenseImageUrl": "https://oss.example.com/license/xxx.jpg",
"creditCode": "91110000XXXXXXXXXX",
"pharmacyName": "XX大药房",
"reviewStatus": "APPROVED",
"reviewTime": "2026-06-16T10:00:00",
"rejectReason": null,
"showVerifiedBadge": true,
"createTime": "2026-06-15T09:00:00"
}
}
字段说明:
reviewStatus: PENDING-待审核 / APPROVED-已通过 / REJECTED-已驳回GET /api/platform-config/enabled
响应:
{
"code": 200,
"data": [
{
"platformCode": "yaoshibang",
"platformName": "药师帮",
"enabled": true,
"requiresRecharge": false,
"queryCost": 1,
"priority": 1,
"underMaintenance": false,
"bindingInstructions": "请输入您在药师帮平台的手机号和密码"
}
]
}
GET /api/platform-config/{platformCode}
路径参数:
platformCode: 平台代码响应:
{
"code": 200,
"data": {
"platformCode": "yaoshibang",
"platformName": "药师帮",
"enabled": true,
"requiresRecharge": false,
"queryCost": 1,
"priority": 1,
"underMaintenance": false,
"maintenanceNotice": null,
"bindingInstructions": "请输入您在药师帮平台的手机号和密码"
}
}
GET /api/trial-quota/active
响应:
{
"code": 200,
"data": {
"configName": "新用户默认体验",
"trialDays": 15,
"dailyQueryLimit": 20,
"monthlyWatchlistLimit": 199,
"configType": "DEFAULT",
"applicableUserType": "NEW_USER",
"description": "新用户注册后自动获得的体验配额"
}
}
GET /api/admin/trial-quota/configs
需要管理员权限
响应:
{
"code": 200,
"data": [
{
"id": 1,
"configName": "新用户默认体验",
"trialDays": 15,
"dailyQueryLimit": 20,
"monthlyWatchlistLimit": 199,
"enabled": true,
"configType": "DEFAULT",
"currentUsers": 1250,
"maxUsers": null
}
]
}
POST /api/admin/trial-quota/config
需要管理员权限
请求体:
{
"configName": "春节活动体验券",
"trialDays": 7,
"dailyQueryLimit": 30,
"monthlyWatchlistLimit": 300,
"configType": "ACTIVITY",
"applicableUserType": "ALL",
"effectiveFrom": "2026-02-01T00:00:00",
"effectiveTo": "2026-02-15T23:59:59",
"maxUsers": 1000,
"description": "春节期间特别活动"
}
响应:
{ "code": 200, "message": "success", "data": null }
PUT /api/admin/trial-quota/config/{id}
需要管理员权限
请求体: 同创建接口
响应:
{ "code": 200, "message": "success", "data": null }
DELETE /api/admin/trial-quota/config/{id}
需要管理员权限
响应:
{ "code": 200, "message": "success", "data": null }
8002## 11. 活动模块 /api/activity & /api/checkin & /api/admin/activity & /api/admin/checkin
模块说明:活动模块(zhijiayun-activity)统一管理签到有礼、邀请有礼、签到送会员、比价抽奖等运营活动。
用户端接口前缀/api/checkin、/api/activity;运营端接口前缀/api/admin/checkin、/api/admin/activity。
GET /api/checkin/status
需要认证
响应:
{
"code": 200,
"data": {
"checkedToday": true,
"continuousDays": 5,
"todayReward": 2,
"baseReward": 1,
"continuousReward": 1,
"continuousThreshold": 7,
"continuousCap": 30
}
}
| 字段 | 类型 | 说明 |
|---|---|---|
| checkedToday | Boolean | 今日是否已签到 |
| continuousDays | Integer | 连续签到天数 |
| todayReward | Integer | 今日签到可得奖励(基础+连续额外) |
| baseReward | Integer | 基础奖励 |
| continuousReward | Integer | 连续达成后额外奖励 |
| continuousThreshold | Integer | 连续阈值(达到后额外奖励生效) |
| continuousCap | Integer | 连续额外奖励上限 |
POST /api/checkin
需要认证
请求参数: clientSource(可选:WINDOWS/ANDROID/MINIAPP)
响应:
{
"code": 200,
"data": {
"id": 123,
"userId": 1,
"checkinDate": "2026-07-07",
"rewardCount": 2,
"continuousDays": 5,
"createTime": "2026-07-07T10:00:00"
}
}
GET /api/checkin/calendar?year=2026&month=7
需要认证
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| year | Integer | 否 | 年份,默认当前年 |
| month | Integer | 否 | 月份,默认当前月 |
响应:
{
"code": 200,
"data": {
"checkedDates": ["2026-07-01", "2026-07-02", "2026-07-05"],
"year": 2026,
"month": 7
}
}
GET /api/checkin/records?limit=30
需要认证
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| limit | Integer | 否 | 返回条数,默认30 |
响应:
{
"code": 200,
"data": [
{
"id": 123,
"userId": 1,
"checkinDate": "2026-07-07",
"rewardCount": 2,
"continuousDays": 5,
"clientSource": "WINDOWS",
"createTime": "2026-07-07T10:00:00"
}
]
}
GET /api/admin/checkin/config
需要管理员权限
响应:
{
"code": 200,
"data": {
"id": 1,
"enabled": 1,
"rewardType": "CRAWLER",
"baseReward": 1,
"continuousReward": 1,
"continuousThreshold": 7,
"continuousCap": 30,
"rewardExpireDays": 30,
"remark": "默认签到配置"
}
}
PUT /api/admin/checkin/config
需要管理员权限
请求体:
{
"enabled": 1,
"rewardType": "CRAWLER",
"baseReward": 1,
"continuousReward": 1,
"continuousThreshold": 7,
"continuousCap": 30,
"rewardExpireDays": 30,
"remark": "默认签到配置"
}
GET /api/admin/checkin/stats
需要管理员权限
响应:
{
"code": 200,
"data": {
"todayCheckinCount": 50,
"yesterdayCheckinCount": 45,
"last7DaysCheckinCount": 320,
"last30DaysCheckinCount": 1200,
"totalCheckinCount": 5000,
"totalCheckinUsers": 800,
"totalRewardGranted": 6500
}
}
GET /api/admin/checkin/records?page=1&size=10&userId=1&startDate=2026-07-01&endDate=2026-07-07&clientSource=WINDOWS
需要管理员权限
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| page | Long | 否 | 页码,默认1 |
| size | Long | 否 | 每页条数,默认10 |
| userId | Long | 否 | 用户ID筛选 |
| startDate | Date | 否 | 起始日期 |
| endDate | Date | 否 | 截止日期 |
| clientSource | String | 否 | 签到端 |
响应: 分页格式(含用户手机号、昵称、药店名)
GET /api/admin/checkin/user/{userId}/records
需要管理员权限
GET /api/activity/invite/status
需要认证
响应:
{
"code": 200,
"data": {
"active": true,
"startTime": "2026-07-10T00:00:00",
"endTime": "2026-07-31T23:59:59",
"rewardDays": 30,
"maxInviterReward": 30,
"rewardTrigger": "LICENSE_APPROVED",
"myReceivedCount": 3,
"myRemainingCount": 27
}
}
| 字段 | 类型 | 说明 |
|---|---|---|
| active | Boolean | 活动是否开启 |
| rewardTrigger | String | REGISTRATION-注册即发 / LICENSE_APPROVED-入驻审核通过后发 |
| myReceivedCount | Long | 我已获得的奖励次数 |
| myRemainingCount | Long | 我剩余可获得的奖励次数 |
GET /api/activity/checkin-cycle/status
需要认证
响应:
{
"code": 200,
"data": {
"active": true,
"startTime": "2026-07-10T00:00:00",
"endTime": "2026-07-31T23:59:59",
"cycleStart": "2026-07-03",
"cycleEnd": "2026-07-09",
"requiredDays": 4,
"rewardDays": 7,
"maxRewardCount": 3,
"currentCycleCheckinDays": 2,
"cycleQualified": false,
"totalReceivedCount": 1,
"remainingCount": 2
}
}
| 字段 | 类型 | 说明 |
|---|---|---|
| active | Boolean | 活动是否开启 |
| cycleStart | String | 当前周期起始日(周五) |
| cycleEnd | String | 当前周期截止日(周四) |
| requiredDays | Integer | 周期内需累计签到天数 |
| rewardDays | Integer | 奖励高级会员天数 |
| maxRewardCount | Integer | 每用户最多领取次数 |
| currentCycleCheckinDays | Integer | 当前周期已签到天数 |
| cycleQualified | Boolean | 当前周期是否达标 |
| totalReceivedCount | Integer | 累计已领取次数 |
| remainingCount | Integer | 剩余可领取次数 |
GET /api/activity/lottery/status
需要认证
响应:
{
"code": 200,
"data": {
"active": true,
"startTime": "2026-07-10T00:00:00",
"endTime": "2026-07-31T23:59:59",
"eligible": true,
"todayChance": 1,
"todayRemaining": 1
}
}
| 字段 | 类型 | 说明 |
|---|---|---|
| active | Boolean | 活动是否开启 |
| eligible | Boolean | 是否满足参与条件(高级会员) |
| todayChance | Integer | 今日获得的机会数 |
| todayRemaining | Integer | 今日剩余可抽奖次数 |
POST /api/activity/lottery/draw
需要认证
响应:
{
"code": 200,
"data": {
"prizeId": 1,
"prizeName": "高级会员7天",
"rewardType": "MEMBERSHIP",
"rewardAmount": 0,
"rewardDays": 7,
"rewardLevel": "PRO",
"createTime": "2026-07-07T10:30:00"
}
}
| rewardType | 说明 |
|---|---|
| MEMBERSHIP | 会员奖励(rewardDays天,rewardLevel等级) |
| CRAWLER | 爬虫次数(rewardAmount次) |
| EMPTY | 谢谢参与 |
GET /api/activity/lottery/records?limit=20
需要认证
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| limit | Integer | 否 | 返回条数,默认20 |
GET /api/admin/activity/invite/config
需要管理员权限
响应:
{
"code": 200,
"data": {
"id": 1,
"enabled": 1,
"startTime": "2026-07-10T00:00:00",
"endTime": "2026-07-31T23:59:59",
"inviterRewardDays": 30,
"inviteeRewardDays": 30,
"maxInviterReward": 30,
"rewardTrigger": "LICENSE_APPROVED",
"requireMiniappInviter": 1,
"remark": "邀请有礼活动"
}
}
PUT /api/admin/activity/invite/config
需要管理员权限
请求体:
{
"enabled": 1,
"startTime": "2026-07-10T00:00:00",
"endTime": "2026-07-31T23:59:59",
"inviterRewardDays": 30,
"inviteeRewardDays": 30,
"maxInviterReward": 30,
"rewardTrigger": "LICENSE_APPROVED",
"requireMiniappInviter": 1,
"remark": "邀请有礼活动"
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| enabled | Integer | 是 | 0-停用 1-启用 |
| rewardTrigger | String | 是 | REGISTRATION-注册即发 LICENSE_APPROVED-入驻审核通过后发 |
| requireMiniappInviter | Integer | 是 | 0-不要求 1-要求邀请人为小程序用户 |
| maxInviterReward | Integer | 是 | 邀请人最多获得奖励次数(默认30) |
POST /api/admin/activity/invite/revoke
需要管理员权限
请求体:
{
"inviteeId": 123,
"reason": "冒用他人资质"
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| inviteeId | Long | 是 | 被邀请人ID(作弊者) |
| reason | String | 是 | 撤销原因 |
响应:
{
"code": 200,
"data": "已撤销 1 条邀请奖励记录"
}
GET /api/admin/activity/checkin-cycle/config
需要管理员权限
PUT /api/admin/activity/checkin-cycle/config
需要管理员权限
请求体:
{
"enabled": 1,
"startTime": "2026-07-10T00:00:00",
"endTime": "2026-07-31T23:59:59",
"cycleMode": "FRI_THU",
"requiredDays": 4,
"rewardDays": 7,
"maxRewardCount": 3,
"remark": "签到送会员"
}
GET /api/admin/activity/lottery/config
需要管理员权限
PUT /api/admin/activity/lottery/config
需要管理员权限
请求体:
{
"enabled": 1,
"startTime": "2026-07-10T00:00:00",
"endTime": "2026-07-31T23:59:59",
"dailyMaxChance": 1,
"requireMembershipLevel": "PRO",
"remark": "比价抽奖"
}
GET /api/admin/activity/lottery/prizes
需要管理员权限
POST /api/admin/activity/lottery/prizes
需要管理员权限
请求体:
{
"name": "高级会员7天",
"rewardType": "MEMBERSHIP",
"rewardAmount": 0,
"rewardDays": 7,
"rewardLevel": "PRO",
"probabilityWeight": 10,
"enabled": 1,
"sort": 1
}
| rewardType | 说明 |
|---|---|
| MEMBERSHIP | 会员奖励(需填rewardDays、rewardLevel) |
| CRAWLER | 爬虫次数(需填rewardAmount) |
| EMPTY | 谢谢参与 |
PUT /api/admin/activity/lottery/prizes/{id}
需要管理员权限
DELETE /api/admin/activity/lottery/prizes/{id}
需要管理员权限
所有登录接口支持loginSource参数,标识登录来源:
| 值 | 说明 |
|---|---|
| WINDOWS | Windows桌面应用 |
| MINIAPP | 微信小程序 |
| ANDROID | Android APP |
| IOS | iOS APP |
| 微信公众号H5 |
示例:
{
"phone": "13800138000",
"code": "123456",
"loginSource": "WINDOWS"
}
用户信息接口返回新增字段:
{
"id": 1,
"userId": 1,
"phone": "13800138000",
"nickname": "用户138****0000",
"avatar": null,
"wechatBound": false,
"membershipLevel": "PLUS",
"membershipLevelName": "PLUS会员",
"levelCode": "PLUS",
"version": "v1.0",
"role": "USER",
"loginSource": "WINDOWS",
"pharmacyName": "XX大药房",
"province": "广东省",
"city": "深圳市",
"district": "南山区",
"createTime": "2026-06-15T10:00:00"
}
字段说明:
membershipLevel: 会员等级(PLUS/PRO/ULTRA)membershipLevelName: 会员等级中文名loginSource: 登录来源(WINDOWS/MINIAPP/ANDROID/IOS/WECHAT)role: 用户角色(USER/ADMIN/SUPER_ADMIN)GET /api/payment/plans
响应:
{
"code": 200,
"data": [
{
"id": 1,
"planCode": "MONTHLY_PRO",
"planName": "高级会员·月卡",
"membershipLevel": "PRO",
"price": 29.90,
"originalPrice": 59.90,
"durationDays": 30,
"sortOrder": 3,
"status": 1,
"description": "每天不限量· 1个月29.9(原价59.9)"
}
]
}
POST /api/payment/order/create
需要认证
请求体:
{
"planId": 1,
"channel": "WECHAT"
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| planId | Long | 是 | 支付方案ID |
| channel | String | 是 | 支付渠道:WECHAT/ALIPAY/WECHAT_MINIAPP |
响应(WECHAT / ALIPAY — 扫码支付,需展示二维码):
{
"code": 200,
"data": {
"orderNo": "OP1234567890123456",
"planName": "高级会员·月卡",
"amount": 29.90,
"channel": "WECHAT",
"status": "PENDING",
"qrCodeBase64": "data:image/png;base64,...",
"payUrl": "weixin://wxpay/bizpayurl?pr=xxx",
"miniAppPayParams": null,
"expireTime": "2026-06-30T22:00:00",
"expireHint": "请在15分钟内完成付款,超时订单将自动过期",
"createTime": "2026-06-30T21:45:00"
}
}
响应(WECHAT_MINIAPP — 小程序支付,直接调起微信支付):
{
"code": 200,
"data": {
"orderNo": "OP1234567890123456",
"planName": "高级会员·月卡",
"amount": 29.90,
"channel": "WECHAT_MINIAPP",
"status": "PENDING",
"qrCodeBase64": null,
"payUrl": null,
"miniAppPayParams": {
"appId": "wxabc123...",
"timeStamp": "1752060000",
"nonceStr": "a1b2c3d4e5f6...",
"package": "prepay_id=wx1234567890...",
"signType": "RSA",
"paySign": "XXXX..."
},
"expireTime": "2026-06-30T22:00:00",
"expireHint": "请在15分钟内完成付款,超时订单将自动过期",
"createTime": "2026-06-30T21:45:00"
}
}
| 响应字段 | 类型 | 说明 |
|---|---|---|
| orderNo | String | 订单号 |
| planName | String | 方案名称 |
| amount | BigDecimal | 金额(元) |
| channel | String | 支付渠道 |
| status | String | PENDING/PAID/EXPIRED |
| qrCodeBase64 | String | 二维码Base64图片(WECHAT/ALIPAY 才有) |
| payUrl | String | 支付链接/码串(WECHAT/ALIPAY 才有) |
| miniAppPayParams | Object | 小程序支付参数,含签名(WECHAT_MINIAPP 才有) |
| expireTime | String | 过期时间 |
| expireHint | String | 过期提示 |
| createTime | String | 创建时间 |
关键区分:
qrCodeBase64/payUrl与miniAppPayParams互斥。扫码支付返回前者,小程序支付返回后者。
⚠️ 前端必读:小程序支付与扫码支付流程完全不同,不是展示二维码,而是一键调起微信支付。
与扫码支付的关键差异:
| WECHAT / ALIPAY(扫码) | WECHAT_MINIAPP(小程序) | |
|---|---|---|
| 用户操作 | 展示二维码 → 扫码付款 | 直接弹出微信支付面板 |
| 返回凭证 | qrCodeBase64(Base64图片) |
miniAppPayParams(签名对象) |
| openId | 不需要 | 自动从用户记录读取(登录时已存储) |
| 下单接口 | TradeTypeEnum.NATIVE |
TradeTypeEnum.JSAPI |
完整前端调用流程:
// ──── 步骤 1:用户登录(已有流程,无需改动)────
// 小程序端调用 wx.login() + 后端 miniappUnifiedLogin
// → 后端 code2Session 获取 openId 并存入 t_user.wechat_mini_open_id
// → 返回 JWT token(后续请求携带)
// ──── 步骤 2:创建小程序支付订单 ────
const res = await request({
url: '/api/payment/order/create',
method: 'POST',
header: { Authorization: `Bearer ${token}` },
data: {
planId: 1,
channel: 'WECHAT_MINIAPP' // ⚠️ 不传 openid,后端从用户记录读取
}
})
// ──── 步骤 3:调起微信支付面板 ────
const params = res.data.miniAppPayParams
wx.requestPayment({
timeStamp: params.timeStamp,
nonceStr: params.nonceStr,
package: params.package, // "prepay_id=wx..."
signType: params.signType, // "RSA"
paySign: params.paySign,
success(res) {
// 支付成功 → 查询订单确认状态
queryOrderStatus(orderNo)
},
fail(err) {
// 用户取消或支付失败
console.log('支付取消', err)
}
})
前置条件(重要):
t_user.wechat_mini_open_id 不为空"未获取到小程序 openId,请先通过小程序登录"openId 在登录时通过 code2Session 获取并持久化,支付时从数据库直接读取,不需要重复 wx.login 授权miniAppPayParams 字段说明:
| 字段 | 说明 | 对应 wx.requestPayment 参数 |
|---|---|---|
| appId | 小程序AppID | ❌ 不传(wx.requestPayment不需要) |
| timeStamp | 时间戳(秒) | ✅ timeStamp |
| nonceStr | 随机字符串(32位hex) | ✅ nonceStr |
| package | 格式 prepay_id=xxx |
✅ package |
| signType | 固定 RSA |
✅ signType |
| paySign | RSA-SHA256签名 | ✅ paySign |
切换渠道注意:
// 如果从 WECHAT_MINIAPP 切换到 WECHAT 扫码:
// → 返回 qrCodeBase64(展示二维码让用户扫码)
// 如果从 WECHAT 切换到 WECHAT_MINIAPP:
// → 返回 miniAppPayParams(直接调起支付面板)
// → 同样是 POST /api/payment/order/{orderNo}/switch-channel,只传 channel
配置要求(后端):
# application.yml
wechat:
miniapp:
app-id: wxMINIAPP123... # 小程序appId(登录用)
app-secret: secret... # 小程序appSecret(登录用)
payment:
miniapp:
app-id: wxMINIAPP123... # 支付签名用appId(必须与小程序的相同,或独立配置)
wechat:
app-id: wxOFFICIAL... # Native扫码用appId(公众号/网站应用,可与上面不同)
mch-id: 1234567890 # 商户号(Native + JSAPI 共用)
# ... 密钥、证书等
错误场景:
| 错误信息 | 原因 | 解决 |
|---|---|---|
未获取到小程序 openId |
用户未通过小程序登录 | 先调用小程序登录接口 |
用户不存在 |
userId 无效 | 检查 JWT token |
微信支付未配置 |
payment.wechat 参数缺失 | 检查配置文件 |
微信小程序支付需要提供用户 openid |
内部异常 | 联系后端(正常情况下不会出现) |
完整 API 清单:
| 接口 | 方法 | 认证 | 说明 |
|---|---|---|---|
/api/payment/plans |
GET | 否 | 获取支付方案列表 |
/api/payment/order/create |
POST | 是 | 创建订单(channel=WECHAT_MINIAPP) |
/api/payment/order/{orderNo}/switch-channel |
POST | 是 | 切换渠道 |
/api/payment/order/{orderNo} |
GET | 是 | 查询订单状态 |
/api/payment/orders |
GET | 是 | 我的订单列表 |
POST /api/payment/order/{orderNo}/switch-channel
需要认证
业务场景: 用户创建订单后,可在订单详情页切换为其他支付渠道,后端根据新渠道重新调用预下单接口生成二维码/小程序支付参数。
重要:不关闭原渠道订单,允许用户在多个渠道间切换。以第一个支付成功渠道为准,后续支付记录到重复支付表并自动退款。
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| channel | String | 是 | 新支付渠道:WECHAT/ALIPAY/WECHAT_MINIAPP |
小程序切渠道时同样不传
openid,后端自动从用户记录读取。
请求体:
{
"channel": "ALIPAY"
}
响应: 同 13.2 创建订单
GET /api/payment/order/{orderNo}
需要认证
响应:
{
"code": 200,
"data": {
"orderNo": "OP1234567890123456",
"planName": "高级会员·月卡",
"amount": 29.90,
"channel": "WECHAT",
"status": "PAID",
"qrCodeBase64": null,
"payUrl": null,
"expireTime": "2026-06-30T22:00:00",
"expireHint": null,
"createTime": "2026-06-30T21:45:00"
}
}
GET /api/payment/orders
需要认证
响应:
{
"code": 200,
"data": [
{
"orderNo": "OP1234567890123456",
"planName": "高级会员·月卡",
"amount": 29.90,
"channel": "WECHAT",
"status": "PAID",
"createTime": "2026-06-30T21:45:00"
}
]
}
POST /api/payment/order/{orderNo}/pay
需要认证
仅在
payment.mock=true时可用。已支付订单会返回错误(code=2005)。
响应:
{
"code": 200,
"data": {
"orderNo": "OP1234567890123456",
"status": "PAID",
"amount": 29.90,
"planName": "高级会员·月卡",
"membershipLevel": "PRO",
"paidTime": "2026-06-30T21:50:00"
}
}
POST /api/payment/callback/wechat
无需认证
微信支付异步通知回调。生产环境需接入微信支付SDK完成RSA验签+解密。
响应: 成功返回 SUCCESS,失败返回 FAIL
POST /api/payment/callback/alipay
无需认证
支付宝异步通知回调。生产环境需接入支付宝SDK完成RSA2验签。
响应: 成功返回 success,失败返回 fail
当同一订单在多个渠道都支付成功时(用户切换渠道后),系统自动处理:
trade_no 不重复记录,避免重复退款PENDING → SUCCESS / FAILED退款渠道实现:
| 渠道 | 退款接口 | 说明 |
|---|---|---|
| 微信 | WxPayService.refundV3() | API v3 退款,需配置退款证书 |
| 支付宝 | AlipayClient.execute(AlipayTradeRefundRequest) | 统一收单交易退款 |
| 模拟模式 | 直接返回模拟退款单号 | mock=true 时不调用真实SDK |
退款状态:
| 状态 | 说明 |
|---|---|
| PENDING | 待退款(初始状态) |
| SUCCESS | 退款成功(记录退款交易号) |
| FAILED | 退款失败(记录失败原因,可后续重试) |
支付模块错误码:
| code | 说明 |
|---|---|
| 2001 | 支付订单不存在 |
| 2002 | 支付订单已过期 |
| 2003 | 支付金额不正确 |
| 2004 | 不支持该支付渠道 |
| 2005 | 支付失败 |
| 2006 | 退款失败,请重试 |
| 2007 | 支付方案不存在 |
| 2008 | 支付方案已下架 |
| 2009 | 支付回调验签失败 |
| 2010 | 支付渠道未配置 |
| 2011 | 方案编码已存在 |
| 2012 | 签约协议不存在 |
| 2013 | 已存在有效签约协议 |
| 2014 | 协议未签约或已解约 |
| 2015 | 自动扣款失败 |
| 2016 | 安心付卡模板不存在 |
| 2017 | 安心付卡模板创建失败 |
| 2018 | 安心付未配置 |
| 2019 | 安心付订单不存在 |
| 2020 | 安心付扣款通知无法匹配到系统用户 |
| 接口 | 说明 |
|---|---|
| POST /api/admin/payment/plans | 创建支付方案(ADMIN+) |
| PUT /api/admin/payment/plans/{id} | 更新支付方案(ADMIN+) |
| PUT /api/admin/payment/plans/{id}/status | 上架/下架方案(ADMIN+) |
| 接口 | 说明 |
|---|---|
| POST /api/payment/agreement/sign | 发起签约 |
| GET /api/payment/agreement/list | 查询用户签约列表 |
| GET /api/payment/agreement/{agreementId} | 查询协议详情 |
| POST /api/payment/agreement/{agreementId}/unsign | 解约 |
| POST /api/payment/agreement/notify/wechat | 微信签约回调(公开) |
| 接口 | 说明 |
|---|---|
| POST /api/admin/payment/anxin/card/create | 创建安心付卡模板(ADMIN+) |
| GET /api/admin/payment/anxin/cards | 查询安心付卡模板列表(ADMIN+) |
| POST /api/admin/payment/anxin/card/{cardId}/sync | 同步安心付卡模板状态(ADMIN+) |
| PUT /api/admin/payment/anxin/card/{cardId}/status | 启用/禁用安心付卡模板(ADMIN+) |
| POST /api/payment/anxin/notify/deduct | 安心付扣款通知(公开) |
| POST /api/payment/anxin/notify/card-change | 安心付卡变更通知(公开) |
| 接口 | 说明 |
|---|---|
| POST /api/payment/alipay/gateway | 支付宝网关回调(公开) |
| GET /api/payment/alipay/auth-callback | 支付宝授权回调(公开) |
| 接口 | 说明 |
|---|---|
| GET /api/admin/audit-log | 分页查询审计日志(ADMIN+) |
| GET /api/admin/audit-log/sensitive | 查询敏感操作日志(ADMIN+) |
| GET /api/admin/audit-log/user/{userId} | 查询指定用户操作历史(ADMIN+) |
| GET /api/admin/audit-log/target/{type}/{id} | 查询指定目标对象操作历史(ADMIN+) |
| GET /api/admin/audit-log/stats | 按模块统计操作次数(ADMIN+) |
| 接口 | 说明 |
|---|---|
| PUT /api/platform-session/{platformCode} | 更新平台会话 |
| GET /api/platform-session/list | 查询平台会话列表 |
| DELETE /api/platform-session/{platformCode} | 删除平台会话 |
| 接口 | 说明 |
|---|---|
| POST /api/search-record/history | 保存搜索记录 |
| GET /api/search-record/history | 获取搜索历史 |
| GET /api/search-record/history/{id} | 获取指定搜索记录 |
| DELETE /api/search-record/history/{id} | 删除指定搜索记录 |
| DELETE /api/search-record/history | 清空搜索历史 |
| 接口 | 说明 |
|---|---|
| GET /api/invite/my-inviter | 查询我的邀请人 |
| POST /api/invite/bind | 补填邀请码 |
POST /api/search/query
需要认证
消耗 1 次爬虫配额,返回各平台报价。
请求体:
{
"keyword": "阿莫西林胶囊",
"platforms": ["yaoshibang", "yaobangmang", "yiyaocheng"]
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| keyword | String | 是 | 药品名称关键词 |
| platforms | Array | 否 | 指定平台列表,为空则查全部已启用平台 |
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| level | String | PLUS | 会员等级:PLUS/PRO/ULTRA |
响应:
{
"code": 200,
"data": [
{
"level": "PRO",
"benefitType": "DAILY_QUOTA",
"benefitValue": 999
},
{
"level": "PRO",
"benefitType": "MONTHLY_QUOTA",
"benefitValue": 29970
},
{
"level": "PRO",
"benefitType": "MAX_CONCURRENT",
"benefitValue": 5
}
]
}
GET /api/watchlist
需要认证
响应:
{
"code": 200,
"data": [
{
"id": 1,
"drugName": "阿莫西林胶囊",
"spec": "0.25g*24粒",
"manufacturer": "珠海联邦制药",
"minPrice": 12.50,
"minPricePlatform": "yaoshibang",
"lastPrice": 13.00,
"priceChange": 0.50,
"status": 1,
"createTime": "2026-06-15T10:00:00"
}
]
}
POST /api/watchlist
需要认证
请求体:
{
"drugName": "阿莫西林胶囊",
"spec": "0.25g*24粒",
"manufacturer": "珠海联邦制药"
}
响应: 同 16.1 单条记录
DELETE /api/watchlist/{id}
需要认证
GET /api/watchlist/stats
需要认证
响应:
{
"code": 200,
"data": {
"total": 15,
"active": 12,
"priceDropCount": 3
}
}
POST /api/upload
需要认证
请求格式: multipart/form-data
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| file | MultipartFile | 是 | 上传的文件 |
响应:
{
"code": 200,
"data": "/opt/uploads/abc123def456.jpg"
}
| 接口 | 说明 |
|---|---|
| GET /api/admin/users?page=1&size=20&phone=138&role=ADMIN | 分页查询用户列表(SUPER_ADMIN) |
| PUT /api/admin/users/{userId}/role | 修改用户角色(SUPER_ADMIN) |
修改角色请求体:
{
"role": "ADMIN"
}
| 接口 | 说明 |
|---|---|
| POST /api/admin/membership/grant | 给用户发放/调整会员等级(ADMIN+) |
| GET /api/admin/membership/memberships?page=1&size=20&userId=1&level=PLUS | 分页查询会员记录(ADMIN+) |
发放会员请求体:
{
"userId": 1,
"level": "PRO",
"durationDays": 30,
"source": "ADMIN_GRANT",
"remark": "运营手动发放"
}
| 接口 | 说明 |
|---|---|
| GET /api/admin/license/review?reviewStatus=PENDING | 查看待审核入驻信息列表(ADMIN+) |
| POST /api/admin/license/review | 审核入驻信息(ADMIN+,通过后赠送30天高级会员) |
审核请求体:
{
"licenseId": 1,
"action": "APPROVED",
"rejectReason": null
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| licenseId | Long | 是 | 入驻信息ID |
| action | String | 是 | 审核动作:APPROVED/REJECTED |
| rejectReason | String | 否 | 驳回原因(REJECTED时必填) |
POST /api/search-record/history
需要认证
请求体:
{
"drugName": "阿莫西林",
"searchedAt": "2026-07-01T10:00:00",
"statusText": "找到3个平台报价",
"platformResults": [{"platform": "平台A", "price": 12.5}],
"searchLog": null
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| drugName | String | 是 | 药品名称 |
| searchedAt | DateTime | 否 | 搜索时间 |
| statusText | String | 否 | 状态文案 |
| platformResults | Object | 否 | 平台搜索结果(任意JSON,原样存储) |
| searchLog | Object | 否 | 搜索日志(任意JSON) |
响应: 同 19.3 查询详情
GET /api/search-record/history?limit=20
需要认证
响应:
{
"code": 200,
"data": [
{
"id": 1,
"drugName": "阿莫西林",
"searchedAt": "2026-07-01T10:00:00",
"statusText": "找到3个平台报价",
"platformResults": [{"platform": "平台A", "price": 12.5}],
"searchLog": null
}
]
}
GET /api/search-record/history/{id}
需要认证
响应:
{
"code": 200,
"data": {
"id": 1,
"drugName": "阿莫西林",
"searchedAt": "2026-07-01T10:00:00",
"statusText": "找到3个平台报价",
"platformResults": [{"platform": "平台A", "price": 12.5}],
"searchLog": null
}
}
DELETE /api/search-record/history/{id}
需要认证
响应:
{ "code": 200, "message": "success", "data": null }
DELETE /api/search-record/history
需要认证
响应:
{ "code": 200, "message": "success", "data": null }
GET /api/admin/audit-log?module=PAYMENT&operationType=GRANT&operatorId=1&isSensitive=false&page=1&size=20
需要管理员权限
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| module | String | 否 | 模块筛选 |
| operationType | String | 否 | 操作类型筛选 |
| operatorId | Long | 否 | 操作人ID |
| startTime | DateTime | 否 | 开始时间 |
| endTime | DateTime | 否 | 结束时间 |
| isSensitive | Boolean | 否 | 是否仅敏感操作 |
| page | int | 否 | 页码(默认1) |
| size | int | 否 | 每页数量(默认20) |
响应: 分页格式(参见“通用说明 - 分页响应格式”)
GET /api/admin/audit-log/sensitive?startTime=2026-07-01T00:00:00
需要管理员权限
响应:
{
"code": 200,
"data": [
{
"id": 1,
"module": "USER",
"operationType": "DISABLE_USER",
"operatorId": 100,
"isSensitive": true,
"targetType": "USER",
"targetId": 5,
"beforeData": "{\"status\":\"ACTIVE\"}",
"afterData": "{\"status\":\"DISABLED\"}",
"ip": "192.168.1.100",
"createdAt": "2026-07-01T10:00:00"
}
]
}
GET /api/admin/audit-log/user/{userId}?limit=50
需要管理员权限
GET /api/admin/audit-log/target/{targetType}/{targetId}?limit=50
需要管理员权限
路径参数:
targetType: 目标类型(USER/ORDER/CONFIG等)targetId: 目标IDGET /api/admin/audit-log/stats?module=PAYMENT&startTime=2026-07-01T00:00:00
需要管理员权限
响应:
{
"code": 200,
"data": { "count": 42 }
}
GET /api/activity/lottery/status
需要认证
响应:
{
"code": 200,
"data": {
"enabled": true,
"inWindow": true,
"eligible": true,
"membershipLevel": "PRO",
"requireMembershipLevel": "PRO",
"availableChances": 1,
"usedChances": 0,
"reason": null
}
}
| 字段 | 类型 | 说明 |
|---|---|---|
| enabled | Boolean | 活动是否开启 |
| inWindow | Boolean | 当前时间是否在活动窗口内 |
| eligible | Boolean | 用户是否具备参与资格(会员等级+入驻审核) |
| membershipLevel | String | 当前会员等级 |
| requireMembershipLevel | String | 所需最低会员等级 |
| availableChances | Integer | 今日可用抽奖机会数 |
| usedChances | Integer | 今日已使用抽奖机会数 |
| reason | String | 状态原因说明(机会为0时告知原因) |
GET /api/activity/lottery/prizes
需要认证
响应:
{
"code": 200,
"data": [
{
"id": 1,
"name": "特等奖 iPhone 17",
"rewardType": "PHYSICAL",
"rewardAmount": 0,
"rewardDays": null,
"rewardLevel": null,
"sort": 1
},
{
"id": 2,
"name": "一等奖 30天高级会员",
"rewardType": "MEMBERSHIP",
"rewardAmount": 0,
"rewardDays": 30,
"rewardLevel": "PRO",
"sort": 2
}
]
}
注意:不返回
probabilityWeight、stock、remainingStock等敏感信息
POST /api/activity/lottery/draw
需要认证
业务规则:
响应(中奖):
{
"code": 200,
"data": {
"recordId": "1234567890",
"prizeName": "一等奖 30天高级会员",
"rewardType": "MEMBERSHIP",
"rewardAmount": 0,
"rewardDays": 30,
"rewardLevel": "PRO",
"prizeTier": "一等奖",
"win": true,
"createTime": "2026-07-13T10:30:00"
}
}
响应(未中奖):
{
"code": 200,
"data": {
"recordId": "1234567891",
"prizeName": "谢谢惠顾",
"rewardType": "EMPTY",
"rewardAmount": 0,
"rewardDays": null,
"rewardLevel": null,
"prizeTier": "谢谢惠顾",
"win": false,
"createTime": "2026-07-13T10:30:00"
}
}
| 字段 | 类型 | 说明 |
|---|---|---|
| recordId | String | 抽奖记录ID |
| prizeName | String | 奖品名称 |
| rewardType | String | 奖励类型:MEMBERSHIP/CRAWLER/EMPTY/PHYSICAL |
| rewardAmount | Integer | 奖励数量 |
| rewardDays | Integer | 奖励天数(会员时长) |
| rewardLevel | String | 奖励等级(PRO/ULTRA) |
| prizeTier | String | 奖品等级名称(特等奖/一等奖/.../谢谢惠顾) |
| win | Boolean | 是否中奖(EMPTY为未中奖) |
| createTime | DateTime | 抽奖时间 |
GET /api/activity/lottery/records?limit=20
需要认证
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| limit | Integer | 否 | 返回条数限制(默认20) |
响应:
{
"code": 200,
"data": [
{
"recordId": "1234567890",
"prizeName": "一等奖 30天高级会员",
"rewardType": "MEMBERSHIP",
"rewardAmount": 0,
"rewardDays": 30,
"rewardLevel": "PRO",
"prizeTier": "一等奖",
"win": true,
"createTime": "2026-07-13T10:30:00"
}
]
}
GET /api/admin/activity/lottery/config
需要管理员权限
响应:
{
"code": 200,
"data": {
"id": 1,
"enabled": 1,
"startTime": "2026-07-13T00:00:00",
"endTime": "2026-07-31T23:59:59",
"dailyChanceLimit": 1,
"requireMembershipLevel": "PRO",
"requireLicenseApproved": 1
}
}
PUT /api/admin/activity/lottery/config
需要管理员权限
请求体:
{
"enabled": 1,
"startTime": "2026-07-13T00:00:00",
"endTime": "2026-07-31T23:59:59",
"dailyChanceLimit": 1,
"requireMembershipLevel": "PRO",
"requireLicenseApproved": 1
}
GET /api/admin/activity/lottery/prizes
需要管理员权限
响应:
{
"code": 200,
"data": [
{
"id": 1,
"name": "特等奖 iPhone 17",
"rewardType": "PHYSICAL",
"rewardAmount": 0,
"rewardDays": null,
"rewardLevel": null,
"stock": 0,
"remainingStock": 0,
"probabilityWeight": 0,
"enabled": 1,
"sort": 1
}
]
}
POST /api/admin/activity/lottery/prizes
需要管理员权限
请求体:
{
"name": "六等奖 2天高级会员",
"rewardType": "MEMBERSHIP",
"rewardAmount": 0,
"rewardDays": 2,
"rewardLevel": "PRO",
"stock": 500,
"probabilityWeight": 500,
"enabled": 1,
"sort": 8
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| name | String | 是 | 奖品名称 |
| rewardType | String | 是 | 奖励类型:MEMBERSHIP/CRAWLER/EMPTY/PHYSICAL |
| rewardAmount | Integer | 否 | 奖励数量 |
| rewardDays | Integer | 否 | 奖励天数(会员时长) |
| rewardLevel | String | 否 | 奖励等级(PRO/ULTRA) |
| stock | Integer | 是 | 奖品总份数(0表示不限或仅展示) |
| probabilityWeight | Integer | 是 | 概率权重(权重=份数,确保库存均匀消耗) |
| enabled | Integer | 否 | 是否启用(默认1) |
| sort | Integer | 否 | 排序(默认按ID) |
PUT /api/admin/activity/lottery/prizes/{id}
需要管理员权限
请求体: 同 21.2.4
DELETE /api/admin/activity/lottery/prizes/{id}
需要管理员权限
GET /api/admin/activity/lottery/records?page=1&size=20&userId=1&prizeType=MEMBERSHIP
需要管理员权限
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| page | Integer | 否 | 页码(默认1) |
| size | Integer | 否 | 每页数量(默认20) |
| userId | Long | 否 | 用户ID筛选 |
| prizeType | String | 否 | 奖品类型筛选(MEMBERSHIP/CRAWLER/EMPTY/PHYSICAL) |
响应: 分页格式(参见"通用说明 - 分页响应格式")
📝 说明:本文档会随着项目迭代持续更新,请以最新版本为准。