You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Stripe与ASP.NET Core Web API集成Gpay等钱包/UPI支付

ASP.NET Core Web API集成Google Pay、PhonePe、Paytm支付方案

Stripe支持Google Pay作为支付方式,但PhonePe、Paytm属于印度本土独立支付网关,需直接对接其官方API。以下是三种支付方式的具体实现代码:


一、Google Pay集成(基于Stripe)

需修改现有Stripe服务,支持指定google_pay作为支付方式类型,前端需配合使用支付Intent的ClientSecret完成支付确认。

1. 调整支付请求模型与Stripe服务

// 扩展支持多支付方式的请求模型
public class StripePaymentRequest
{
    public string CustomerId { get; set; }
    public string Email { get; set; }
    public string Description { get; set; }
    public string Currency { get; set; }
    public long Amount { get; set; } // 单位为最小货币单位(如印度卢比=派萨)
    public string PaymentMethodType { get; set; } // 可选值:card、google_pay等
}

// 更新StripeService中的支付方法
public async Task<PaymentIntent> AddStripePaymentAsync(StripePaymentRequest request, CancellationToken ct)
{
    var options = new PaymentIntentCreateOptions
    {
        Customer = request.CustomerId,
        Description = request.Description,
        Amount = request.Amount,
        Currency = request.Currency,
        PaymentMethodTypes = new List<string> { request.PaymentMethodType },
        ReceiptEmail = request.Email,
    };

    var service = new PaymentIntentService();
    return await service.CreateAsync(options, ct);
}

2. 调用代码替换原卡片支付逻辑

try
{
    var paymentRequest = new StripePaymentRequest
    {
        CustomerId = customerId,
        Email = paymentDetails.emailAddress,
        Description = paymentDetails.Description,
        Currency = paymentDetails.Currency, // 示例:"inr"
        Amount = paymentDetails.Amount, // 注意转换为最小单位(如100卢比=10000派萨)
        PaymentMethodType = "google_pay"
    };

    var paymentIntent = await _stripeService.AddStripePaymentAsync(paymentRequest, ct).ConfigureAwait(false);
    return paymentIntent.ClientSecret; // 返回给前端完成支付确认
}
catch (Exception exp)
{
    // 建议添加日志记录,不要直接返回null
    return null;
}

二、PhonePe UPI支付集成

PhonePe提供独立REST API,需完成签名生成、支付发起、回调验证三个核心步骤。

1. 配置参数(appsettings.json)

"PhonePeSettings": {
    "MerchantId": "你的商户ID",
    "SaltKey": "你的盐值",
    "SaltIndex": "1",
    "BaseUrl": "https://api.phonepe.com/apis/hermes",
    "CallbackUrl": "https://你的公网域名/api/payments/phonepe-callback"
}

2. 支付发起与回调处理代码

// PhonePe支付请求模型
public class PhonePePaymentRequest
{
    public string MerchantTransactionId { get; set; }
    public long Amount { get; set; } // 单位:派萨
    public string MerchantUserId { get; set; }
}

// PhonePe支付服务
public class PhonePePaymentService
{
    private readonly IConfiguration _config;

    public PhonePePaymentService(IConfiguration config)
    {
        _config = config;
    }

    public async Task<string> InitiatePaymentAsync(PhonePePaymentRequest request, CancellationToken ct)
    {
        var merchantId = _config["PhonePeSettings:MerchantId"];
        var saltKey = _config["PhonePeSettings:SaltKey"];
        var baseUrl = _config["PhonePeSettings:BaseUrl"];
        var callbackUrl = _config["PhonePeSettings:CallbackUrl"];

        // 构建支付请求体
        var paymentData = new
        {
            merchantId = merchantId,
            merchantTransactionId = request.MerchantTransactionId,
            merchantUserId = request.MerchantUserId,
            amount = request.Amount,
            callbackUrl = callbackUrl,
            paymentInstrument = new { type = "UPI", targetApp = "com.phonepe.app" }
        };

        // 生成签名
        var payload = Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonSerializer.Serialize(paymentData)));
        var signatureRaw = $"{payload}/{request.MerchantTransactionId}/{saltKey}";
        var signature = HashSHA256(signatureRaw) + "###" + _config["PhonePeSettings:SaltIndex"];

        // 发起支付请求
        using var client = new HttpClient();
        var requestMessage = new HttpRequestMessage(HttpMethod.Post, $"{baseUrl}/pg/v1/pay")
        {
            Headers = { { "X-VERIFY", signature } },
            Content = new StringContent(JsonSerializer.Serialize(new { request = payload }), Encoding.UTF8, "application/json")
        };

        var response = await client.SendAsync(requestMessage, ct);
        var responseContent = await response.Content.ReadAsStringAsync(ct);
        var result = JsonSerializer.Deserialize<PhonePePaymentResponse>(responseContent);

        return result.Data.InstrumentResponse.RedirectInfo.Url; // 返回跳转URL给前端
    }

    // SHA256哈希工具方法
    private string HashSHA256(string input)
    {
        using var sha256 = SHA256.Create();
        var bytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(input));
        return BitConverter.ToString(bytes).Replace("-", "").ToLower();
    }
}

// 回调处理接口
[ApiController]
[Route("api/payments")]
public class PaymentController : ControllerBase
{
    private readonly IConfiguration _config;

    public PaymentController(IConfiguration config)
    {
        _config = config;
    }

