Implementing WeChat Pay V3 Unified Order API in ASP.NET Core

Offficial API Documentation

Signature Generation: https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_0.shtml

Unified Order API: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_1.shtml

Certificate Serial Number: https://wechatpay-api.gitbook.io/wechatpay-api-v3/chang-jian-wen-ti/zheng-shu-xiang-guan#ru-he-cha-kan-zheng-shu-xu-lie-hao

Private Key and Certiifcates: https://wechatpay-api.gitbook.io/wechatpay-api-v3/ren-zheng/zheng-shu#sheng-ming-suo-shi-yong-de-zheng-shu

Signature Implementation

Create a custom HTTP handler to generate WeChat Pay V3 signatures:

using System;
using System.IO;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

public class WeChatPayAuthHandler : DelegatingHandler
{
    private readonly string merchantIdentifier;
    private readonly string certificateSerial;

    public WeChatPayAuthHandler(string merchantId, string certSerial)
    {
        InnerHandler = new HttpClientHandler();
        merchantIdentifier = merchantId;
        certificateSerial = certSerial;
    }

    protected override async Task<httpresponsemessage> SendAsync(
        HttpRequestMessage request, 
        CancellationToken cancellationToken)
    {
        var authorization = await GenerateAuthorizationHeader(request);
        request.Headers.Add("Authorization", $"WECHATPAY2-SHA256-RSA2048 {authorization}");
        request.Headers.Add("Accept", "application/json");
        request.Headers.Add("User-Agent", "Custom-WeChatPay-Client");
        
        return await base.SendAsync(request, cancellationToken);
    }

    private async Task<string> GenerateAuthorizationHeader(HttpRequestMessage request)
    {
        string httpMethod = request.Method.Method;
        string requestBody = "";
        
        if (request.Content != null && (httpMethod == "POST" || httpMethod == "PUT"))
        {
            requestBody = await request.Content.ReadAsStringAsync();
        }

        string pathAndQuery = request.RequestUri.PathAndQuery;
        long timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
        string nonce = Guid.NewGuid().ToString("N");

        string signatureData = $"{httpMethod}\n{pathAndQuery}\n{timestamp}\n{nonce}\n{requestBody}\n";
        string digitalSignature = CreateSignature(signatureData);
        
        return $"mchid=\"{merchantIdentifier}\",nonce_str=\"{nonce}\"," +
               $"timestamp=\"{timestamp}\",serial_no=\"{certificateSerial}\"," +
               $"signature=\"{digitalSignature}\"";
    }

    private string CreateSignature(string data)
    {
        string privateKey = "YOUR_PRIVATE_KEY_CONTENT";
        byte[] keyBytes = Convert.FromBase64String(privateKey);
        
        using (var cngKey = CngKey.Import(keyBytes, CngKeyBlobFormat.Pkcs8PrivateBlob))
        using (var rsa = new RSACng(cngKey))
        {
            byte[] dataBytes = Encoding.UTF8.GetBytes(data);
            byte[] signatureBytes = rsa.SignData(dataBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
            return Convert.ToBase64String(signatureBytes);
        }
    }
}
</string></httpresponsemessage>

Unified Order API Integration

Execute unified order requests using the authentication handler:

var apiEndpoint = "https://api.mch.weixin.qq.com/v3/pay/transactions/app";
var orderRequest = new
{
    appid = "YOUR_APP_ID",
    mchid = "YOUR_MERCHANT_ID",
    description = "Product Description",
    amount = new { total = 100 },
    out_trade_no = "ORDER_NUMBER_123",
    notify_url = "https://your-domain.com/api/payment-callback"
};

using (var client = new HttpClient(new WeChatPayAuthHandler("MERCHANT_ID", "CERT_SERIAL")))
{
    var jsonContent = new StringContent(
        Newtonsoft.Json.JsonConvert.SerializeObject(orderRequest),
        Encoding.UTF8,
        "application/json"
    );

    var response = await client.PostAsync(apiEndpoint, jsonContent);
    var responseContent = await response.Content.ReadAsStringAsync();
    
    // Response contains prepay_id and other payment details
}

Implementation Notes

Ensure proper certificate installation for both development and production environments. The private key should be extracted from the merchant certificate provided by WeChat Pay. Always verify request body content matches the signed data during debugging.

Tags: ASP.NET Core WeChat Pay Payment Integration API V3 Signature Generation

Posted on Mon, 05 Oct 2026 16:26:14 +0000 by Tony187uk