如何获取 Easy Pay2 API 并集成 payment gateway?
结论
仅凭“Easy Pay2”这个名称,无法确认具体的支付服务商、API 地址或接口参数,也无法编写可用于生产环境的集成代码。接入支付网关前,商户需要向 Easy Pay2 的运营方、收单机构或代理商申请账号,并取得官方技术文档、测试环境凭证和签名规则,不能靠猜测接口完成接入。
如果找不到公开资料,先确认产品的完整名称、官方网站和合同主体。“Easy Pay2”可能是内部产品名、地区性支付服务、旧版系统,也可能是其他品牌的非正式写法。在服务商身份得到确认前,不要向未知地址发送订单、银行卡或用户资料。
接入前需要向服务商索取什么
联系 Easy Pay2 的商务或技术支持时,至少需要索取:
- 商户后台地址和技术支持联系方式
- API 文档或 Hosted Payment Page 接入文档
- Sandbox 测试环境及测试账号
merchant_id、API Key、Client Secret 或证书- 创建支付、查询订单和退款接口
- 支付完成后的浏览器返回规则
- Webhook/Callback 异步通知规则
- 请求签名与回调验签算法
- 金额单位、币种格式和订单号限制
- IP 白名单及 TLS 版本要求
- 错误码、重试机制和接口限流规则
- 上线审核流程及生产环境地址
- PCI DSS、隐私保护和数据存储要求
可以直接向服务商询问:
请提供 Easy Pay2 支付网关的官方 API 文档、Sandbox 环境、商户凭证申请流程、签名与验签规范,以及支付、查询、退款和 Webhook 接口说明。另请确认产品的正式名称、官方网站和生产环境域名。
如果对方只能提供后台账号,却拿不出任何接口文档,需要继续确认该产品是否支持网站 API 集成。有些支付产品只提供付款链接、二维码、POS 或人工对账,不开放 API。
推荐的集成流程
1. 确认支付模式
支付网关通常有两种接入方式:
- 托管收银台:网站创建支付订单后,把用户重定向到服务商的支付页面。这种方式接入成本较低,也能减少网站直接接触敏感支付数据的风险。
- 服务端 API:网站后端直接调用网关接口,前端通过网关提供的组件完成支付。这种方式有更多控制能力,但安全和合规要求通常也更高。
除非 Easy Pay2 明确提供并授权直连支付 API,否则应优先使用托管收银台。不要自行采集或保存银行卡号、CVV、支付密码等敏感信息。
2. 在服务端创建本地订单
用户点击支付按钮后,应先在自己的数据库中创建订单,并保存以下信息:
- 本地订单号
- 应付金额和币种
- 初始状态,例如
PENDING - 用户标识
- 创建时间
- 支付网关返回的交易号
金额应以最小货币单位的整数保存。例如,人民币 10.99 元可保存为 1099 分,避免浮点数精度问题。
3. 由后端调用支付网关
下面是一个通用的 Node.js 结构示例。代码中的字段名称、API 地址和签名方式都是占位设计,必须按照 Easy Pay2 官方文档替换,不能直接用于生产环境。
import crypto from "node:crypto";
function signPayload(payload, secret) {
const canonical = Object.keys(payload)
.sort()
.map((key) => `${key}=${payload[key]}`)
.join("&");
return crypto
.createHmac("sha256", secret)
.update(canonical, "utf8")
.digest("hex");
}
export async function createPayment(order) {
const payload = {
merchant_id: process.env.EASYPAY2_MERCHANT_ID,
order_id: order.id,
amount: order.amountMinor,
currency: order.currency,
return_url: "https://example.com/payment/return",
notify_url: "https://example.com/webhooks/easypay2",
timestamp: Math.floor(Date.now() / 1000)
};
const signature = signPayload(
payload,
process.env.EASYPAY2_API_SECRET
);
const response = await fetch(
process.env.EASYPAY2_CREATE_PAYMENT_URL,
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${process.env.EASYPAY2_API_KEY}`,
"X-Signature": signature
},
body: JSON.stringify(payload),
signal: AbortSignal.timeout(10000)
}
);
if (!response.ok) {
throw new Error(`Payment API returned HTTP ${response.status}`);
}
return response.json();
}
示例使用 HMAC-SHA256 展示一种常见的签名结构。Easy Pay2 实际采用的可能是 RSA、证书、OAuth 2.0、字段拼接签名或其他认证方式,必须严格遵循官方规范。以下内容尤其不能自行假定:
- 参数名称和大小写
- JSON 或表单编码方式
- 金额是元还是分
- 时间戳单位
- 字段排序规则
- 签名字符集
- 签名结果是 Hex 还是 Base64
- 密钥放在 Header 还是请求体中
4. 将用户引导至支付页面
如果创建支付接口返回托管收银台地址,后端应先验证返回结果,再把地址交给前端跳转。
const result = await createPayment(order);
if (!result.payment_url) {
throw new Error("Payment gateway did not return payment_url");
}
// 将 payment_url 返回给前端,由前端执行跳转
不要直接信任未经验证的跳转地址。可以根据官方生产域名设置允许列表,降低开放重定向和钓鱼风险。
5. 处理异步支付通知
浏览器回跳只能用来展示结果,不能作为订单支付成功的最终依据。用户可能在回跳前关闭页面,回跳参数也可能被伪造。订单状态应以通过验签的 Webhook 为准,必要时再调用订单查询接口复核。
下面的代码仍然只是通用结构。Header、原始请求体的处理方式和验签算法,都必须以官方文档为准。
import crypto from "node:crypto";
import express from "express";
const app = express();
app.post(
"/webhooks/easypay2",
express.raw({ type: "application/json" }),
async (req, res) => {
const receivedSignature = req.get("X-Signature") ?? "";
const expectedSignature = crypto
.createHmac("sha256", process.env.EASYPAY2_WEBHOOK_SECRET)
.update(req.body)
.digest("hex");
const received = Buffer.from(receivedSignature, "utf8");
const expected = Buffer.from(expectedSignature, "utf8");
if (
received.length !== expected.length ||
!crypto.timingSafeEqual(received, expected)
) {
return res.status(401).send("invalid signature");
}
const event = JSON.parse(req.body.toString("utf8"));
// 同一事件可能重复发送,必须按 event_id 或交易号做幂等处理。
// 更新订单前还要核对订单号、金额、币种和商户号。
await processPaymentEvent(event);
return res.status(200).send("ok");
}
);
有些框架会默认先解析 JSON,这可能改变用于验签的请求体。如果官方签名以原始请求字节为准,就必须保留 raw body,否则即使密钥正确,验签也可能失败。
6. 查询并确认订单状态
Webhook 超时、订单状态不明确或用户主动返回网站时,可以调用订单查询接口。在确认支付成功前,至少需要核对:
merchant_id
order_id
gateway_transaction_id
amount
currency
payment_status
只有支付状态明确为成功,且商户号、订单号、金额和币种全部匹配,才能把本地订单更新为已支付。
订单处理必须保证幂等
支付通知可能因网络超时而重复发送。同一个支付事件无论到达多少次,都只能触发一次发货、充值或权益开通。
常见的处理方式如下:
- 使用本地订单号或网关事件编号建立唯一约束。
- 在数据库事务中锁定订单。
- 检查订单当前状态是否已经是
PAID。 - 核对金额、币种和交易号。
- 更新订单状态并记录事件。
- 等事务提交后再触发发货流程。
不要使用内存变量去重。应用重启或采用多实例部署后,内存中的去重状态会失效。
安全与上线注意事项
- API Secret、私钥和证书只能保存在服务端,不能写入 JavaScript 前端代码,也不能提交到代码仓库。
- 所有支付接口和 Webhook 都必须使用 HTTPS。
- 日志中不要记录完整密钥、银行卡数据、身份证件或完整支付请求。
- Webhook 除了验签,还要核对订单金额、币种和商户号。
- 支付失败后不要无限重试创建订单,以免产生重复交易。
- 外部请求需要设置连接超时、读取超时,并限制退避重试次数。
- 如果请求已经发出,但响应超时,应先查询原订单,不能立即创建新订单。
- 测试环境和生产环境的地址、密钥及数据库记录必须严格隔离。
- 上线前需要覆盖支付成功、失败、取消、超时、重复通知、退款和金额不一致等场景。
- 如果接入方式会直接处理银行卡数据,应先确认 PCI DSS 等适用的合规要求,不能仅凭技术接口上线。
找不到官方资料时怎么办
如果 Easy Pay2 的销售方、合同方或技术支持无法提供可验证的官方文档,就不具备安全接入所需的基本条件。此时应暂停开发,不要采用第三方博客提供的未知接口地址或所谓“通用密钥”。
可以通过以下信息继续确认服务商身份:
- 签约合同中的公司全称
- 商户后台的正式域名
- 收款页面显示的品牌和法律主体
- 开户邮件中的技术支持地址
- 现有插件或 SDK 的发布者、包名和代码仓库
- 银行或收单机构提供的产品编号
拿到文档后,重点确认创建支付请求、签名、异步通知和订单查询四部分。只要提供官方文档中的接口定义和脱敏示例,就能据此编写准确的适配代码。在此之前,任何声称可以直接使用的 Easy Pay2 API 地址或参数,都可能是虚构内容,并带来资金安全风险。
备注:内容仅供参考。
