API-小程序.md 19 KB

智价云小程序 API 接口设计 V1.0

定稿日期:2026-06-27
与桌面端共用后端 · Base URL 示例:https://api.proprice.kailin.com.cn/v1
关联 PRD:PRD-小程序-V1.0.md


1. 通用约定

1.1 请求头

Header 说明
Authorization Bearer {access_token},除登录/回调外必填
X-Client 固定 mini_program
X-Client-Version 小程序版本号,如 1.0.0
Content-Type application/json

1.2 响应格式

{
  "code": 0,
  "message": "ok",
  "data": {}
}
code 含义
0 成功
40001 参数错误
40101 未登录 / Token 过期
40301 无权限(如体验用户访问超限历史)
40401 资源不存在
42901 请求过于频繁
50001 服务器错误

1.3 分页

列表接口统一参数:

参数 类型 说明
page int 页码,从 1 开始,默认 1
page_size int 每页条数,默认 20,最大 50

响应 data 结构:

{
  "items": [],
  "total": 100,
  "page": 1,
  "page_size": 20,
  "has_more": true
}

2. 数据实体

2.1 User(扩展)

在 PRD §10 基础上扩展:

字段 类型 说明
id string 用户 ID
phone string 手机号(脱敏返回)
pharmacy_name string 药店名称
region object { province, city, district }
license_status enum pending / approved / rejected
license_reject_reason string? 驳回原因
member_type enum trial / paid / expired
trial_end_at datetime? 体验到期时间
member_expire_at datetime? 会员到期时间
invite_code string 个人邀请码
wx_openid string 微信 openid(内部)
wx_unionid string? 微信 unionid(内部)
created_at datetime 注册时间

2.2 UserGateStatus(聚合,非表)

/users/me 返回的门禁摘要(与主 PRD §3.4 一致,各端共用):

字段 类型 说明
can_query_on_desktop bool 执照已通过且绑平台 ≥1 时为 true
license_status enum 执照状态
platform_bound_count int 已绑定平台数
gate_messages string[] 待完成事项(引导完成注册/执照/绑平台)

上述门禁仅影响桌面查价等等价能力;不用于裁剪小程序历史/采购接口返回。

2.3 BusinessLicense(新增)

字段 类型 说明
id string 执照记录 ID
user_id string 用户 ID
image_url string 执照图片 URL(私有存储,需签名访问)
status enum pending / approved / rejected
reject_reason string? 驳回原因
submitted_at datetime 提交时间
reviewed_at datetime? 审核时间
source_client enum mini_program / windows / android
reviewer_id string? 运营审核人(Admin)

审核通过/驳回由 Admin 操作台调用内部接口,与桌面端上传共用队列。

2.4 QueryLog(扩展)

字段 类型 说明
id string query_id
user_id string 用户 ID
keyword string 搜索关键词
queried_at datetime 查询时间
source_client enum windows / android / mini_program
result_count int 命中 SKU 数
lowest_platform string 最低价平台
lowest_price decimal 参考最低价
snapshot QuerySnapshot 完整快照 JSON
related_intent_ids string[] 关联跳转购买 ID

QuerySnapshot 结构

{
  "items": [
    {
      "platform": "药帮忙",
      "platform_id": "yaobangmang",
      "price": 8.50,
      "spec": "0.25g×24粒",
      "manufacturer": "石药集团",
      "approval_number": "国药准字H13020961",
      "expiry": "2027-06",
      "moq": "10盒",
      "stock_status": "in_stock",
      "is_lowest": true,
      "external_url": "https://..."
    }
  ]
}

2.5 PurchaseIntent(新增)

字段 类型 说明
id string intent_id
user_id string 用户 ID
query_id string? 关联 QueryLog
drug_name string 药品名称
spec string 规格
manufacturer string? 厂家
platform string 药师帮 / 药帮忙 / 1药城
platform_id string 平台标识
reference_price decimal 跳转时参考价
clicked_at datetime 跳转时间
source_client enum 产生端
external_url string? 跳转 URL(内部存储,小程序不返回)

2.6 ProcurementLedger(V1.1 新增)

字段 类型 说明
id string ledger_id
user_id string 用户 ID
intent_id string? 关联 PurchaseIntent
query_id string? 关联 QueryLog
drug_name string 药品名称
spec string 规格
qty decimal 数量
unit_price decimal 单价
total decimal 总价
platform string? 平台
order_note string? 备注
status enum ordered / received
created_at datetime 录入时间

2.7 Order(扩展)

字段 类型 说明
id string 订单 ID
order_no string 业务订单号
user_id string 用户 ID
package_type enum monthly / quarterly / yearly
amount decimal 应付金额(元)
pay_channel enum wechat_mp / wechat_qr / alipay
source_client enum mini_program / windows / android
status enum pending / paid / failed / closed
paid_at datetime? 支付时间
member_expire_at datetime? 开通后会员到期
created_at datetime 创建时间

