Files
rnpay/docs/walletman后端对接.md
2026-06-17 01:57:49 +08:00

7.4 KiB
Raw Permalink Blame History

WalletMan 后端对接文档

前端集成见 walletman前端对接.md


1. 架构

Android 宿主 ◄── HTTP / WS ──► walletman (:16000 或反代) ◄── 代理 TCP ──► 钱包 API
                ◄── FCM data ──► Firebase
链路 用途
HTTP REST 登录、绑钱包、查流水等业务
WebSocket /ws 设备注册、TCP 代理、心跳
FCM data WS 断线拉活、token 过期重绑

clientId:设备唯一 IDWS 注册 key + FCM 目标 key须与 App DeviceInfo.getUniqueIdSync() 一致。


2. 启动与配置

cd servers/walletman/cmd/server
go run . -tls android
  • 默认监听 :16000
  • 测试页:http://localhost:16000/test/index.html
  • 钱包持久化:cmd/wallets.json

FCM 服务账号(二选一):

servers/walletman/cmd/server/config/fcm-service-account.json

或环境变量 FCM_SERVICE_ACCOUNT=/path/to/json。须与宿主 App 的 google-services.json 同一 Firebase 项目


3. 通用约定

响应格式:

{ "success": true, "message": "说明", "data": {} }

需登录接口请求头:

Content-Type: application/json
X-User-ID: 10000

4. HTTP 接口

POST /login

// req
{ "username": "test123", "password": "123456" }
// data
{ "userId": 10000, "userToken": "10000" }

POST /register

Token 模式绑钱包 / 静默重绑落库。

{
  "walletType": "paytm",
  "params": {
    "type": "paytm",
    "token": "...",
    "refreshToken": "...",
    "mobile": "9876543210",
    "deviceId": "...",
    "chType": "ipay",
    "chVersion": "3"
  }
}
// data
{ "walletId": "paytm_9876543210", "walletType": "paytm" }

walletId = {walletType}_{phone}

支持的 walletType(见 walletman.GetAllWalletTypes()

walletType 说明
paytm Paytm Personalipay AIDL
phonepe PhonePe Personalipay AIDL
mobikwik Mobikwik Personal
freecharge Freecharge Personal
amazonpay Amazon Pay Personal
paytm business Paytm Business
phonepe business PhonePe Business
googlepay business Google Pay Business
bharatpe business BharatPe Business

各类型 params 字段以对应 *_personal.go / *_business.go 及前端 Bind 组件为准。

POST /request-otp / POST /verify-otp

OTP 绑钱包。重绑场景若钱包已存在,会复用已有 params保留 deviceId 等),见 requestOTPHTTP

GET /wallets

{
  "wallets": [{
    "id": "paytm_9876543210",
    "walletType": "paytm",
    "phone": "9876543210",
    "upi": "xxx@paytm",
    "status": "active",
    "otpMode": false
  }]
}

status=inactiveotpMode=false 时,可能触发 FCM 重绑(见 §6

POST /fcm/register

{ "clientId": "设备ID", "fcmToken": "..." }

与 WS register.data.fcmToken 等价,均写入 FCM token 存储。

POST /fcm/send-wake

{ "clientId": "xxx" }
// 或
{ "userId": 10000 }

下发 wake_proxy,客户端重连 WS。

POST /fcm/send-rebind

{
  "walletId": "paytm_9876543210",
  "walletType": "paytm",
  "phone": "9876543210",
  "retry": false,
  "notify": true
}
字段 说明
clientId 可省略,按 wallet owner 查 GetFcmClientID
retry 传给客户端;phonepe 类型服务端会强制 retry=true
notify true 时在 data 中带 msg 文案;客户端 AIDL 失败才本地弹通知

GET /fcm/clients

已注册 FCM 的 clientId 列表。

POST /wallet/set-status

手动改钱包状态;设为 inactive 时会 maybeNotifyWalletRebind


5. WebSocket /ws

URLws://host:16000/wswss://host/ws(反代)

客户端 → 服务端

register连接后立即发送

{
  "type": "register",
  "messageId": "register_1700000000000",
  "clientId": "设备ID",
  "data": { "userId": 10000, "fcmToken": "可选" }
}
  • 绑定 clientId → Client
  • userManager.SetProxy(userId, clientId, ...)
  • 同 clientId 新连接踢旧连接

ping建议 10s

{ "type": "ping", "messageId": "ping_xxx" }

proxyReady / proxyData / proxyClose

type 说明
proxyReady TCP 已连 host:port
proxyData data.data = base64
proxyClose 结束本次代理

服务端 → 客户端

proxyRequest

{
  "type": "proxyRequest",
  "messageId": "req_1700000000000",
  "data": { "host": "api.phonepe.com", "port": 443 }
}

443 端口在服务端侧做 TLS再 HTTP/2 转发。

服务端行为

事件 行为
WS 断开 cleanupClientsendFcmWake(clientId)
45s 无活动 心跳超时清理 + wake
代理时 client 离线 requestProxy 失败 → wake
钱包 API 出网 proxyRoundTripperrequestProxy

代码入口:websocket_handler.goproxy.gofcm.go


6. FCM 下发

重绑走 data-only(不发 FCM notification 块),文案放在 data.msg,由客户端决定何时弹本地通知。

data key 说明
msg 通知文案(notify=true 时有值)
cmd wake_proxy | rebind_wallet
params JSON 字符串

wake_proxy

{ "cmd": "wake_proxy", "params": "{}" }

rebind_wallet

{
  "cmd": "rebind_wallet",
  "msg": "Paytm 已过期,点我自动重绑",
  "params": "{\"walletId\":\"paytm_9876543210\",\"walletType\":\"paytm\",\"phone\":\"9876543210\",\"retry\":false,\"tryGtkAnyway\":false}"
}

params 字段:

字段 说明
walletId 钱包 ID
walletType 钱包类型
phone 手机号
retry PhonePe 是否走 gtk 重试phonepe 类型服务端默认 true
tryGtkAnyway 客户端扩展,当前服务端固定 false

自动触发

  1. POST /wallet/set-status 设为 inactive → maybeNotifyWalletRebind(..., retry=false)
  2. 拉流水后 token 失效变 inactive → persistWalletIfChanged → phonepe 且 inactiveCount>1 时 retry=true

条件:GetOTPMode()==falseGetStatus()==inactive

发送实现

sendFcmToClient → FCM HTTP v1 projects/{id}/messages:send


7. 时序

代理请求

walletman HTTP 出网
  → GetProxyClientID(userId)
  → requestProxy(clientId, host, 443)
  → WS proxyRequest → 等 proxyReady
  → 双向 proxyData

断线拉活

WS cleanupClient
  → sendFcmWake(clientId)
  → 客户端 wakeFromPrefs → 重连 WS register

重绑

inactive 检测 / POST /fcm/send-rebind
  → FCM rebind_walletdata.msg + params
  → 客户端静默 AIDL → registerWallet → POST /register
  → 失败 → 客户端本地通知 → 用户点击 → JS handler 打开 Bind

8. 调试

方式 说明
http://localhost:16000/test/index.html 发 wake / rebind、看 WS
GET /fcm/clients 已注册设备
POST /fcm/send-wake 手动拉活
POST /fcm/send-rebind 手动重绑
现象 排查
FCM send failed 服务账号路径、project_id
no FCM token for clientId App 未 POST /fcm/register 且 WS 未带 fcmToken
Client not connected WS 未连;先发 wake
重绑发了客户端无反应 Firebase 项目是否与 App 一致logcat ProxyFcmService