oauth-business-login-app-api.md 7.9 KB

商家 / 骑手 App 三方登录接入文档(Apple / Google / LINE)

依据 specs/017-oauth-login(含 2026-10-08 业务端账号密码绑定增量)整理。 适用端:骑手 App、商家 App(含商家子账号)。用户端 App 的手机号+短信流程不在本文范围。

1. 渠道与 provider

端 Apple Google LINE
骑手 apple_rider google_rider line_rider
商家(含子账号) apple_merchant google_merchant line_merchant
  • 三方账号只做已有业务账号的快捷登录入口:骑手渠道只能绑已有有效骑手账号,商家渠道只能绑已有有效商家/子账号,不会自动创建业务账号。
  • 一个三方账号在同一 provider 下只能绑定一个业务账号;换绑需联系平台处理。

2. 总体流程

① App 取三方凭证
   Apple  :Sign in with Apple SDK → identityToken
   Google :Google Sign-In SDK → idToken
   LINE   :先调 /auth/line/authorize 拿授权地址和 state,打开授权页
② POST /infouser/user/oauthLogin 提交 provider + credential
   ├─ 已绑定 → 直接返回 { data: 用户信息, token },登录完成
   └─ 未绑定 → 返回 { data: { status:"needPhone", tempKey } }
③ 首次绑定:App 弹【账号 + 密码】表单
   POST /infouser/user/oauthBindPhone  提交 tempKey + userName + password(RSA密文)
   → 成功返回 { data: 用户信息, token },绑定并登录完成
  • token 与现有账号密码登录(syslodeing / shanglodeing)签发的是同类会话 token(骑手端 / 商家端各自独立),后续请求照旧放 token 请求头即可,无需其它接入。
  • LINE 走服务端回调时第②步由后端回调完成,App 从回跳 scheme 参数里直接拿到 token 或 tempKey,见第 6 节。

3. 接口:签发 LINE 授权地址 POST /auth/line/authorize(免登录)

业务端 LINE 登录必须先从服务端拿授权地址(内含服务端签发的 state,5 分钟有效、单次消费),不要自行拼接 LINE 授权 URL。

请求体:

{ "provider": "line_rider" }   // 商家端传 line_merchant

响应:

{
  "code": 200,
  "data": {
    "authorizationUrl": "https://access.line.me/oauth2/v2.1/authorize?...",
    "state": "32位hex"
  }
}

App 打开 authorizationUrl(系统浏览器或 WebView),并保存 state 用于回跳比对。

4. 接口:三方登录第一步 POST /infouser/user/oauthLogin(免登录)

请求体:

字段 必填 说明
provider 是 见第 1 节
credential 是 Apple=identityToken;Google=idToken;LINE=授权 code
state LINE 直连提交 code 时必填 /auth/line/authorize 返回的 state;Apple/Google 不传
cid cidType deviceToken voIPToken 否 推送字段,与现有登录一致
fullName 否 仅 Apple:首次授权时用户共享的姓名,从 ASAuthorization 凭证取;后续登录不再传

响应 A(已绑定,直接登录):

{ "code": 200, "msg": "...", "data": { ...用户信息... }, "token": "xxx" }

响应 B(未绑定,首次):

{ "code": 200, "msg": "...", "data": { "status": "needPhone", "tempKey": "xxx" } }
  • tempKey 5 分钟有效、一次性:过期或任何一步失败,都要重新从 oauthLogin 开始,不能重试旧 tempKey。
  • 注意:字段名 needPhone 是历史契约(用户端为手机号+短信),业务端拿到该状态后展示的是「账号 + 密码」表单,不走短信。
  • 响应 data 不含三方渠道字段(骑手返回账号实体、商家返回 MerchantLoginView,均只有账号资料);登录渠道 App 自己发起时已知,需要展示时按第 7 节查询。

失败: code != 200(凭证无效/过期、provider 不支持、账号已停用、state 无效等),直接提示 msg。

