3d1e8969e6
- 新增 docs/integrations/(README + jiguang/sms/meituan/pangle/wxpay 各一篇): 记录各 SDK 集成的签名/验签/加解密/协议细节与踩坑(对齐 app/integrations 分层) - docs/api 接口文档变薄: 受影响接口头部加「集成实现」链接,把验签/RSA/CPS 签名 等重逻辑描述移到集成文档;ad-pangle-callback 验签段精简为指针 - docs/api/README 补架构说明(api 薄 / 重逻辑在 integrations) - 后端技术实现.md 目录树补全(福利/钱包/签到/省钱/发奖端点 + crud/integrations 现状), pangle/wxpay 标注移入 integrations - ad_reward_golive_checklist 路径同步 core→integrations Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
37 lines
2.0 KiB
Markdown
37 lines
2.0 KiB
Markdown
# 极光一键登录 — 服务端核验 + RSA 解密手机号(jiguang)
|
||
|
||
> 文件:`app/integrations/jiguang.py` | 关联接口:[auth-jverify-login](../api/auth-jverify-login.md) | [← 集成索引](./README.md)
|
||
|
||
## 作用
|
||
极光一键登录的服务端环节:拿客户端的 `loginToken` 调极光 REST 验真,取回 RSA 加密的手机号并解密成明文。
|
||
|
||
## 链路
|
||
```
|
||
Android SDK loginAuth → loginToken
|
||
→ 本服务 POST 极光 /v1/web/loginTokenVerify (Basic Auth = AppKey:MasterSecret)
|
||
→ 极光返回 RSA 公钥加密的手机号 (base64)
|
||
→ 用配套 RSA 私钥解密
|
||
→ 返回明文手机号
|
||
```
|
||
|
||
## 函数 / 异常
|
||
- `verify_and_get_phone(login_token)` —— 对外入口,验证 + 解密一把梭。
|
||
- 失败统一抛 `JiguangError`,api 层 catch 后翻成 4xx/5xx(验证失败/解密失败 → `502`)。
|
||
- RSA 私钥**懒加载并缓存**(`_private_key_cache`):文件缺失抛 `JiguangError`(让单请求失败 + 日志,而不是 import 时炸进程)。
|
||
|
||
## RSA 解密策略(关键)
|
||
极光文档没明说 padding。实测 PKCS1v15 套在 OAEP 密文上会"假成功"返回垃圾(`UnicodeDecodeError 0x8e`)。因此按 **OAEP-SHA1 → OAEP-SHA256 → PKCS1v15** 顺序尝试,谁能解出 **11 位纯数字手机号**就用谁;base64 先按 4 字节对齐补 `=`(各运营商可能返回不带 `=` 的 base64)。
|
||
|
||
## 配置
|
||
| 配置项 | 说明 |
|
||
|---|---|
|
||
| `JG_APP_KEY` / `JG_MASTER_SECRET` | 极光 AppKey / MasterSecret(拼 Basic Auth) |
|
||
| `JG_PRIVATE_KEY_PATH` | RSA 私钥 .pem 路径 |
|
||
| `JG_VERIFY_ENDPOINT` | 极光验证接口 URL(`/v1/web/loginTokenVerify`) |
|
||
| `JG_REQUEST_TIMEOUT_SEC` | 请求超时 |
|
||
|
||
## 踩坑
|
||
- **私钥必须与极光控制台为该 appkey 登记的公钥配对**,否则三种 padding 全失败、报 `all RSA paddings failed; last error: Decryption failed`。私钥由相关开发同学生成提供。
|
||
- **换私钥后必须重启后端**——`_private_key_cache` 会缓存旧 key。
|
||
- 极光验证响应 `code != 8000` 视为失败;缺 `phone` 字段也失败。
|