本页内容 应用身份由平台登记平台登录与会话两种应用范围会话变化与退出应用标识的安全边界Android:安装登录响应后创建客户端iOS:在会话写入成功后继续
APP SDK / Android · iOS

账号与厂家范围

使用平台注册的 clientId 和平台会话,约束车辆绑定、商城与门店的厂家范围。

应用身份由平台登记

每个合作应用使用平台登记的 clientId。平台将它关联到固定厂家,并启用对应服务。Android 使用 Configuration.clientId,iOS 使用 configureWithConsent:clientId:paymentScheme:。不要沿用 SDK 默认的官方应用标识。

manufacturerId 是服务端返回的业务范围,不是接入方自由传入的授权参数。修改请求头或在 UI 隐藏其他厂家都不能替代服务端校验。

平台登录与会话

宿主调用约定的平台登录、验证接口。登录请求须携带 X-App-Client: <registeredClientId>;SDK 为它自己发起的后续请求添加此请求头,宿主自行发起的请求仍由宿主负责。

登录响应原样交给 SDK,会话包含:

字段 含义
user.id 平台用户 ID,字符串
accessToken 平台签发的访问令牌
expiresAt、verifiedAt ISO 8601 时间
clientId 与 SDK 配置一致的应用身份
manufacturerId 平台签发的厂家范围,官方跨厂家会话可以为空

SDK 校验会话并安全存储。伪造 JSON 字段不会取得平台权限。合作方自有 token 不能直接作为平台 token;当前版本不提供合作方账号换票。

两种应用范围

场景 车辆 商城与门店
无限骑行官方 APP 按用户授权访问不同厂家车辆 根据选中的 vehicleId 解析厂家
固定厂家 APP 只能绑定和访问平台允许的对应厂家车辆 浏览固定厂家内容,可省略浏览接口的 vehicleId

下单仍需明确的 vehicleId 和 bindingVersion。厂家应用传入不匹配车辆时,不能借此切换厂家。订单同时受账号与应用范围限制;金额、库存、可执行动作以服务端返回为准。

未知或停用的应用不能登录。厂家会话不能通过删掉 X-App-Client 或改成官方标识扩大权限。正式交付前由平台确认应用登记、厂家映射及对应服务已经启用。

会话变化与退出

账号或 token 改变后,取消旧云操作,等待回调,安装新会话并重新创建车辆与商城客户端。清除旧 UI 的车辆、订单和地址状态,避免异步旧结果展示到新账号下。

退出使用 SDK 的 clearSession 或 account.clear,不要直接修改安全存储。待确认绑定、解绑和支付记录由 SDK 管理;重新登录原账号时走恢复流程。

车辆缓存与云恢复记录按 API 基址、clientId 和账号隔离;token 更新不改变记录归属。终端连接凭据仍按账号/终端保存,测试和正式环境继续使用独立安装身份与存储。

从 0.2.0 及更早版本升级时,旧记录没有保存 API/clientId 来源。有未认领的待处理记录会返回 LEGACY_SCOPE_REQUIRED。宿主必须从原安装配置核实来源,在原账号、原 API 基址和 clientId 下调用 adoptLegacy(参数空对象),成功后再 recover。不要对任意当前环境自动认领,也不要删除旧记录绕过错误。LEGACY_SCOPE_CONFLICT 表示已认领到另一来源,应回到该来源处理。旧记录保留,已完成的记录不会被再次恢复。

应用标识的安全边界

clientId 可以出现在安装包内,它不是秘密,也不能证明请求来自某个真实安装包。当前版本未集成 App Attest、Play Integrity 或包签名验证。需要这些保证的合作方案应另外约定应用真实性验证,不能把公开标识当作密钥。

不要把平台管理密钥、设备凭据或支付签名参数写入前端配置、日志或埋点。支付由 SDK 调用,订单资金状态由服务端确认。

Android:安装登录响应后创建客户端

先按 Android 接入配置已登记的 clientId 并取得隐私同意。在主线程调用下面的函数,传入平台登录响应原文和约定 API 基址。setSession 同步返回;配置或会话无效时会抛出异常。宿主捕获并提示会话错误,成功前保持业务页面关闭,不记录 JSON 或异常中的凭据。

import android.content.Context
import net.oou.mobile.CloudVehicles
import net.oou.mobile.MobileSdk

fun installVehicleSession(
    context: Context,
    platformSessionJson: String,
    apiBase: String,
    language: String
): CloudVehicles {
    MobileSdk.setSession(context, platformSessionJson)
    return MobileSdk.vehicles(context, apiBase, language)
}

iOS:在会话写入成功后继续

完成 iOS 初始化后,在主线程调用;成功分支再创建客户端并进入恢复流程。以下 ready 和 failure 由宿主提供,失败时保持业务入口关闭。

#import <InfiniteRideMobile/InfiniteRideMobile.h>

void InstallVehicleSession(NSString *sessionJSON, NSString *apiBase,
                           NSString *language,
                           void (^ready)(IRCloudVehicles *), IRReject failure) {
    [[IRMobileSDK account] write:sessionJSON resolve:^(id value) {
        IRCloudVehicles *vehicles = [[IRCloudVehicles alloc]
            initWithBaseURL:apiBase language:language];
        ready(vehicles);
    } reject:failure];
}