PAYATHON 2026

如何在 WordPress 和 ASP.NET 网站集成印度支付方式?

支付阿杰

结论

WordPress 和 ASP.NET 都能接入印度信用卡、借记卡和 NetBanking。比较省事且安全的做法,是选择一家印度支付聚合服务商,通过托管结账页或官方 SDK 完成支付,无需分别对接银行和卡组织。

需要特别注意的是,不能默认某个 WordPress 插件同时支持 Credit Card、Debit Card、NetBanking 和 Airtel Money。前三项是印度支付网关常见的支付方式,Airtel Money 是否可用,则可能受服务商、商户类型、账户地区和当前合作政策影响。签约前应要求支付服务商书面确认,最终以商户后台实际开通的渠道为准。

选择支付服务商

可以咨询在印度提供商户收款服务的支付网关,如 Razorpay、Cashfree Payments、PayU 或 Paytm Payment Gateway。选择时需要确认:

  • 是否支持印度发行的 Credit Card 和 Debit Card;
  • 是否覆盖所需银行的 NetBanking;
  • Airtel Money 是以钱包、Airtel Payments Bank,还是其他支付渠道的形式提供;
  • 是否有适用于 WooCommerce 的官方插件;
  • 是否提供 ASP.NET SDK 或通用 REST API;
  • 是否支持 Webhook、退款、订单查询和支付签名验证;
  • 结算周期、手续费、最低交易额和退款费用;
  • 开户是否需要印度公司、印度银行账户、PAN、GSTIN 等材料;
  • 是否支持你的业务类别、交易币种和目标客户所在地区。

不要只看插件页面上展示的支付方式图标。即使某种支付方式出现在结账界面,也不代表商户账户已经获批使用。

WordPress 集成方案

如果网站使用 WooCommerce,建议优先选择支付服务商提供或明确认可的 WooCommerce 插件。

通常需要完成以下步骤:

  1. 注册支付服务商的商户账户并完成 KYC。
  2. 在商户后台申请需要使用的支付渠道。
  3. 获取测试环境凭据,如 Key ID、Key Secret 或 Client ID。
  4. 在 WordPress 后台安装对应的 WooCommerce 支付插件。
  5. 进入 WooCommerce → 设置 → 付款,启用该网关。
  6. 填写测试凭据并配置 Webhook URL。
  7. 分别测试支付成功、失败、取消、超时和退款。
  8. 确认测试结果无误后,再切换到生产凭据。

如果网站没有使用 WooCommerce,可以通过服务商的 WordPress 插件、支付链接或自定义插件接入。不要直接修改主题的 functions.php 来保存支付密钥,否则容易引发升级冲突,也会增加密钥泄露的风险。

WordPress 自定义 Webhook 示例

下面的代码只演示 WordPress 接收 Webhook 的基本结构。事件名称、签名算法和请求头必须按照所选支付服务商的官方文档实现。

<?php

add_action('rest_api_init', function () {
    register_rest_route('payments/v1', '/webhook', [
        'methods'             => 'POST',
        'callback'            => 'handle_payment_webhook',
        'permission_callback' => '__return_true',
    ]);
});

function handle_payment_webhook(WP_REST_Request $request)
{
    $rawBody   = $request->get_body();
    $signature = $request->get_header('x-payment-signature');

    if (!verify_gateway_signature($rawBody, $signature)) {
        return new WP_REST_Response(
            ['error' => 'Invalid signature'],
            401
        );
    }

    $event = json_decode($rawBody, true);

    if (!is_array($event)) {
        return new WP_REST_Response(
            ['error' => 'Invalid payload'],
            400
        );
    }

    // 根据支付服务商的事件结构读取订单号和支付状态。
    // 更新 WooCommerce 订单前,还应查询并核对金额、币种和商户订单号。

    return new WP_REST_Response(['received' => true], 200);
}

function verify_gateway_signature(string $payload, string $signature): bool
{
    $secret = PAYMENT_WEBHOOK_SECRET;

    // 这里只是常见的 HMAC-SHA256 示例。
    // 实际算法、编码格式和请求头名称必须以支付服务商文档为准。
    $expected = hash_hmac('sha256', $payload, $secret);

    return hash_equals($expected, $signature);
}

生产环境中的密钥应存放在服务器环境变量、WordPress 配置或专用密钥管理系统中,不要写入可公开访问的插件文件。

ASP.NET 集成方案

ASP.NET 网站一般通过支付服务商的 .NET SDK 或 REST API 接入。推荐的模式是由服务器创建订单,浏览器打开托管结账页,再由服务器验证支付结果。

典型流程如下:

  1. ASP.NET 服务端根据本地订单创建支付订单;
  2. 服务端将支付订单编号和公开凭据返回给浏览器;
  3. 浏览器打开服务商的托管结账页;
  4. 用户选择卡、NetBanking 或已经开通的钱包;
  5. 支付完成后,浏览器将支付结果提交给服务端;
  6. 服务端验证签名;
  7. 服务端通过订单查询接口或 Webhook 确认最终状态;
  8. 核对金额、币种和订单号一致后,更新本地订单。

