快速入门
一步步完成您的第一笔测试支付
完成入驻和初始设置后,在 Stage 环境中运行一笔测试支付。
- Stage:不涉及真实资金
- cURL 和 Node.js
- 虚构测试数据
概览
三个阶段,六个步骤
以下所有操作都在 Stage 进行,这是与生产环境一致的沙盒。完成第 6 步中的检查后,才会开通生产环境访问。
- 01
配置访问
获取 Stage 凭证,存入密钥管理服务,并将服务器 IP 加入白名单。
步骤 1–2
- 02
发起首批调用
获取令牌,创建一笔测试收款,并验证确认该收款的 Webhook。
步骤 3–5
- 03
正式上线
完成安全评审和企业验证(KYB),然后切换到生产凭证。
步骤 6
第 1 步,共 6 步
获取 Stage 凭证
Stage 凭证(用于 api.stage.localpayment.com 的 API 用户名和密码)在您与 Localpayment 的合作启动时发放。从第一天起,就按生产密钥的标准来管理它们。
- 从密钥管理服务或环境变量加载凭证,切勿提交到代码仓库
- Stage 与生产环境使用不同的凭证和 Base URL
- 只使用虚构的测试数据,绝不使用真实客户数据
// 启动时从 AWS Secrets Manager 读取 Stage 凭证(AWS SDK v3)。
// 任何密钥库都可以,关键是密钥永远不写进源代码。
import { SecretsManagerClient, GetSecretValueCommand } from '@aws-sdk/client-secrets-manager';
const client = new SecretsManagerClient({ region: process.env.AWS_REGION });
export async function loadMerchantSecrets() {
const { SecretString } = await client.send(
new GetSecretValueCommand({ SecretId: 'localpayment/stage/api' }),
);
// 预期 JSON:{ "username": "…", "password": "…", "webhookSecret": "…" }
return JSON.parse(SecretString);
}第 2 步,共 6 步
将服务器 IP 加入白名单
API 只接受来自白名单 IP 的调用。在发出第一个请求之前,请在 Stage 的 Business Portal 中添加服务器的出站 IP。
- Business Portal → Whitelist your IP
- 来自其他 IP 的请求会被拒绝
- 使用 Serverless 或自动扩缩容?请通过固定出口 IP(NAT)转发出站流量
- 上线前在生产环境重复同样的配置
- PCI DSS v4.0.1
- SOC 2 Type II
- ISO 27001
- AML/KYC
- TLS 1.2+ · AES-256
第 3 步,共 6 步
获取访问令牌
用 API 用户名和密码换取一对 JWT。每次调用都以 Bearer 方式发送访问令牌,并在过期前刷新。
- 访问令牌:有效期 5 分钟
- 刷新令牌:有效期 24 小时,使用 POST /api/token/refresh/
- 令牌只保存在内存中,切勿写入日志
# 在 Stage 环境获取访问令牌(有效期 5 分钟)
curl -X POST https://api.stage.localpayment.com/api/token/ \
-H "Content-Type: application/json" \
-d "{\"username\": \"$LP_API_USER\", \"password\": \"$LP_API_PASSWORD\"}"第 4 步,共 6 步
创建一笔测试收款
本示例在巴西创建一笔 Pix 收款。响应会返回二维码和 Pix Copia e Cola 字符串,在付款人完成支付前状态为 100 INPROGRESS。
- 每笔交易都生成一个新的 UUID 作为 externalId
- 使用相同 externalId 重试会返回 409 Conflict,而不会创建第二笔收款
- 金额以美元计:响应会返回付款人实际支付的 BRL 金额及所用汇率
# 示例:在 Stage 创建 Pix 收款(巴西)。数值均为虚构,
# 完整字段请参阅 docs.localpayment.com。
curl -X POST https://api.stage.localpayment.com/api/payin/ \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"paymentMethod": { "type": "BankTransfer", "code": "1314", "flow": "DIRECT" },
"externalId": "7c1e2f7a-0000-4000-8000-000000000001",
"country": "BRA",
"currency": "USD",
"amount": 100,
"accountNumber": "<your-account-number>",
"conceptCode": "0003",
"merchant": { "type": "COMPANY", "name": "Nortia Commerce Ltda" },
"payer": {
"type": "INDIVIDUAL",
"name": "Maria",
"lastname": "Silva",
"document": { "type": "CPF", "id": "000.000.000-00" }
}
}'第 5 步,共 6 步
处理 Webhook
支付完成后,Localpayment 会向您的 HTTPS 端点发送签名通知。请基于原始请求体验证签名,立即返回 200,再异步处理业务。
- 在 Business Portal → Configurations → Clients → Notifications 中登记您的 URL
- 使用恒定时间比较,将 x-Signature 与您自己计算的 HMAC-SHA256 对比
- 未收到 200 响应的投递会按指数退避重试
// 用 Express 接收 Localpayment Webhook(Node.js 18+)。
import crypto from 'node:crypto';
import express from 'express';
import { jobQueue } from './queue.js'; // 您自己的异步任务队列
const app = express();
// 启动时从密钥管理服务读取 Webhook 密钥,切勿硬编码。
const WEBHOOK_SECRET = process.env.LP_WEBHOOK_SECRET;
if (!WEBHOOK_SECRET) throw new Error('LP_WEBHOOK_SECRET is not configured');
function hasValidSignature(rawBody, header) {
if (typeof rawBody !== 'string') return false;
// 请求头格式:"x-Signature: HMAC-SHA256 <hex>",先去掉前缀。
const received = String(header ?? '').replace(/^HMAC-SHA256\s+/i, '').trim();
if (!/^[0-9a-f]{64}$/i.test(received)) return false;
const expected = crypto.createHmac('sha256', WEBHOOK_SECRET).update(rawBody, 'utf8').digest();
return crypto.timingSafeEqual(Buffer.from(received, 'hex'), expected);
}
// 请求体是以 Content-Type text/plain 发送的 JSON:计算 HMAC 时请使用原始文本。
app.post('/webhooks/localpayment', express.text({ type: '*/*', limit: '1mb' }), (req, res) => {
if (!hasValidSignature(req.body, req.get('x-signature'))) return res.sendStatus(401);
let event;
try {
event = JSON.parse(req.body);
} catch {
return res.sendStatus(400);
}
res.sendStatus(200); // 先快速确认,再做耗时处理
// 异步处理。按 internalId/externalId + 状态去重,
// 确保重试投递只生效一次。切勿记录完整载荷。
jobQueue.enqueue(event);
});第 6 步,共 6 步
上线检查清单
只有完成以下检查后才会发放生产凭证。请尽早规划:这些检查有助于保护平台上的每一个商户,也包括您。
完成 Stage 测试
覆盖您将上线的每种支付方式和每个国家的成功、拒绝、待处理和错误路径。
通过安全评审
在开通生产访问前,我们的团队会评审并认证您的集成。
完成企业验证
合规团队会在入驻过程中核验您的公司、股权结构和业务场景(KYB)。
妥善保管生产凭证
存放在密钥管理服务中,与 Stage 分开,并仅授权给需要的服务访问。
添加生产 IP 白名单
在生产环境的 Business Portal 中添加生产服务器的出站 IP。
配置生产 Webhook
登记生产环境的 HTTPS 端点,并在第一笔真实交易前确认签名验证正常。
故障排查
首次调用的常见问题
收到 401 Unauthorized,应该检查什么?
访问令牌 5 分钟后过期。请通过 POST /api/token/refresh/ 刷新或重新申请令牌,并确认请求头为 Authorization: Bearer 加访问令牌。
令牌有效,请求却被拒绝。
请检查发起调用的服务器出站 IP 是否已在该环境的 Business Portal 中加入白名单。Stage 与生产环境需分别配置。
为什么收到 409 Conflict?
该 externalId 已被使用。请通过 GET /api/transactions/{externalId}/status 查询已有交易,不要再新建。
收款一直停留在 100 INPROGRESS。
对于 Pix、银行转账和虚拟账户等异步支付方式,这是正常的:付款人完成支付后状态才会变化,最终状态通过 Webhook 送达。
Webhook 签名对不上。
请基于收到的原始请求体计算 HMAC(在解析 JSON 之前),并在比较前去掉请求头中的 "HMAC-SHA256 " 前缀。

Stage:不涉及真实资金