Skip to content
LIQFYdocs
PTENENEN
Go to dashboard

官方 SDK

Liqfy 为 Node.js、Python、PHP 和 .NET 发布官方客户端。它们封装的是 API 参考 中描述的同一套 /v1 REST API —— 凡是能用 curl 完成的操作, 不用 SDK 也同样能完成。SDK 额外提供的,是那些容易在细节上出错的部分: 幂等性、重试策略以及 webhook 签名校验。

四个 SDK 共用同一个版本号:0.8.0。

语言包安装运行时
Node.js / TypeScript@liqfy/nodenpm i @liqfy/nodeNode 18+
Pythonliqfypip install liqfyPython 3.8+
PHPliqfy/sdk-phpcomposer require liqfy/sdk-phpPHP 8.1+
.NET / C#Liqfydotnet add package Liqfynetstandard2.0, net8.0

#每个 SDK 的保证

这四个客户端在行为上完全一致,而不仅仅是相似。尤其是 webhook 签名校验,在 CI 中针对同一组共享测试向量运行 —— 只要 Node 接受某个签名,Python、PHP 和 .NET 也会逐字节地接受同一个签名。

#资源族

每个客户端都暴露相同的六个资源族 —— 路由和传输格式均与 API 参考 一致:

资源族NodePythonPHP.NET
收款(/v1/charges)client.chargesclient.charges$client->chargesclient.Charges
支付操作(/v1/payments)client.paymentsclient.payments$client->paymentsclient.Payments
付款(/v1/withdrawals)client.payoutsclient.payouts$client->payoutsclient.Payouts
余额(/v1/wallets)client.balanceclient.balance$client->balanceclient.Balance
Webhooks(/v1/webhooks)client.webhooks(含 client.webhooks.endpoints)client.webhooks(含 client.webhooks.endpoints)$client->webhooks(含 $client->webhooks->endpoints)client.Webhooks(含 client.Webhooks.Endpoints)
MED 案例client.medCasesclient.med_cases$client->medCasesclient.MedCases

方法名遵循各语言的惯例(Node 中为 client.payments.create(input, { idempotencyKey }),Python 中为 client.payments.create(input, idempotency_key),PHP 中为 $client->payments->create($input, $idempotencyKey),.NET 中为 client.Payments.CreateAsync(input, idempotencyKey))。payments.refund 被有意省略:对于所有使用 API 密钥的请求,API 都会返回 403 —— error.code 为 "forbidden",且消息以 REFUND_ADMIN_ONLY 标记开头(这是消息前缀,而非错误码),因为退款只能通过管理后台发起。

#身份验证

text
Authorization: Bearer lq_live_…

SDK 发送规范的 Authorization: Bearer 请求头;出于兼容性考虑,API 仍接受旧版的 apikey: 请求头。环境(测试或生产)由密钥本身决定。你无需配置环境, 也永远不会传入或返回任何账户或商户标识符。

#资金类写操作必须提供幂等键

创建收款或付款需要提供幂等键。缺少幂等键时,SDK 会直接拒绝调用, 而不是发出请求后听天由命。

请根据你自己的订单(pedido-1234)生成该键,切勿使用随机值。随机值 会让整个机制失效:如果你的请求已经到达但响应丢失, 用新键重试会产生第二笔收款;而用同一个键重试则会返回原始结果。

#重试策略

情形是否重试?
GET / HEAD 遇到 5xx 或网络错误是
POST 带有幂等键是 —— 每次尝试使用同一个键
POST 未带幂等键绝不
任何 4xx绝不 —— 请求本身有误,重试无法解决

退避采用带完全抖动(full jitter)的指数退避,上限为 8 秒。

关键在于第三行。网络故障并不能告诉你服务器是否已处理该请求 —— 只能说明没有收到响应。在这种不确定的情况下重试不带幂等键的 资金类写操作,正是客户被重复扣款的原因。

#快速入门

#Node.js

js
import { LiqfyClient } from '@liqfy/node';

const liqfy = new LiqfyClient({ apiKey: process.env.LIQFY_API_KEY });

const charge = await liqfy.charges.create(
  {
    amount: 15000,                 // R$ 150.00 in centavos — always an integer
    currency: 'BRL',
    payment_method: 'pix',
    customer: { name: 'Maria Silva', document: '12345678901' },
  },
  { idempotencyKey: `pedido-${orderId}` },
);

charge.pix.br_code;                // Pix Copia e Cola

