asp.net 有偿求解决微信APIV3验签错误问题。
排查了很多遍了没找到原因,求指导,谢谢。
是asp.net开发语言,不要从别处copy代码过来回复。
不要回复Java的代码,谢谢。
{
"code": "SIGN_ERROR",
"detail": {
"detail": {
"issue": "sign not match"
},
"field": "signature",
"location": "authorization",
"sign_information": {
"method": "POST",
"sign_message_length": 391,
"truncated_sign_message": "POST\n/v3/transfer/batches\n1717809045\ne88f817a05b245fd870a5e1b827d3ebb\n{\"appid\"\n",
"url": "/v3/transfer/batches"
}
},
"message": "错误的签名,验签失败"
}
public string tixian(string uid, int amount)
{
//商户平台证书号
string zsh = "66CF9B00B8F357F29BFD1DFAAAAAAAAAAA";
//证书密码(商户号)
string password = "1652555555";
//请求地址
string url = "https://api.mch.weixin.qq.com/v3/transfer/batches";
//生成随机id
var sn = "P" + IdHelper.GetId();
string appid = "wxab7919b2axxxxx";
string openid = uid;
string batch_name = "提现";
string batch_remark = "提现";
int total_amount = amount;
int total_num = 1;
var transfer_detail_list = new List<Dictionary<string, object>>
{
new Dictionary<string, object> {
["out_detail_no"] = "T" + IdHelper.GetId(),
["transfer_amount"] = total_amount,
["transfer_remark"] = "提现",
["openid"] = openid,
}
};
var parm = new Dictionary<string, object>
{
["appid"] = appid,
["out_batch_no"] = sn,
["batch_name"] = batch_name,
["batch_remark"] = batch_remark,
["total_amount"] = total_amount,
["total_num"] = total_num,
["transfer_detail_list"] = transfer_detail_list,
};
//导出证书密钥
string strReadFilePath = GlobalSwitch.WebRootPath + @"\apiclient_key.pem";
LogHelper.WriteLog_LocalTxt(strReadFilePath);
StreamReader srReadFile = new StreamReader(strReadFilePath, Encoding.GetEncoding("GB2312"));
var txt = "";
// 读取流直至文件末尾结束
while (!srReadFile.EndOfStream)
{
string strReadLine = srReadFile.ReadLine(); //读取每行数据
txt += strReadLine;
Console.WriteLine(strReadLine); //屏幕打印每行数据
}
srReadFile.Close();
LogHelper.WriteLog_LocalTxt("parmToJson:" + parm.ToJson());
//发送post请求
var sess = httpPost(url, parm.ToJson(), txt, password, zsh);
LogHelper.WriteLog_LocalTxt("PayApi-tixian:" + sess);
return "成功";
}
public static string httpPost(string url, string postData, string privateKey, string merchantId, string serialNo)
{
privateKey = privateKey.Replace("-----BEGIN PRIVATE KEY-----", "").Replace("-----END PRIVATE KEY-----", "");
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "application/json;charset=UTF-8";
request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3100.0 Safari/537.36";
request.Accept = "application/json";
//生成微信支付V3签名
string Authorization = GetAuthorization(url, "POST", postData, privateKey, merchantId, serialNo);
request.Headers.Add("Authorization", Authorization);
byte[] paramJsonBytes = Encoding.UTF8.GetBytes(postData);
request.ContentLength = paramJsonBytes.Length;
Stream writer;
try
{
writer = request.GetRequestStream();
}
catch (Exception)
{
writer = null;
//throw new PayServiceException(500, "连接服务器失败");自定义异常类,无需理会
}
writer.Write(paramJsonBytes, 0, paramJsonBytes.Length);
writer.Close();
HttpWebResponse response;
try
{
response = (HttpWebResponse)request.GetResponse();
}
catch (WebException ex)
{
response = ex.Response as HttpWebResponse;
}
Stream resStream = response.GetResponseStream();
StreamReader reader = new StreamReader(resStream);
string text = reader.ReadToEnd();
LogHelper.WriteLog_LocalTxt("PostResult:" + text);
//如果不是返回正确的响应,就把微信返回的message抛出去
if (!response.StatusCode.ToString().Equals("OK"))
{
LogHelper.WriteLog_LocalTxt("PayApi-httpPost:" + text);
}
return text;
}
public static string GetAuthorization(string url, string method, string data, string privateKey, string merchantId, string serialNo)
{
var uri = new Uri(url);
string urlPath = uri.PathAndQuery;
//string urlPath = "/v3/certificates";
string nonce = Guid.NewGuid().ToString("N");
var timestamp = DateTimeOffset.Now.ToUnixTimeSeconds();
//数据签名 HTTP请求方法\n接口地址的url\n请求时间戳\n请求随机串\n请求报文主体\n
method = string.IsNullOrEmpty(method) ? "" : method;
//string message = string.Format("{0}\n{1}\n{2}\n{3}\n{4}", method, urlPath, timestamp, nonce, data);
string message = $"{method}\n{uri}\n{timestamp}\n{nonce}\n{data}\n";
LogHelper.WriteLog_LocalTxt("GetAuthorization-Message:" + message);
LogHelper.WriteLog_LocalTxt("SignLength:" + message.Length);
string signTxt = Sign(message, privateKey);
//Authorization和格式
string authorzationTxt = string.Format("WECHATPAY2-SHA256-RSA2048 mchid=\"{0}\",nonce_str=\"{1}\",timestamp=\"{2}\",serial_no=\"{3}\",signature=\"{4}\"",
merchantId,
nonce,
timestamp,
serialNo,
signTxt
);
LogHelper.WriteLog_LocalTxt("authorzationTxt:" + authorzationTxt);
LogHelper.WriteLog_LocalTxt("signTxt:" + signTxt);
return authorzationTxt;
}
public static string Sign(string message, string privateKey)
{
//string mes = message.ToJson();
byte[] keyData = Convert.FromBase64String(privateKey);
using (CngKey cngKey = CngKey.Import(keyData, CngKeyBlobFormat.Pkcs8PrivateBlob))
using (RSACng rsa = new RSACng(cngKey))
{
byte[] data = Encoding.UTF8.GetBytes(message);
return Convert.ToBase64String(rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
}
}
+v:y00100594131