- A+
所属分类:.NET技术
接口文档:微信支付-开发者文档 (qq.com)
public const string transactions_url = "https://api.mch.weixin.qq.com/v3/pay/transactions/h5"; public static string certPath = AppDomain.CurrentDomain.BaseDirectory + @"certapiclient_cert.p12"; public static string certificatesPath = AppDomain.CurrentDomain.BaseDirectory + @"certcertificates_cert.pem"; // 回调解密证书 根据接口获取后 保存为 pem 后缀 我请求后自己手动保存的。没写代码去保存 private static string certPassword = "888888888"; //.p12 的证书密码 public string BuildAuth(string mchid, string serial_no, string method, string uri, string body) { var timestamp = DateTimeOffset.Now.ToUnixTimeSeconds(); string nonce = Guid.NewGuid().ToString(); //构造签名串 //HTTP请求方法n + URLn + 请求时间戳n + 请求随机串n + 请求报文主体n string message = method + "n" + uri + "n" + timestamp + "n" + nonce + "n" + body + "n"; string signature = GenerateSignature(message); //发起请求的商户(包括直连商户、服务商或渠道商)的商户号 mchid //商户API证书序列号serial_no,用于声明所使用的证书 //请求随机串nonce_str //时间戳timestamp //签名值signature return "mchid="" + mchid + "",nonce_str="" + nonce + "",timestamp="" + timestamp + "",serial_no="" + serial_no + "",signature="" + signature + """; } /// <summary> /// 生成签名 /// </summary> /// <param name="message"></param> /// <returns></returns> public static string GenerateSignature(string message) { X509Certificate2 cert = new X509Certificate2(certPath, certPassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable); RSA PrivateKey = cert.GetRSAPrivateKey(); byte[] dataBytes = Encoding.UTF8.GetBytes(message); byte[] signatureBytes = PrivateKey.SignData(dataBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); return Convert.ToBase64String(signatureBytes); } /// <summary> /// 验证回调签名 /// </summary> /// <param name="signature"></param> /// <param name="timestamp"></param> /// <param name="nonce"></param> /// <param name="body"></param> /// <returns></returns> public static bool VerifySignature(string signature, string timestamp, string nonce, string body) { //应答时间戳n //应答随机串n //应答报文主体n X509Certificate2 wechatCert = new X509Certificate2(certificatesPath); //, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable string combinedString = string.Format("{0}n{1}n{2}n", timestamp, nonce, body); byte[] buff = Encoding.UTF8.GetBytes(combinedString); var rsaPar = wechatCert.GetRSAPublicKey().ExportParameters(false); var rsa = new RSACryptoServiceProvider(); rsa.ImportParameters(rsaPar); return rsa.VerifyData(buff, CryptoConfig.MapNameToOID("SHA256"), Convert.FromBase64String(signature)); } #region 加密解密 public static string AesGcmDecrypt(string associatedData, string nonce, string ciphertext, string apikey) { GcmBlockCipher gcmBlockCipher = new GcmBlockCipher(new AesEngine()); AeadParameters aeadParameters = new AeadParameters( new KeyParameter(Encoding.UTF8.GetBytes(apikey)), 128, Encoding.UTF8.GetBytes(nonce), Encoding.UTF8.GetBytes(associatedData)); gcmBlockCipher.Init(false, aeadParameters); byte[] data = Convert.FromBase64String(ciphertext); byte[] plaintext = new byte[gcmBlockCipher.GetOutputSize(data.Length)]; int length = gcmBlockCipher.ProcessBytes(data, 0, data.Length, plaintext, 0); gcmBlockCipher.DoFinal(plaintext, length); return Encoding.UTF8.GetString(plaintext); } #endregion
遇到的问题有
1、签名老验证不过去:
生成的签名老验证不过 n 不要加转义符
2、 发送的请求老是400 使用工具请求正常。代码不行。
UserAgent = "m.cnblogs.com/WebRequest";
不要留空就行 网址可填自己的。
3、回调解密的证书是自己获取的。可以获取后自己保存为后缀 .pem的证书文件
获取平台证书列表-文档中心-微信支付商户平台 (qq.com)
4、请求到h5_url 后可以在后面拼接指定跳转链接 https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx2916263004719461949c84457c735b0000&package=2150917749&redirect_url=System.Web.HttpUtility.UrlEncode("https://www.cnblogs.com/MIMU86")
5、苹果手机不是默认浏览器会跳到默认浏览器 无解