跳至正文

快速入门

一步步完成您的第一笔测试支付

完成入驻和初始设置后,在 Stage 环境中运行一笔测试支付。

  • Stage:不涉及真实资金
  • cURL 和 Node.js
  • 虚构测试数据

概览

三个阶段,六个步骤

以下所有操作都在 Stage 进行,这是与生产环境一致的沙盒。完成第 6 步中的检查后,才会开通生产环境访问。

  1. 01

    配置访问

    获取 Stage 凭证,存入密钥管理服务,并将服务器 IP 加入白名单。

    步骤 1–2

  2. 02

    发起首批调用

    获取令牌,创建一笔测试收款,并验证确认该收款的 Webhook。

    步骤 3–5

  3. 03

    正式上线

    完成安全评审和企业验证(KYB),然后切换到生产凭证。

    步骤 6

第 1 步,共 6 步

获取 Stage 凭证

Stage 凭证(用于 api.stage.localpayment.com 的 API 用户名和密码)在您与 Localpayment 的合作启动时发放。从第一天起,就按生产密钥的标准来管理它们。

  • 从密钥管理服务或环境变量加载凭证,切勿提交到代码仓库
  • Stage 与生产环境使用不同的凭证和 Base URL
  • 只使用虚构的测试数据,绝不使用真实客户数据
secrets.js
// 启动时从 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)转发出站流量
  • 上线前在生产环境重复同样的配置

第 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 响应的投递会按指数退避重试
webhook.js
// 用 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 凭证?

告诉我们您的业务场景和目标市场。我们的团队会协助您完成入驻,并在合作启动时开通 Stage 访问。

我们能为您做些什么?

下载完整版

留下您的信息,即可立即获取完整版。