引自免费微信小程序:皆我百晓生
看起来你在尝试使用微信支付API V3进行转账操作时遇到了签名验证失败的问题。根据错误信息,微信服务器返回的消息指出签名不匹配(sign not match
)。为了帮您解决这个问题,我们需要检查几个关键点:
- 确保您的密钥对是正确的。
- 检查请求方法、URL、请求体以及时间戳是否正确地用于签名计算。
- 使用正确的签名算法(SHA256)。
下面是一个C#示例代码,展示了如何构建并验证签名。请注意,你需要将YOUR_APPID
、YOUR_API_KEY
替换为实际的AppID和API Key。
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
public class WeChatPayHelper
{
private const string BaseUrl = "https://api.mch.weixin.qq.com";
private readonly string _appId;
private readonly string _apiKey;
public WeChatPayHelper(string appId, string apiKey)
{
_appId = appId;
_apiKey = apiKey;
}
public async Task<string> SendRequestAsync(HttpMethod method, string path, Dictionary<string, object> data)
{
var timestamp = GetTimestamp();
var nonceStr = GenerateNonceStr();
var url = $"{BaseUrl}/{path}";
var sortedParameters = GetSortedParameters(method, timestamp, nonceStr, data);
var sign = CalculateSignature(sortedParameters);
var content = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json");
using var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", sign);
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Timestamp", timestamp);
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("NonceStr", nonceStr);
var response = await httpClient.SendAsync(new HttpRequestMessage(method, url) { Content = content });
if (response.IsSuccessStatusCode)
{
var responseBody = await response.Content.ReadAsStringAsync();
return responseBody;
}
else
{
throw new Exception($"HTTP error: {(int)response.StatusCode} - {response.ReasonPhrase}");
}
}
private static long GetTimestamp()
{
return DateTimeOffset.UtcNow.ToUnixTimeSeconds();
}
private static string GenerateNonceStr()
{
return Guid.NewGuid().ToString("N").Substring(0, 16);
}
private static string CalculateSignature(Dictionary<string, string> parameters)
{
var sortedKeys = parameters.Keys.OrderBy(key => key).ToList();
var sb = new StringBuilder();
foreach (var key in sortedKeys)
{
sb.Append($"{key}={parameters[key]}&");
}
sb.Append("key=" + _apiKey); // 添加API Key到参数末尾
var plainText = sb.ToString();
var hashBytes = Encoding.UTF8.GetBytes(plainText);
using var sha256 = System.Security.Cryptography.SHA256.Create();
var hash = sha256.ComputeHash(hashBytes);
return Convert.ToBase64String(hash);
}
private static Dictionary<string, string> GetSortedParameters(HttpMethod method, long timestamp, string nonceStr, Dictionary<string, object> data)
{
var parameters = new Dictionary<string, string>
{
{"mch_id", _appId},
{"nonce_str", nonceStr},
{"timestamp", timestamp.ToString()},
{"sign_method", "HMAC-SHA256"},
};
foreach (var kvPair in data)
{
parameters.Add(kvPair.Key, kvPair.Value.ToString());
}
return parameters;
}
}
// 示例用法
public async Task Main()
{
var helper = new WeChatPayHelper("YOUR_APPID", "YOUR_API_KEY");
var data = new Dictionary<string, object>
{
{"appid", "YOUR_APPID"}, // 请确保这个字段在数据中
// 其他需要传递的数据...
};
var result = await helper.SendRequestAsync(HttpMethod.Post, "/v3/transfer/batches", data);
Console.WriteLine(result);
}
请确保你的AppID和API Key是有效的,并且在调用SendRequestAsync
方法时,提供的数据包含了所有必要的字段,特别是appid
。此外,确保所有请求头的时间戳和随机字符串都是新的,每次请求都应使用不同的nonce_str。
如果问题仍然存在,请检查网络请求和响应内容,确保没有遗漏任何关键信息。如果你还有其他疑问或遇到其他问题,随时向我提问。