5. 接口:首次绑定 POST /infouser/user/oauthBindPhone(免登录)

业务端绑定 = 校验业务账号密码后写入三方绑定,成功即登录。

请求体:

字段 必填 说明
tempKey 是 oauthLogin 返回
userName 是 业务账号登录名(与 syslodeing / shanglodeing 登录用的账号一致)
password 是 RSA 公钥加密后的密码密文,加密方式与现有账号密码登录完全一致(同一公钥、同一格式,直接复用现有加密函数)
cid cidType deviceToken voIPToken 否 推送字段

业务端不传 phone / code(那是用户端 App 的短信绑定参数)。

响应(成功):

{ "code": 200, "msg": "...", "data": { ...用户信息... }, "token": "xxx" }

绑定成功后即完成登录,无需再调登录接口;该三方账号下次登录走 oauthLogin 直接拿 token。

失败(不写绑定、不签 token):

场景 处理建议
tempKey 缺失/过期 重新发起 oauthLogin
缺 userName / password 表单校验拦截
账号不存在 提示 msg(账号名或角色不符、已删除均按不存在处理)
密码错误 提示 msg,可重输
账号停用 / 子账号被禁用或归属失效 提示 msg,联系平台

6. LINE 服务端回调 GET /auth/line/callback(LINE 服务器调用,App 不直接请求)

LINE 授权完成后,后端处理回调并 302 跳回对应 App 的 scheme,App 按查询参数分流:

回跳参数 含义 App 动作
?token=...&state=... 已绑定,登录成功 比对 state 后保存 token,进入首页
?needPhone=1&tempKey=...&state=... 未绑定,首次 比对 state 后弹账号+密码表单 → 调 oauthBindPhone
?error=no_code\|user_stopped\|fail&state=... 失败 提示失败,可重试
  • App 必须比对回跳 state 与第 3 节保存的发起值,不一致视为异常放弃本次登录。
  • 若业务端在 H5/webview 内能自己拿到授权 code,也可不走回调,改为直接调 oauthLogin 提交 provider + credential(code) + state。

7. 登录渠道与第三方名称展示(与用户端同一契约)

与用户端 App 一致:登录接口响应不带渠道字段,需要展示「本次登录渠道 + 第三方名称」时调用:

GET /infouser/user/getuserinfo(token 请求头;骑手/商家 OAuth 登录签发的 token 均可直接调用)

响应 data 中与渠道相关的两个字段(017 2026-09-24 增量,三端共用同一契约):

字段 说明
oauthProvider 本次会话登录渠道:apple_rider / google_rider / line_rider / apple_merchant / google_merchant / line_merchant;账号密码登录的会话该字段为空
providerDisplayName 该渠道的第三方显示名称(LINE 的 displayName / Apple 首次授权共享的 fullName),可空

展示规则(与用户端一致):

  • 第三方名称与账号昵称 nickName 分开显示;providerDisplayName 为空时只展示渠道(如「Apple 登录」),不要用昵称冒充第三方名称。
  • LINE 名称由服务端每次成功登录自动刷新,App 无需额外操作。
  • 这两个字段反映的是本次会话的登录方式,不是账号维度的「最后一次登录方式」。

8. 注意事项汇总

  1. Apple / Google:App 用各自 SDK 在本地取凭证后直接调 oauthLogin,无需服务端授权地址。
  2. LINE:必须走 /auth/line/authorize 拿授权地址与 state(服务端校验单次消费),state 过期需重新获取。
  3. tempKey 一次性、5 分钟 TTL;绑定任何失败都从 oauthLogin 重来。
  4. 密码只接受 RSA 密文,与现有登录接口同公钥同格式。
  5. 各端 audience/clientId 独立:Apple/Google 凭证必须用对应业务端 App 的 bundleId/clientId 获取,用户端凭证在业务端会被拒绝。