版本:V1.4
更新日期:2026-07-09
变更说明:响应 userInfo 补全完整返回字段(userName、药店信息、邀请人信息等);修正 nickname 优先级描述(nickname > username)
本接口用于第三方系统通过用户手机号换取登录 Token,实现免密登录。系统会自动查找或注册用户,返回访问令牌和刷新令牌。同时支持第三方系统传入用户详细信息(用户名、药店名称、地址、联系人等),由我方负责存储,第三方无需我方再次维护用户信息。
核心特性:
t_business_license,免去额外调用入驻接口tokenVersion,不踢出 PC 端已有会话licenseApproved=true)自动赠送 30 天 PRO 高级会员| 项目 | 说明 |
|---|---|
| 接口名称 | 外部系统换取小程序 Token |
| 请求方式 | POST |
| 接口路径 | /api/auth/external/miniapp-token |
| Content-Type | application/json |
| 字符编码 | UTF-8 |
使用 API Key 鉴权,在请求头中传入:
X-Api-Key: {我方提供的API Key}
API Key 格式建议:32 位随机十六进制字符串(大小写字母 + 数字)。
参考示例:a3f8c21e67b94d0e5f1a6c8d3b9e2071⚠️ 请妥善保管 API Key,不要泄露到前端代码或客户端。请在后端服务中调用此接口。
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
X-Api-Key |
String | 是 | 接口鉴权密钥 |
Content-Type |
String | 是 | 固定值 application/json |
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
phone |
String | 是 | 用户手机号 |
inviteCode |
String | 否 | 邀请码(仅新用户注册时生效) |
| 参数名 | 类型 | 必填 | 说明 | 对应我方字段 |
|---|---|---|---|---|
username |
String | 否 | 用户名(保存到 userName 字段;若未传 nickname,则自动作为 nickname 的兜底值) | nickname / userName |
nickname |
String | 否 | 昵称(不传则使用 username,再不传则按手机号生成) | nickname |
pharmacyName |
String | 否 | 药店名称 | pharmacy_name |
province |
String | 否 | 省 | province |
city |
String | 否 | 市 | city |
district |
String | 否 | 区 | district |
pharmacyAddress |
String | 否 | 药店详细地址 | pharmacy_address |
contactPerson |
String | 否 | 联系人 | contact_person |
contactPhone |
String | 否 | 联系电话 | contact_phone |
businessLicenseNo |
String | 否 | 营业执照号(统一社会信用代码) | business_license_no |
| 参数名 | 类型 | 必填 | 说明 | 对应我方字段 |
|---|---|---|---|---|
storeName |
String | 否 | 店铺名称(不传则使用 pharmacyName) | store_name |
terminalType |
String | 否 | 终端类型:1-单店 / 2-连锁 / 3-诊所、社康等 |
terminal_type |
businessLicenseUrl |
String | 否 | 营业执照图片URL | license_image_url |
drugLicenseUrl |
String | 否 | 药品经营许可证图片URL | drug_license_url |
medicalDeviceClass2Url |
String | 否 | 二类医疗器械备案图片URL | medical_device_class2_url |
medicalDeviceClass3Url |
String | 否 | 三类医疗器械备案图片URL | medical_device_class3_url |
licenseApproved |
Boolean | 否 | 审核状态标记。true = 第三方已审核通过,无需我方再次审核,直接设为 APPROVED 并赠送 30 天高级会员;不传/false = 待审核 PENDING |
— |
💡 审核状态说明:
- 如果第三方系统已完成资质审核,传
licenseApproved: true,我方将直接标记为"审核通过"并赠送 30 天 PRO 高级会员- 如果第三方尚未审核或不确定,不传该字段(默认
PENDING),由我方运营审核- 已审核通过的入驻记录不会因后续调用而降级
- 只要请求中包含任一入驻信息字段(storeName / terminalType / businessLicenseUrl / drugLicenseUrl / medicalDeviceClass2Url / medicalDeviceClass3Url),即自动写入
t_business_license表licenseApproved=true:审核状态设为APPROVED(审核通过),首次通过赠送 30 天 PRO 高级会员- 未传
licenseApproved或false:审核状态设为PENDING(待运营审核)- 已存在入驻记录:已 APPROVED 状态不降级,PENDING/REJECTED 状态可随
licenseApproved=true升级- 省/市/区/地址/联系人/电话等字段会自动从用户信息字段中提取填入
💡 字段更新规则:
- 新用户会写入所有传入字段
- 已存在用户仅更新非空字段(不会清空已有数据)
💡 nickname 优先级:
nickname>username> 手机号生成(如用户8000)💡 建议:第三方每次调用时传入最新的用户信息,我方会自动同步更新,无需额外维护。
{
"phone": "13800138000"
}
{
"phone": "13800138000",
"inviteCode": "ABC123",
"username": "yaohuigou001",
"nickname": "药汇购001",
"pharmacyName": "北京同仁堂大药房",
"province": "北京市",
"city": "北京市",
"district": "朝阳区",
"pharmacyAddress": "建国路88号",
"contactPerson": "张三",
"contactPhone": "13800138000",
"businessLicenseNo": "91110105MA12345678",
"storeName": "北京同仁堂大药房(朝阳分店)",
"terminalType": "1",
"businessLicenseUrl": "https://oss.example.com/yyzz.jpg",
"drugLicenseUrl": "https://oss.example.com/ypjy.jpg",
"medicalDeviceClass2Url": "https://oss.example.com/elqx.jpg",
"medicalDeviceClass3Url": "https://oss.example.com/slqx.jpg",
"licenseApproved": true
}
{
"code": 200,
"message": "success",
"data": { }
}
| 字段 | 类型 | 说明 |
|---|---|---|
code |
int | 状态码,200 表示成功 |
message |
String | 提示信息 |
data |
Object | 登录响应数据 |
| 参数名 | 类型 | 说明 |
|---|---|---|
userId |
String | 用户ID(字符串,避免JS大数精度丢失) |
accessToken |
String | 访问令牌 |
refreshToken |
String | 刷新令牌 |
expiresIn |
Long | accessToken有效期(秒),默认7200 |
newUser |
Boolean | 是否为新注册用户 |
needBindPhone |
Boolean | 始终返回false |
role |
String | 固定值"USER" |
userInfo |
Object | 用户基本信息 |
| 参数名 | 类型 | 说明 |
|---|---|---|
id |
String | 用户ID |
phone |
String | 手机号 |
nickname |
String | 昵称(即第三方传入的 nickname 或 username) |
userName |
String | 第三方传入的原始用户名 |
avatar |
String | 头像 URL |
wechatBound |
Boolean | 是否已绑定微信 |
loginSource |
String | 登录来源,"MINIAPP" 表示小程序 |
pharmacyName |
String | 药店名称 |
province |
String | 省 |
city |
String | 市 |
district |
String | 区 |
membershipLevel |
String | 会员等级代码(PLUS / PRO / ULTRA) |
membershipLevelName |
String | 会员等级名称 |
licenseStatus |
String | 营业执照审核状态:NOT_SUBMITTED / PENDING / APPROVED / REJECTED |
inviterId |
String | 邀请人用户ID(未绑定邀请码则为 null) |
inviterNickname |
String | 邀请人昵称 |
hasBoundInviteCode |
Boolean | 是否已绑定邀请码 |
createTime |
String | 注册时间 |
{
"code": 200,
"message": "success",
"data": {
"userId": "1234567890123456789",
"accessToken": "eyJhbGciOiJIUzI1NiJ9...",
"refreshToken": "eyJhbGciOiJIUzI1NiJ9...",
"expiresIn": 7200,
"newUser": false,
"needBindPhone": false,
"role": "USER",
"userInfo": {
"id": "1234567890123456789",
"phone": "138****8000",
"nickname": "药汇购001",
"userName": "yaohuigou001",
"avatar": null,
"wechatBound": false,
"loginSource": "MINIAPP",
"pharmacyName": "北京同仁堂大药房",
"province": "北京市",
"city": "北京市",
"district": "朝阳区",
"membershipLevel": "PRO",
"membershipLevelName": "高级会员",
"licenseStatus": "APPROVED",
"inviterId": "1234567890123456788",
"inviterNickname": "邀请人昵称",
"hasBoundInviteCode": true,
"createTime": "2025-01-01T12:00:00"
}
}
}
| 错误码 | 说明 | 处理建议 |
|---|---|---|
200 |
成功 | — |
401 |
API Key 无效或缺失 | 检查X-Api-Key请求头 |
400 |
参数校验失败 | 检查phone是否为空 |
500 |
服务器内部错误 | 重试,持续失败联系我方 |
后续所有业务接口请求需在请求头中携带 accessToken:
Authorization: Bearer {accessToken}
accessToken 过期后,使用 refreshToken 换取新 Token:
POST /api/auth/refresh
Content-Type: application/json
{ "refreshToken": "{refreshToken}" }
刷新后旧 refreshToken 立即失效(Token 旋转机制)。
建议客户端定时调用心跳接口,保持登录状态:
POST /api/auth/heartbeat
Authorization: Bearer {currentAccessToken}
建议间隔 = accessToken有效期 × 80%,约5760秒。
| # | 说明 |
|---|---|
| 1 | PC端严格单设备,小程序与PC互不干扰,同一账号可同时登录 |
| 2 | 手机号未注册时自动创建账号并初始化 PLUS 会员(普通会员) |
| 3 | inviteCode仅新用户注册时生效 |
| 4 | API Key请在后端调用,勿暴露到客户端 |
| 5 | accessToken默认2小时,refreshToken默认7天 |
| 6 | 每次刷新后旧refreshToken立即作废,请保存最新的 |
| 7 | 用户信息字段(username、药店信息等)每次调用都会同步更新,建议传入最新数据 |
| 8 | username 会保存到我方的 nickname 字段,不需要额外维护用户名表 |
| 9 | 传入入驻信息字段后自动创建/更新入驻记录,无需再调用 /api/business-license/upload |
| 10 | licenseApproved=true 时入驻状态直接审核通过,首次通过赠送 30 天 PRO 高级会员 |
| 11 | 已审核通过的入驻记录(APPROVED)不会因后续调用而降级 |
curl -X POST "https://your-domain.com/api/auth/external/miniapp-token" \
-H "Content-Type: application/json" \
-H "X-Api-Key: your-api-key-here" \
-d '{
"phone": "13800138000",
"username": "yaohuigou001",
"pharmacyName": "北京同仁堂大药房",
"province": "北京市",
"city": "北京市",
"district": "朝阳区",
"pharmacyAddress": "建国路88号",
"contactPerson": "张三",
"contactPhone": "13800138000",
"businessLicenseNo": "91110105MA12345678",
"storeName": "北京同仁堂大药房(朝阳分店)",
"terminalType": "1",
"businessLicenseUrl": "https://oss.example.com/yyzz.jpg",
"drugLicenseUrl": "https://oss.example.com/ypjy.jpg",
"licenseApproved": true
}'
OkHttpClient client = new OkHttpClient();
String json = "{"
+ "\"phone\": \"13800138000\","
+ "\"username\": \"yaohuigou001\","
+ "\"pharmacyName\": \"北京同仁堂大药房\","
+ "\"province\": \"北京市\","
+ "\"city\": \"北京市\","
+ "\"district\": \"朝阳区\","
+ "\"pharmacyAddress\": \"建国路88号\","
+ "\"contactPerson\": \"张三\","
+ "\"contactPhone\": \"13800138000\","
+ "\"businessLicenseNo\": \"91110105MA12345678\","
+ "\"storeName\": \"北京同仁堂大药房(朝阳分店)\","
+ "\"terminalType\": \"1\","
+ "\"businessLicenseUrl\": \"https://oss.example.com/yyzz.jpg\","
+ "\"drugLicenseUrl\": \"https://oss.example.com/ypjy.jpg\","
+ "\"licenseApproved\": true"
+ "}";
RequestBody body = RequestBody.create(json, MediaType.parse("application/json"));
Request request = new Request.Builder()
.url("https://your-domain.com/api/auth/external/miniapp-token")
.post(body)
.addHeader("X-Api-Key", "your-api-key-here")
.addHeader("Content-Type", "application/json")
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println(response.body().string());
}
import requests
url = "https://your-domain.com/api/auth/external/miniapp-token"
headers = {
"X-Api-Key": "your-api-key-here",
"Content-Type": "application/json"
}
data = {
"phone": "13800138000",
"username": "yaohuigou001",
"pharmacyName": "北京同仁堂大药房",
"province": "北京市",
"city": "北京市",
"district": "朝阳区",
"pharmacyAddress": "建国路88号",
"contactPerson": "张三",
"contactPhone": "13800138000",
"businessLicenseNo": "91110105MA12345678",
"storeName": "北京同仁堂大药房(朝阳分店)",
"terminalType": "1",
"businessLicenseUrl": "https://oss.example.com/yyzz.jpg",
"drugLicenseUrl": "https://oss.example.com/ypjy.jpg",
"licenseApproved": True
}
response = requests.post(url, json=data, headers=headers)
print(response.json())
第三方传入字段与我方数据库字段的对应关系:
| 第三方传入字段 | 我方数据库字段 | 我方实体字段 | 说明 |
|---|---|---|---|
phone |
phone |
phone |
手机号(必填) |
username |
nickname |
nickname |
用户名(同时写入 nickname 和 userName) |
nickname |
nickname |
nickname |
昵称(优先级低于 username) |
pharmacyName |
pharmacy_name |
pharmacyName |
药店名称(也作为 storeName 兜底) |
province |
province |
province |
省 |
city |
city |
city |
市 |
district |
district |
district |
区 |
pharmacyAddress |
pharmacy_address |
pharmacyAddress |
药店详细地址 |
contactPerson |
contact_person |
contactPerson |
联系人 |
contactPhone |
contact_phone |
contactPhone |
联系电话 |
businessLicenseNo |
business_license_no |
businessLicenseNo |
营业执照号 |
| 第三方传入字段 | 我方数据库字段 | 我方实体字段 | 说明 |
|---|---|---|---|
storeName |
store_name |
storeName |
店铺名称(不传则用 pharmacyName) |
terminalType |
terminal_type |
terminalType |
终端类型 |
businessLicenseUrl |
license_image_url |
licenseImageUrl |
营业执照图片URL |
drugLicenseUrl |
drug_license_url |
drugLicenseUrl |
药品经营许可证图片URL |
medicalDeviceClass2Url |
medical_device_class2_url |
medicalDeviceClass2Url |
二类医疗器械备案图片URL |
medicalDeviceClass3Url |
medical_device_class3_url |
medicalDeviceClass3Url |
三类医疗器械备案图片URL |
licenseApproved |
review_status |
reviewStatus |
审核状态标记,true → APPROVED / false → PENDING |
💡 入驻记录保存时,以下字段由系统自动填入(无需第三方传入):
store_address← 从pharmacyAddress提取credit_code← 从businessLicenseNo提取sync_source← 固定为MINIAPP_SYNCreview_status← 取决于licenseApproved:true→APPROVED,false/不传 →PENDINGshow_verified_badge← 首次审核通过时设为true
如有问题,请联系我方技术支持。
| 版本 | 日期 | 变更内容 |
|---|---|---|
| V1.0 | 2026-07-07 | 初始版本:基础登录接口 |
| V1.1 | 2026-07-07 | 扩展请求参数:支持传入用户名、药店信息等,自动保存到用户表 |
| V1.2 | 2026-07-09 | 新增入驻信息字段(storeName / terminalType / businessLicenseUrl / drugLicenseUrl / medicalDeviceClass2Url / medicalDeviceClass3Url),传入后同步写入 t_business_license,无需额外调用入驻接口 |
| V1.3 | 2026-07-09 | 新增 licenseApproved 参数支持第三方已审核入驻状态直通;审核通过自动赠送 30 天 PRO 高级会员;已 APPROVED 状态不降级;响应新增 licenseStatus 字段 |
| V1.4 | 2026-07-09 | 响应 userInfo 补全完整返回字段(userName、pharmacyName、province、city、district、inviterId、inviterNickname、hasBoundInviteCode);修正 nickname 优先级描述(nickname > username) |