如何为 Pinnacle Cart 添加自定义 payment gateway?
结论
Pinnacle Cart 通常无法通过后台表单添加默认列表以外的 payment gateway。接入自定义网关需要开发与当前 Pinnacle Cart 版本兼容的支付模块。如果当前部署版本未开放支付模块接口或结账流程源码,就需要联系 Pinnacle Cart 官方支持,确认是否能提供开发接口、定制集成服务,或将新网关加入支持列表。
不要直接修改现有网关文件来”套用”新接口。这些改动可能在升级后被覆盖,还可能导致重复扣款、订单状态错误或敏感信息泄露。
建议的处理步骤
1. 先确认部署方式和扩展能力
向 Pinnacle Cart 支持团队确认以下事项:
- 当前版本是否允许安装第三方 payment module。
- 是否提供 payment gateway SDK、模块模板或开发者接口。
- 自定义模块应放在哪个目录,如何注册和启用。
- 支持哪些支付方式:redirect、hosted checkout、iframe 或 server-to-server API。
- 可以使用哪些订单创建、状态更新、退款和 webhook 接口。
- 系统升级是否会覆盖自定义文件。
- 托管版账户是否允许修改结账流程。
如果官方没有提供公开的模块规范,不要直接参照其他版本的目录结构或社区示例开发。不同 Pinnacle Cart 版本和部署方式可能具有不同的扩展能力。
2. 选择合适的集成方式
优先考虑网关提供的托管支付页或 redirect 模式:
- 商城创建待付款订单。
- 后端向网关创建支付请求。
- 将顾客重定向到网关的支付页面。
- 网关通过 webhook 通知支付结果。
- 商城后端验证通知并更新订单状态。
- 顾客返回商城结果页。
采用这种方式,商城通常不需要直接处理银行卡号,PCI DSS 的合规范围也相对较小。只有 Pinnacle Cart 和支付服务商均明确支持时,才应考虑由商城直接收集卡片信息。
3. 实现网关适配层
具体类名和方法必须以当前 Pinnacle Cart 版本提供的接口为准。以下代码仅用于说明结构,不能直接作为 Pinnacle Cart 的真实 API 使用:
<?php
final class CustomGateway
{
public function __construct(
private string $apiKey,
private string $webhookSecret,
private bool $sandbox
) {
}
public function createPayment(array $order): array
{
$payload = [
'merchant_reference' => (string) $order['id'],
'amount' => $this->toMinorUnits($order['total']),
'currency' => strtoupper($order['currency']),
'return_url' => $order['return_url'],
'cancel_url' => $order['cancel_url'],
'webhook_url' => $order['webhook_url'],
];
// 使用支付服务商的官方 SDK 或后端 HTTP 客户端发送请求。
// API key 只能保存在服务器端,不能输出到浏览器。
$response = $this->sendRequest('/payments', $payload);
return [
'gateway_payment_id' => $response['id'],
'redirect_url' => $response['checkout_url'],
];
}
public function verifyWebhook(
string $rawBody,
string $signature
): bool {
$expected = hash_hmac('sha256', $rawBody, $this->webhookSecret);
return hash_equals($expected, $signature);
}
private function toMinorUnits(string $amount): int
{
return (int) bcmul($amount, '100', 0);
}
private function sendRequest(string $path, array $payload): array
{
throw new RuntimeException(
'Implement this method with the gateway official SDK.'
);
}
}
后台配置通常至少包含:
- Merchant ID 或 Account ID
- API key
- Webhook secret
- Sandbox/Production 模式
- 支持的币种
- 超时时间
- 支付成功、失败和取消状态的映射
实际配置项名称应以支付服务商和 Pinnacle Cart 的模块规范为准。
正确处理 webhook
不能只根据浏览器返回页面判断付款成功。用户可能关闭页面或伪造请求,网络也可能在付款完成后中断。订单状态应以通过签名验证的 webhook 或服务端查询结果为准。
处理流程示例如下:
<?php
$rawBody = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_GATEWAY_SIGNATURE'] ?? '';
if (!$gateway->verifyWebhook($rawBody, $signature)) {
http_response_code(401);
exit('Invalid signature');
}
$event = json_decode($rawBody, true, 512, JSON_THROW_ON_ERROR);
if ($event['type'] === 'payment.succeeded') {
$orderId = $event['data']['merchant_reference'];
// 再次核对金额、币种、商户号和 gateway payment ID。
// 仅当订单尚未支付时执行状态变更,保证幂等性。
markOrderAsPaid($orderId, $event['data']['id']);
}
http_response_code(200);
echo 'OK';
X-Gateway-Signature、事件名称和字段结构均为占位示例,必须替换为目标网关文档中规定的真实值。
必须验证的场景
上线前至少应测试:
- 支付成功、失败、取消和超时
- webhook 重复发送及乱序到达
- 用户付款后没有返回商城
- 金额或币种与订单不一致
- 同一订单被重复提交
- 已付款订单再次收到成功通知
- 全额退款和部分退款
- API 超时后的状态查询
- 测试环境与生产环境凭证隔离
- 日志脱敏,确保不记录 API secret、完整卡号或 CVV
计算金额时不要使用普通浮点数。应按照网关要求使用最小货币单位,或采用 BCMath 等十进制定点方式,以免产生舍入误差。
如果没有开放的模块接口
如果 Pinnacle Cart 支持团队确认当前方案不允许安装自定义 payment gateway,可以选择:
- 申请官方定制集成。
- 请求官方将该网关加入支持列表。
- 使用网关提供的 hosted payment page,并通过 Pinnacle Cart 允许的外部支付方式连接。
- 增加独立的支付中间层,由其处理签名、webhook、退款和状态同步。
- 改用 Pinnacle Cart 已支持且符合业务需求的支付服务商。
在没有官方扩展点的情况下,直接修改核心结账代码风险很高。除了改动可能被升级覆盖,还可能影响订单、税费、库存、优惠券和退款流程。开发前,最好先取得当前版本的模块接口说明,并要求官方书面确认自定义代码的支持范围。
备注:内容仅供参考。
