DEV-19566: Bank of America Open Banking API Migration
Ticket Overview
Section titled “Ticket Overview”| Field | Value |
|---|---|
| Key | DEV-19566 |
| Summary | Upcoming Change: Bank of America Open Banking API Migration |
| Status | In Progress |
| Priority | Medium |
| Assignee | Heli Yin |
| Created by | Yan Hu |
| Created | 2026-03-05 |
Background
Section titled “Background”Yodlee 通知 Bank of America (BOA) 将升级其 Open Banking API 至新版本,导致所有连接的认证方式发生变化。迁移暂定 2026 年 4 月底开始,6 月底结束。
核心变化:
- 所有用户必须一次性重新认证 BOA 连接
- BOA 的 Provider ID 将变更(Yodlee 侧的机构标识符更换为新 ID)
providerAccountId和accountId保持不变(Yodlee 已确认,重新认证后连接 ID 和账户 ID 不变)
Product Lead (Megan) 要求工程团队评估 Yodlee 邮件中高亮的两个关注点:
- Sync Data Extracts API:如果应用通过 sync API 消费 Yodlee 数据,需验证应用能正确更新新的 provider 和 providerAccountId
- FastLink Deep Link Flow:如果应用使用 FastLink Deep Link flow,需将现有 provider ID 替换为新 provider ID
Investigation
Section titled “Investigation”1. Sync Data Extracts API — 不适用
Section titled “1. Sync Data Extracts API — 不适用”RightCapital 不使用 Yodlee 的 Data Extracts API,使用的是标准 REST API:
| API Endpoint | 用途 | 代码位置 |
|---|---|---|
GET /providerAccounts | 拉取所有 provider accounts | Api::getProviderAccounts() |
GET /providerAccounts/{id} | 获取单个 provider account | Api::getProviderAccount() |
GET /accounts?providerAccountId={id} | 获取账户详情 | Api::getAccounts() |
PUT /providerAccounts?providerAccountIds={id} | 触发刷新 | Api::startProviderAccountRefresh() |
代码位置:retail-api/app/Integrations/Yodlee/Api.php
Provider ID 处理方式:Integrator::saveProviderAccount() 从 API response 中动态读取 providerId 和 id(providerAccountId),没有任何硬编码的 BOA provider ID。
$provider_account_reference = $provider_account_array['id']; // providerAccountId$yodlee_provider_reference = $provider_account_array['providerId']; // providerId使用 firstOrNew() 模式创建/更新记录,新的 ID 会自动创建新记录。
结论:不需要工程改动。
2. FastLink Deep Link Flow — 不适用
Section titled “2. FastLink Deep Link Flow — 不适用”RightCapital 不使用 FastLink Deep Link Flow。Deep Link Flow 是指在初始化 FastLink 时传入 providerId 以跳过银行搜索,直接进入特定银行的登录页。
我们的 FastLink 配置接口:
export interface IFastLinkConfig { params?: Partial<{ userExperienceFlow: IUserExperienceFlow; providerAccountId?: number; // 仅用于 Edit/Refresh,不是 providerId flow?: IFastLinkFlow; }>;}三种使用模式:
| Mode | 用途 | 是否传 providerId |
|---|---|---|
| Add | 新增账户连接 | 否,用户在 FastLink 中搜索银行 |
| Edit | 更新凭证 | 否,传 providerAccountId(连接 ID,非机构 ID) |
| Refresh | 手动刷新 | 否,传 providerAccountId |
注意区分:providerAccountId(用户与银行之间的连接 ID)和 providerId(银行机构 ID)是不同概念。Deep Link Flow 需要传 providerId,我们没有使用。
前端还有一个 openFastLinkModal URL 参数:
const [{ openFastLinkModal: shouldOpenFastLinkModal = false }] = useSearch({ openFastLinkModal: 'boolean',});这是应用内部的 URL 快捷方式(如 /profile/net-worth?openFastLinkModal=true),用于自动打开 FastLink 弹窗,与 Yodlee 的 Deep Link Flow 无关。
结论:不需要工程改动。
3. 迁移对现有数据的影响
Section titled “3. 迁移对现有数据的影响”Yodlee 确认的 ID 变化
Section titled “Yodlee 确认的 ID 变化”Yodlee 已确认重新认证后各 ID 的变化情况:
| ID 类型 | 是否变化 | 说明 |
|---|---|---|
providerId(银行机构 ID) | 会变 | 旧 Provider ID → 新 Provider ID |
providerAccountId(用户连接 ID) | 不变 | 重新认证后保持原值 |
accountId(具体账户 ID) | 不变 | 重新认证后保持原值 |
数据模型映射
Section titled “数据模型映射”| Yodlee 概念 | 数据库表 | 主键字段 |
|---|---|---|
| Provider ID(银行机构) | yodlee_providers | reference |
| Provider Account ID(用户连接) | yodlee_provider_accounts | reference |
| Account ID(具体账户) | account_yodlees | yodlee_account_reference |
迁移后的数据流
Section titled “迁移后的数据流”由于 providerAccountId 和 accountId 不变,数据变化非常小:
迁移前: yodlee_providers(reference=旧ID, name="Bank of America") └── yodlee_provider_accounts(reference=PA_ID, yodlee_provider_reference=旧ID) └── account_yodlees(yodlee_account_reference=ACC_ID) → accounts
迁移后 + 用户重新认证: yodlee_providers(reference=新ID, name="Bank of America") ← 新记录(自动创建) └── yodlee_provider_accounts(reference=PA_ID, yodlee_provider_reference=新ID) ← 同一记录,外键更新 └── account_yodlees(yodlee_account_reference=ACC_ID) → accounts ← 完全不变
yodlee_providers(reference=旧ID) ← 孤儿记录(无害,仅占少量空间)关键结论:
- 不会产生重复账户 —
providerAccountId不变,yodlee_provider_accounts命中现有记录并更新外键 - 账户数据完整保留 —
accountId不变,account_yodlees和accounts记录完全不受影响 - 账户历史数据连续 — 余额历史等不中断
- Advisor 无需手动删除旧账户 — 不存在旧账户/新账户并存的情况
YodleeProviderAccountController@index 行为
Section titled “YodleeProviderAccountController@index 行为”index 方法完全以 Yodlee API 返回为准,不查本地数据库:
$provider_account_arrays = $yodlee_api->getProviderAccounts(); // 从 Yodlee API 拉取foreach ($provider_account_arrays as $provider_account) { // 只遍历 API 返回的 $yodlee_provider_account = Integrator::saveProviderAccount($provider_account); $provider_accounts->add($yodlee_provider_account);}return response()->json(YodleeProviderAccountResource::collection($provider_accounts));迁移后用户重新认证时:
- Yodlee API 返回相同的
providerAccountId,但providerId为新值 saveProviderAccount()通过firstOrNew()命中现有yodlee_provider_accounts记录yodlee_provider_reference外键更新为新的 Provider ID- 新的
yodlee_providers记录自动创建(如不存在) - 账户数据无缝衔接,前端无感知
Conclusion
Section titled “Conclusion”| 项目 | 结论 |
|---|---|
| Sync Data Extracts API | 不适用,无需改动 |
| FastLink Deep Link Flow | 不适用,无需改动 |
| 工程改动 | 零 |
| 用户影响 | BOA 连接需一次性重新认证 |
| Advisor 操作 | 无需额外操作(账户数据无缝衔接) |
| 数据连续性 | providerAccountId 和 accountId 不变,账户历史完整保留 |
| 待确认项 | 等待 Yodlee 提供新 Provider ID 和具体时间表 |
Action Items
Section titled “Action Items”- 回复 Megan:两个高亮关注点均不适用,不需要额外工程步骤
- Mary 继续推进:通知 advisor 告知客户需要一次性重新认证 BOA 连接(重新认证后账户自动恢复,无需删除旧账户)
- 后续跟进:Yodlee 分享新 Provider ID 和迁移时间表后,评估是否需要额外准备