2.8 MembershipQuota(聚合)

/users/me 返回配额摘要:

字段 类型 说明
daily_query_used int 桌面今日已用查询次数
daily_query_limit int 桌面每日上限(体验 20,会员 -1 表示不限)
watchlist_used int 本月已关注品种数
watchlist_limit int 关注上限

小程序历史/采购参考 history_visible_* 配额字段;列表接口不对体验用户做裁剪。


3. 认证接口

3.1 小程序登录

POST /auth/mp/login

请求:

{
  "code": "wx.login 返回的 code",
  "phone_code": "getPhoneNumber 返回的 code"
}

响应 data

{
  "access_token": "eyJ...",
  "expires_in": 7200,
  "refresh_token": "rf_...",
  "is_registered": true,
  "user": { /* User 摘要,is_registered=true 时返回 */ }
}
场景 行为
手机号已注册 绑定/更新 wx_openid,返回 token + user
手机号未注册 is_registered: false,前端跳转 mp-register

3.2 新用户注册

POST /auth/register

{
  "invite_code": "PX8K2M",
  "pharmacy_name": "康宁大药房",
  "region": {
    "province": "广东省",
    "city": "广州市",
    "district": "天河区"
  }
}

需已登录(微信授权 + 手机号已绑定)。成功后创建 User,license_status: null(未上传),返回更新后的 user。

3.3 刷新 Token

POST /auth/refresh

{ "refresh_token": "rf_..." }

3.4 退出登录

POST /auth/logout

清除服务端 session(可选);小程序端清除本地 token。


4. 用户接口

4.1 获取当前用户

GET /users/me

响应 data

{
  "user": { /* User */ },
  "gate": { /* UserGateStatus */ },
  "quota": { /* MembershipQuota */ },
  "platform_bindings": [
    {
      "platform_id": "yaobangmang",
      "platform_name": "药帮忙",
      "status": "bound",
      "last_validated_at": "2026-06-27T10:00:00Z"
    }
  ]
}

不返回平台账号密码。

4.2 首页概览统计

GET /users/me/dashboard

响应 data

{
  "today_query_count": 8,
  "today_purchase_intent_count": 3,
  "total_query_count": 156,
  "recent_queries": [ /* QueryLog 摘要,最多 3 条 */ ]
}

5. 营业执照接口

5.1 获取执照状态

GET /licenses/current

响应 data

{
  "status": "pending",
  "reject_reason": null,
  "submitted_at": "2026-06-27T15:30:00Z",
  "reviewed_at": null,
  "image_url": "https://...signed...",
  "source_client": "mini_program"
}
status 说明
null / 404 未上传,前端跳转 mp-license-upload
pending 审核中
approved 已通过
rejected 已驳回,含 reject_reason

5.2 上传营业执照

POST /licenses/upload

Content-Type: multipart/form-data

字段 类型 说明
file file JPG/PNG,≤ 5MB

响应 data

{
  "id": "lic_abc",
  "status": "pending",
  "submitted_at": "2026-06-27T15:30:00Z"
}

