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.