#Python

python
import os
from liqfy import LiqfyClient

liqfy = LiqfyClient(api_key=os.environ["LIQFY_API_KEY"])

cobranca = liqfy.charges.create(
    {
        "amount": 15000,
        "currency": "BRL",
        "payment_method": "pix",
        "customer": {"name": "Maria Silva", "document": "12345678901"},
    },
    idempotency_key=f"pedido-{pedido_id}",
)

cobranca["pix"]["br_code"]

Python SDK 没有任何运行时依赖 —— 仅使用标准库。支付 SDK 运行在你的进程中;它引入的每一个传递依赖包,都会成为你从我们这里继承的 供应链攻击面。

#PHP

php
<?php
require __DIR__ . '/vendor/autoload.php';

use Liqfy\LiqfyClient;

$cliente = new LiqfyClient(['apiKey' => getenv('LIQFY_API_KEY')]);

$cobranca = $cliente->charges->create([
    'amount' => 15000,
    'currency' => 'BRL',
    'payment_method' => 'pix',
    'customer' => ['name' => 'Maria Silva', 'document' => '12345678901'],
], 'pedido-' . $pedidoId);

$cobranca['pix']['br_code'];

#C#

csharp
using Liqfy;

// Register as a SINGLETON — it is thread-safe and reuses its HttpClient.
// One client per request exhausts TCP ports, the classic .NET trap.
var liqfy = new LiqfyClient(Environment.GetEnvironmentVariable("LIQFY_API_KEY")!);

var cobranca = await liqfy.Charges.CreateAsync(new
{
    amount = 15000,
    currency = "BRL",
    payment_method = "pix",
    customer = new { name = "Maria Silva", document = "12345678901" },
}, idempotencyKey: $"pedido-{orderId}");

var brCode = cobranca!.RootElement.GetProperty("pix").GetProperty("br_code").GetString();

#校验 webhook

校验不需要 API 密钥 —— 单独实例化 webhook 辅助工具即可。

js
// Node — Express with a raw body parser
app.post('/webhooks/liqfy', express.raw({ type: 'application/json' }), (req, res) => {
  if (!liqfy.webhooks.verify(req.body, req.headers['x-liqfy-signature'], secret)) {
    return res.status(401).end();
  }
  const event = JSON.parse(req.body.toString('utf8'));
  res.status(200).end();          // any 2xx confirms delivery
});
python
# Python — Flask
if not webhooks.verify(request.get_data(), request.headers.get("X-Liqfy-Signature"), secret):
    return "", 401
csharp
// C# — minimal API
if (!webhooks.Verify(corpo, req.Headers["X-Liqfy-Signature"], secret))
    return Results.Unauthorized();

请传入原始字节。 校验前不要对请求体进行反序列化再重新序列化: 空白字符或键顺序的任何差异都会改变 HMAC,导致签名校验失败。 这是所有语言中最常见的 webhook 集成错误。

默认情况下,超过 5 分钟的签名会被拒绝,从而防止被截获的 POST 请求被无限重放。签名格式和重试计划请参阅 Webhooks。

#错误

每个 SDK 都会抛出带有 status、code、type 和 request_id 的类型化错误。

失败类别NodePythonPHPC#
401 / 403LiqfyAuthErrorLiqfyAuthErrorLiqfyAuthErrorLiqfyAuthException
400 / 422LiqfyValidationErrorLiqfyValidationErrorLiqfyValidationErrorLiqfyValidationException
409LiqfyConflictErrorLiqfyConflictErrorLiqfyConflictErrorLiqfyConflictException
完全没有响应LiqfyNetworkErrorLiqfyNetworkErrorLiqfyNetworkErrorLiqfyNetworkException

请根据 code 进行分支判断,切勿依据消息内容 —— 消息是写给人看的,可能随时变更且不另行通知。code 属于契约的一部分;完整目录请参阅 错误。唯一有文档说明的消息标记是 REFUND_ADMIN_ONLY(退款仅限管理后台操作,并返回普通的 forbidden);请将其作为前缀匹配,而不是作为错误码。

在全部四个 SDK 中,网络错误都被有意设计为不是 API 错误的子类。 当没有收到响应时,你无法知道服务器是否已处理该请求。 在同一个分支中同时捕获两者,恰恰会掩盖决定重试是否安全的那个关键区别。

联系支持团队时请提供 request_id —— 它可以帮助我们在日志中精确定位该请求。