ASP.NET Core 创建支付订单的结构示例

以下代码展示了一种推荐的分层方式。IPaymentGateway 并非某家服务商提供的官方接口,需要根据实际使用的 SDK 或 REST API 实现。

public sealed record CreatePaymentRequest(
    string OrderId,
    long AmountInPaise,
    string Currency
);

public sealed record PaymentOrderResult(
    string GatewayOrderId,
    string PublicKey,
    long AmountInPaise,
    string Currency
);

public interface IPaymentGateway
{
    Task<PaymentOrderResult> CreateOrderAsync(
        CreatePaymentRequest request,
        CancellationToken cancellationToken
    );

    bool VerifySignature(
        string gatewayOrderId,
        string paymentId,
        string signature
    );
}
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/payments")]
public sealed class PaymentsController : ControllerBase
{
    private readonly IPaymentGateway _paymentGateway;

    public PaymentsController(IPaymentGateway paymentGateway)
    {
        _paymentGateway = paymentGateway;
    }

    [HttpPost("orders")]
    public async Task<ActionResult<PaymentOrderResult>> CreateOrder(
        [FromBody] CreatePaymentRequest request,
        CancellationToken cancellationToken)
    {
        if (request.AmountInPaise <= 0)
        {
            return BadRequest("Amount must be greater than zero.");
        }

        if (!string.Equals(request.Currency, "INR",
                StringComparison.OrdinalIgnoreCase))
        {
            return BadRequest("Unsupported currency.");
        }

        // 生产环境应从数据库读取订单金额,
        // 不应直接信任浏览器提交的 AmountInPaise。
        var result = await _paymentGateway.CreateOrderAsync(
            request,
            cancellationToken
        );

        return Ok(result);
    }
}

印度支付 API 经常使用最小货币单位表示金额。例如,₹499.00 通常会表示为 49900 paise,具体仍应以所选服务商的 API 说明为准。

ASP.NET Core 支付结果验证示例

public sealed record VerifyPaymentRequest(
    string GatewayOrderId,
    string PaymentId,
    string Signature
);

[HttpPost("verify")]
public IActionResult VerifyPayment(
    [FromBody] VerifyPaymentRequest request)
{
    var valid = _paymentGateway.VerifySignature(
        request.GatewayOrderId,
        request.PaymentId,
        request.Signature
    );

    if (!valid)
    {
        return Unauthorized(new
        {
            verified = false,
            message = "Invalid payment signature."
        });
    }

    // 验签成功不一定等于资金已经最终结算。
    // 还应核对本地订单、金额、币种,并结合查询接口或 Webhook 确认状态。

    return Ok(new { verified = true });
}

密钥应通过配置系统读取:

{
  "PaymentGateway": {
    "PublicKey": "set-through-environment-variables",
    "SecretKey": "set-through-environment-variables",
    "WebhookSecret": "set-through-environment-variables"
  }
}

不要将生产密钥直接提交到 appsettings.json、Git 仓库或前端 JavaScript。只有服务商明确标记为公开的 Key 才能发送给浏览器。

Airtel Money 需要单独确认

Airtel Money 是这项需求中最容易引起误解的部分。不同支付服务商可能会:

  • 将其归类为 Wallet;
  • 只支持 Airtel Payments Bank 的部分支付流程;
  • 仅向符合条件的商户开放;
  • 调整或停止某种旧版钱包接口;
  • 在 API 中保留渠道名称,但当前商户账户无法启用。

购买插件或开始开发前,应向服务商确认:

我的印度商户账户能否在生产环境接受 Airtel Money 付款?它在 API 和结账页中的准确渠道名称是什么?WooCommerce 插件和 REST API 是否都支持该渠道?

如果没有服务商能同时提供所有渠道,可以使用一个主支付网关处理卡和 NetBanking,再为 Airtel 相关支付增加第二个网关。但这种方案会增加对账、退款、Webhook 和订单状态管理的复杂度。

测试与上线注意事项

上线前至少要测试以下场景:

  • Credit Card 和 Debit Card 支付成功及失败;
  • 3-D Secure、OTP 或其他身份验证流程;
  • NetBanking 用户中途取消;
  • 支付成功,但浏览器没有返回网站;
  • Webhook 重复发送或乱序到达;
  • 金额、币种或订单号不一致;
  • 全额退款和部分退款;
  • 测试凭据误用于生产环境;
  • 同一个支付通知被重复处理。

订单状态不能只依据前端跳转结果判断。用户可能在支付成功后直接关闭页面,网络也可能在跳转过程中中断。应主要依据通过验签的 Webhook 和服务端订单查询结果,并对 Webhook 做幂等处理,防止重复发货。

使用托管结账页通常能减少网站直接接触银行卡数据的范围,但不代表网站会自动满足所有合规要求。仍需确认 PCI DSS、印度监管要求、隐私政策、税务规定和支付服务商的商户条款。具体义务取决于业务模式、公司所在地和实际支付流程。

备注:内容仅供参考。