行为:

  • 新上传或驳回后重传:创建新记录或更新,statuspending
  • 同步更新 User.license_statuspending
  • 审核中不可重复提交(返回 40903

5.3 获取执照图片(签名 URL)

GET /licenses/current/image-url

返回短期有效的 signed URL,供小程序预览已提交执照。


6. 平台绑定接口

与桌面端共用 PlatformBinding 实体;任一端绑定/解绑,各端同步。

6.1 平台列表

GET /platform-bindings

响应 data.items[]

{
  "platform_id": "yaobangmang",
  "platform_name": "药帮忙",
  "status": "bound",
  "account_masked": "138****5678",
  "last_validated_at": "2026-06-27T10:00:00Z"
}

未绑定的平台也返回,status: "unbound"

6.2 绑定平台

POST /platform-bindings

{
  "platform_id": "yaobangmang",
  "account": "user@example.com",
  "password": "******",
  "source_client": "mini_program"
}

密码加密传输,服务端加密存储;响应不含明文密码。

6.3 解绑平台

DELETE /platform-bindings/{platform_id}

至少保留 0 个绑定;若解绑后导致 can_query_on_desktop=false,与主 PRD 一致。

6.4 验证绑定

POST /platform-bindings/{platform_id}/validate

触发凭证有效性校验,更新 last_validated_at


7. 查询历史接口

7.1 查询历史列表

GET /queries

参数 类型 说明
keyword string? 关键词搜索
days int? 可选时间筛选:7 / 30 / 90(用户主动筛选,非会员限制)
source_client string? 来源端筛选

响应 data.items[] 摘要字段:

{
  "id": "q_abc123",
  "keyword": "阿莫西林胶囊",
  "queried_at": "2026-06-27T14:32:00Z",
  "source_client": "windows",
  "result_count": 3,
  "lowest_platform": "药帮忙",
  "lowest_price": 8.50
}

不做会员级裁剪:体验用户与付费会员返回相同全量数据(分页仍按 page / page_size)。

7.2 查询快照详情

GET /queries/{id}

响应 data:完整 QueryLog + snapshot + related_intents[]


8. 采购参考接口

8.1 跳转购买记录列表

GET /purchase-intents

参数 类型 说明
keyword string? 药品名搜索
platform_id string? 平台筛选
days int? 可选时间筛选(用户主动筛选,非会员限制)

不做会员级裁剪:体验用户与付费会员返回相同全量数据。

响应 data.items[]

{
  "id": "pi_xyz789",
  "query_id": "q_abc123",
  "drug_name": "阿莫西林胶囊",
  "spec": "0.25g×24粒",
  "manufacturer": "石药集团",
  "platform": "药帮忙",
  "platform_id": "yaobangmang",
  "reference_price": 8.50,
  "clicked_at": "2026-06-27T14:35:00Z",
  "source_client": "windows"
}

8.2 跳转购买详情

GET /purchase-intents/{id}

含关联 query_summary(若有 query_id)。

8.3 写入跳转记录(桌面/Android 调用,小程序只读)

POST /purchase-intents

小程序 MVP 不暴露此接口;由 Windows/Android 在点击「去购买」时调用。

{
  "query_id": "q_abc123",
  "drug_name": "阿莫西林胶囊",
  "spec": "0.25g×24粒",
  "manufacturer": "石药集团",
  "platform_id": "yaobangmang",
  "reference_price": 8.50,
  "source_client": "windows",
  "external_url": "https://..."
}

8.4 写入查询快照(桌面/Android 调用)

POST /queries

小程序 MVP 不暴露写接口。

{
  "keyword": "阿莫西林胶囊",
  "source_client": "windows",
  "result_count": 3,
  "lowest_platform": "药帮忙",
  "lowest_price": 8.50,
  "snapshot": { "items": [ /* ... */ ] }
}

8. 手动采购台账(V1.1)

8.1 列表

GET /procurement-ledgers

仅付费会员可用;体验用户返回 40301

8.2 创建

POST /procurement-ledgers

{
  "intent_id": "pi_xyz789",
  "query_id": "q_abc123",
  "drug_name": "阿莫西林胶囊",
  "spec": "0.25g×24粒",
  "qty": 10,
  "unit_price": 8.50,
  "total": 85.00,
  "platform": "药帮忙",
  "order_note": "6月补货",
  "status": "ordered"
}

8.3 更新 / 删除

PATCH /procurement-ledgers/{id}
DELETE /procurement-ledgers/{id}


9. 会员与支付接口

9.1 获取套餐列表

GET /membership/plans

响应 data.plans[]

{
  "package_type": "yearly",
  "name": "年卡会员",
  "price": 899.00,
  "original_price": 999.00,
  "duration_days": 365,
  "badge": "最划算",
  "features": ["不限查询", "1999关注/月"]
}

9.2 创建会员订单

POST /membership/orders

{
  "package_type": "yearly",
  "source_client": "mini_program"
}

响应 data

{
  "order_id": "ord_123",
  "order_no": "202606271430001",
  "amount": 899.00,
  "status": "pending",
  "wechat_pay": {
    "timeStamp": "1719492600",
    "nonceStr": "abc123",
    "package": "prepay_id=wx...",
    "signType": "RSA",
    "paySign": "..."
  }
}

小程序调用 wx.requestPayment(wechat_pay)

9.3 查询订单状态

GET /membership/orders/{order_no}

用于支付后轮询:

{
  "order_no": "202606271430001",
  "status": "paid",
  "paid_at": "2026-06-27T14:30:05Z",
  "member_expire_at": "2027-06-27T14:30:05Z"
}

9.4 微信支付回调

POST /payments/wechat/notify

微信服务器回调,验签后更新 Order 状态及 User 会员字段。不对小程序暴露。


10. 邀请与体验券

10.1 邀请统计

GET /invites/stats

{
  "invite_code": "PX8K2M",
  "invited_count": 5,
  "activated_count": 3,
  "total_reward_days": 21,
  "records": [
    {
      "invitee_phone_masked": "138****1234",
      "status": "activated",
      "reward_days": 7,
      "activated_at": "2026-06-20T10:00:00Z"
    }
  ]
}

10.2 体验券核销

POST /coupons/redeem

{ "code": "TRIAL-ABCD-1234" }

成功响应:

{
  "days_added": 15,
  "trial_end_at": "2026-07-12T00:00:00Z",
  "member_type": "trial"
}

11. 内容与配置

11.1 帮助与 FAQ

GET /content/help

返回 FAQ 列表、合规文案、桌面下载链接。

11.2 桌面下载链接

GET /content/download

{
  "windows_url": "https://proprice.kailin.com.cn/download/windows",
  "official_site_url": "https://proprice.kailin.com.cn",
  "mini_program_appid": "wx...",
  "version": "1.0.0",
  "release_notes": "..."
}

12. 错误码补充

code message 示例 场景
40302 体验用户历史记录超出可见范围 已废弃:历史不做会员裁剪
40303 请升级会员后使用采购台账 V1.1 台账
40304 请先上传营业执照 已废弃:小程序历史/采购不因执照状态拦截
40402 用户未注册 登录后业务接口
40901 体验券已使用或无效 核销失败
40902 订单已支付或已关闭 重复支付
40903 营业执照审核中,请勿重复提交 重复上传
41301 图片超过 5MB 或格式不支持 执照上传

13. 接口清单汇总

方法 路径 调用端 MVP
POST /auth/mp/login 小程序
POST /auth/register 小程序
POST /auth/refresh 小程序
GET /users/me 小程序
GET /users/me/dashboard 小程序
GET /licenses/current 小程序
POST /licenses/upload 小程序
GET /licenses/current/image-url 小程序
GET /platform-bindings 小程序
POST /platform-bindings 小程序
DELETE /platform-bindings/{platform_id} 小程序
POST /platform-bindings/{platform_id}/validate 小程序
GET /queries 小程序
GET /queries/{id} 小程序
POST /queries 桌面/Android
GET /purchase-intents 小程序
GET /purchase-intents/{id} 小程序
POST /purchase-intents 桌面/Android
GET /membership/plans 小程序
POST /membership/orders 小程序
GET /membership/orders/{order_no} 小程序
POST /payments/wechat/notify 微信服务器
GET /invites/stats 小程序
POST /coupons/redeem 小程序
GET /content/help 小程序
GET /content/download 小程序
GET /procurement-ledgers 小程序 V1.1
POST /procurement-ledgers 小程序 V1.1

14. 数据库变更建议

-- User 扩展
ALTER TABLE users ADD COLUMN wx_openid VARCHAR(64) NULL;
ALTER TABLE users ADD COLUMN wx_unionid VARCHAR(64) NULL;
CREATE UNIQUE INDEX idx_users_wx_openid ON users(wx_openid);

-- BusinessLicense 新表
CREATE TABLE business_licenses (
  id VARCHAR(32) PRIMARY KEY,
  user_id VARCHAR(32) NOT NULL,
  image_url TEXT NOT NULL,
  status VARCHAR(16) NOT NULL DEFAULT 'pending',
  reject_reason TEXT NULL,
  submitted_at TIMESTAMP NOT NULL,
  reviewed_at TIMESTAMP NULL,
  source_client VARCHAR(32) NOT NULL,
  reviewer_id VARCHAR(32) NULL,
  INDEX idx_bl_user_status (user_id, status),
  INDEX idx_bl_pending (status, submitted_at)
);

-- QueryLog 扩展
ALTER TABLE query_logs ADD COLUMN source_client VARCHAR(32) NOT NULL DEFAULT 'windows';
ALTER TABLE query_logs ADD COLUMN result_count INT NOT NULL DEFAULT 0;
ALTER TABLE query_logs ADD COLUMN lowest_platform VARCHAR(32) NULL;
ALTER TABLE query_logs ADD COLUMN lowest_price DECIMAL(10,2) NULL;
ALTER TABLE query_logs ADD COLUMN snapshot JSON NOT NULL;

-- PurchaseIntent 新表
CREATE TABLE purchase_intents (
  id VARCHAR(32) PRIMARY KEY,
  user_id VARCHAR(32) NOT NULL,
  query_id VARCHAR(32) NULL,
  drug_name VARCHAR(128) NOT NULL,
  spec VARCHAR(64) NOT NULL,
  manufacturer VARCHAR(128) NULL,
  platform_id VARCHAR(32) NOT NULL,
  reference_price DECIMAL(10,2) NOT NULL,
  clicked_at TIMESTAMP NOT NULL,
  source_client VARCHAR(32) NOT NULL,
  external_url TEXT NULL,
  INDEX idx_pi_user_clicked (user_id, clicked_at DESC),
  INDEX idx_pi_query (query_id)
);

-- Order 扩展
ALTER TABLE orders ADD COLUMN source_client VARCHAR(32) NOT NULL DEFAULT 'windows';