    [HttpPost("phonepe-callback")]
    public IActionResult PhonePeCallback([FromBody] PhonePeCallbackRequest callbackRequest)
    {
        var saltKey = _config["PhonePeSettings:SaltKey"];
        var signature = callbackRequest.Signature;
        var payload = callbackRequest.Response;

        // 验证签名
        var expectedSignatureRaw = $"{payload}/{callbackRequest.MerchantTransactionId}/{saltKey}";
        var expectedSignature = HashSHA256(expectedSignatureRaw) + "###" + _config["PhonePeSettings:SaltIndex"];

        if (signature != expectedSignature)
            return BadRequest("无效签名");

        var responseData = JsonSerializer.Deserialize<PhonePeCallbackResponse>(Convert.FromBase64String(payload));
        if (responseData.Data.TransactionStatus == "SUCCESS")
        {
            // 处理支付成功逻辑(如更新订单状态)
            return Ok(new { status = "SUCCESS" });
        }

        return BadRequest("支付失败");
    }

    private string HashSHA256(string input)
    {
        using var sha256 = SHA256.Create();
        var bytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(input));
        return BitConverter.ToString(bytes).Replace("-", "").ToLower();
    }
}

// 辅助模型(需根据PhonePe官方文档定义完整字段)
public class PhonePePaymentResponse { /* 省略字段定义 */ }
public class PhonePeCallbackRequest { /* 省略字段定义 */ }
public class PhonePeCallbackResponse { /* 省略字段定义 */ }

三、Paytm UPI支付集成

Paytm同样提供独立API,需完成订单创建、签名验证、回调处理流程。

1. 配置参数(appsettings.json)

"PaytmSettings": {
    "MerchantId": "你的商户ID",
    "MerchantKey": "你的商户密钥",
    "BaseUrl": "https://securegw.paytm.in",
    "CallbackUrl": "https://你的公网域名/api/payments/paytm-callback"
}

2. 支付发起与回调处理代码

// Paytm支付服务
public class PaytmPaymentService
{
    private readonly IConfiguration _config;

    public PaytmPaymentService(IConfiguration config)
    {
        _config = config;
    }

    public async Task<string> InitiatePaymentAsync(string orderId, long amount, string userId, CancellationToken ct)
    {
        var merchantId = _config["PaytmSettings:MerchantId"];
        var merchantKey = _config["PaytmSettings:MerchantKey"];
        var baseUrl = _config["PaytmSettings:BaseUrl"];
        var callbackUrl = _config["PaytmSettings:CallbackUrl"];

        // 构建请求参数
        var parameters = new Dictionary<string, string>
        {
            { "MID", merchantId },
            { "ORDER_ID", orderId },
            { "CUST_ID", userId },
            { "TXN_AMOUNT", amount.ToString() },
            { "CHANNEL_ID", "WAP" },
            { "INDUSTRY_TYPE_ID", "Retail" },
            { "WEBSITE", "WEBSTAGING" }, // 生产环境改为DEFAULT
            { "CALLBACK_URL", callbackUrl },
            { "PAYMENT_MODE_ONLY", "UPI" } // 指定仅UPI支付
        };

        // 生成签名
        var signature = GeneratePaytmSignature(parameters, merchantKey);
        parameters.Add("CHECKSUMHASH", signature);

        // 创建订单并获取跳转URL
        using var client = new HttpClient();
        var content = new FormUrlEncodedContent(parameters);
        var response = await client.PostAsync($"{baseUrl}/order/create", content, ct);
        var responseContent = await response.Content.ReadAsStringAsync(ct);
        var result = JsonSerializer.Deserialize<PaytmCreateOrderResponse>(responseContent);

        if (result.Status == "SUCCESS")
            return $"{baseUrl}/theia/api/v1/showPaymentPage?mid={merchantId}&orderId={orderId}";

        throw new Exception("Paytm支付发起失败");
    }

    // Paytm签名生成方法
    private string GeneratePaytmSignature(Dictionary<string, string> parameters, string merchantKey)
    {
        var sortedParams = parameters.OrderBy(k => k.Key).ToDictionary(k => k.Key, v => v.Value);
        var stringToHash = string.Join("|", sortedParams.Values) + "|" + merchantKey;
        using var sha256 = SHA256.Create();
        var bytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(stringToHash));
        return Convert.ToBase64String(bytes);
    }
}

// 回调处理接口
[HttpPost("paytm-callback")]
public IActionResult PaytmCallback([FromForm] Dictionary<string, string> formData)
{
    var merchantKey = _config["PaytmSettings:MerchantKey"];
    var signature = formData["CHECKSUMHASH"];
    formData.Remove("CHECKSUMHASH");

    // 验证签名
    var computedSignature = GeneratePaytmSignature(formData, merchantKey);
    if (computedSignature != signature)
        return BadRequest("无效签名");

    if (formData["STATUS"] == "TXN_SUCCESS")
    {
        // 处理支付成功逻辑
        return Ok(new { status = "SUCCESS" });
    }

    return BadRequest("支付失败");
}

// 辅助模型(需根据Paytm官方文档定义完整字段)
public class PaytmCreateOrderResponse { /* 省略字段定义 */ }

注意事项

  1. 所有支付网关需提前申请商户账号,获取对应的密钥、商户ID等参数
  2. 金额需转换为对应货币的最小单位(如印度卢比=派萨,1卢比=100派萨)
  3. 回调地址需为公网可访问地址,测试阶段可使用ngrok等工具映射本地端口
  4. 需完善异常处理与日志记录,避免直接返回null

内容的提问来源于stack exchange,提问作者rameshsriram

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 23:54:59