关于 plaid
面向开发者的 Plaid Banking API 实施参考,涵盖账户连接、金融数据读取、支付及身份验证相关产品。还提供 Link 流程、Webhook、环境配置和安全处理说明。
主要功能
- 01Plaid Link 账户连接流程
- 02读取交易、余额与账户信息
- 03Auth、Identity、Investments 和 Liabilities 产品
- 04ACH 转账与 Webhook 处理
- 05沙盒、开发和生产环境说明
- 06令牌安全与重新认证建议
适用场景
- 01在金融科技应用中连接银行账户
- 02获取交易记录和实时余额
- 03实现 ACH 账户信息读取
- 04处理交易更新和账户连接错误
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ raintree-technology/ claude-starter --skill plaid安装后在 Claude Code 中输入/plaid确认已加载。
详细介绍
Plaid 银行 API 专家
Plaid 将应用连接到用户的银行账户,以便访问金融数据、进行支付和验证身份。
使用场景
- 在金融科技应用中连接银行账户
- 实现 Plaid Link 流程
- 获取交易记录、余额或账户信息
- 设置 ACH 转账
- 验证身份/收入
- 处理 Plaid Webhook
核心产品
| 产品 | 用途 |
|---|---|
| Auth | 获取用于 ACH 的银行账号/路由号码 |
| Transactions | 交易历史记录(最多 24 个月) |
| Identity | 通过银行账户所有权验证用户身份 |
| Balance | 实时账户余额 |
| Investments | 投资账户中的持仓 |
| Liabilities | 贷款和信用卡数据 |
快速开始
1. 安装 SDK
npm install plaid react-plaid-link
2. 创建 Plaid 客户端
import { Configuration, PlaidApi, PlaidEnvironments } from "plaid";
const client = new PlaidApi(
new Configuration({
basePath: PlaidEnvironments.sandbox,
baseOptions: {
headers: {
"PLAID-CLIENT-ID": process.env.PLAID_CLIENT_ID,
"PLAID-SECRET": process.env.PLAID_SECRET,
},
},
})
);
3. 创建 Link Token(服务端)
// POST /api/plaid/create-link-token
export async function POST(req: Request) {
const response = await client.linkTokenCreate({
user: { client_user_id: userId },
client_name: "Your App",
products: ["auth", "transactions"],
country_codes: ["US"],
language: "en",
});
return Response.json({ link_token: response.data.link_token });
}
4. Plaid Link(客户端)
import { usePlaidLink } from "react-plaid-link";
function ConnectBank({ linkToken }) {
const { open, ready } = usePlaidLink({
token: linkToken,
onSuccess: async (public_token, metadata) => {
// Exchange for access_token on server
await fetch("/api/plaid/exchange-token", {
method: "POST",
body: JSON.stringify({ public_token }),
});
},
});
return (
<button onClick={() => open()} disabled={!ready}>
Connect Bank Account
</button>
);
}
5. 交换 Token(服务端)
// POST /api/plaid/exchange-token
export async function POST(req: Request) {
const { public_token } = await req.json();
const response = await client.itemPublicTokenExchange({
public_token,
});
// Store access_token securely (encrypted in database)
await db.users.update(userId, {
plaid_access_token: response.data.access_token,
plaid_item_id: response.data.item_id,
});
return Response.json({ success: true });
}
获取数据
获取 Auth(账号/路由号码)
const response = await client.authGet({ access_token });
const ach = response.data.numbers.ach[0];
console.log("Account:", ach.account);
console.log("Routing:", ach.routing);
获取交易记录
const response = await client.transactionsGet({
access_token,
start_date: "2024-01-01",
end_date: "2024-12-31",
});
let transactions = response.data.transactions;
// Handle pagination
while (transactions.length < response.data.total_transactions) {
const more = await client.transactionsGet({
access_token,
start_date: "2024-01-01",
end_date: "2024-12-31",
offset: transactions.length,
});
transactions = transactions.concat(more.data.transactions);
}
交易对象:
{
transaction_id: "abc123",
amount: 12.34, // Positive = outflow
date: "2024-11-16",
name: "Starbucks",
merchant_name: "Starbucks",
category: ["Food and Drink", "Coffee Shop"],
pending: false,
}
获取余额
const response = await client.accountsBalanceGet({ access_token });
response.data.accounts.forEach((account) => {
console.log(`${account.name}: $${account.balances.current}`);
});
获取身份信息
const response = await client.identityGet({ access_token });
const owner = response.data.accounts[0].owners[0];
console.log("Name:", owner.names[0]);
console.log("Email:", owner.emails[0].data);
console.log("Phone:", owner.phone_numbers[0].data);
Webhook
设置端点
// POST /api/plaid/webhook
export async function POST(req: Request) {
const { webhook_type, webhook_code, item_id } = await req.json();
switch (webhook_type) {
case "TRANSACTIONS":
if (webhook_code === "DEFAULT_UPDATE") {
// New transactions available - fetch them
await syncTransactions(item_id);
}
break;
case "ITEM":
if (webhook_code === "ERROR") {
// Connection issue - prompt user to re-authenticate
await notifyUserReauth(item_id);
}
break;
}
return Response.json({ received: true });
}
主要 Webhook 事件:
| 事件 | 含义 |
|---|---|
TRANSACTIONS: INITIAL_UPDATE | 第一批数据已就绪 |
TRANSACTIONS: DEFAULT_UPDATE | 有新交易记录 |
ITEM: ERROR | 连接问题 |
ITEM: PENDING_EXPIRATION | 凭据即将过期 |
环境
| 环境 | 使用场景 | 基础路径 |
|---|---|---|
| Sandbox | 测试 | PlaidEnvironments.sandbox |
| Development | 有限的线上使用(100 个连接) | PlaidEnvironments.development |
| Production | 线上使用 | PlaidEnvironments.production |
Sandbox 测试凭据
- 用户名:
user_good - 密码:
pass_good - MFA:
1234
错误处理
重新认证(更新模式)
凭据过期时:
// Create link token for update mode
const response = await client.linkTokenCreate({
user: { client_user_id: userId },
client_name: "Your App",
access_token: existingAccessToken, // Triggers update mode
country_codes: ["US"],
language: "en",
});
常见错误
| 错误 | 解决方案 |
|---|---|
ITEM_LOGIN_REQUIRED | 通过 Link 更新模式重新认证 |
RATE_LIMIT_EXCEEDED | 实现指数退避 |
PRODUCT_NOT_READY | 等待 Webhook 或重试 |
安全最佳实践
应该:
- 在数据库中加密存储访问 Token
- 使用环境变量保存凭据
- 验证 Webhook 签名
- 为所有端点使用 HTTPS
不应该:
- 在客户端暴露密钥
- 记录访问 Token
- 将凭据存储在代码中
Next.js App Router 示例
// app/api/plaid/create-link-token/route.ts
import { NextResponse } from "next/server";
import { Configuration, PlaidApi, PlaidEnvironments } from "plaid";
const client = new PlaidApi(
new Configuration({
basePath: PlaidEnvironments.sandbox,
baseOptions: {
headers: {
"PLAID-CLIENT-ID": process.env.PLAID_CLIENT_ID!,
"PLAID-SECRET": process.env.PLAID_SECRET!,
},
},
})
);
export async function POST(req: Request) {
const session = await getSession();
const response = await client.linkTokenCreate({
user: { client_user_id: session.user.id },
client_name: "Your App",
products: ["auth", "transactions"],
country_codes: ["US"],
language: "en",
webhook: `${process.env.NEXT_PUBLIC_URL}/api/plaid/webhook`,
});
return NextResponse.json({ link_token: response.data.link_token });
}
实现清单
- 注册 Plaid 账户
- 获取客户端 ID 和密钥
- 安装
plaid和react-plaid-link - 设置环境变量
- 创建 Link Token 端点
- 实现 Token 交换端点
- 在前端集成 Plaid Link
- 安全存储访问 Token
- 设置 Webhook 端点
- 处理重新认证错误
- 使用 Sandbox 凭据进行测试
资源
评论
支持 Markdown