接口文档:微信支付-开发者文档 (qq.com)
public const string transactions_url = "https://api.mch.weixin.qq.com/v3/pay/transactions/h5"; public static string certpath = appdomain.currentdomain.basedirectory + @"\cert\apiclient_cert.p12"; public static string certificatespath = appdomain.currentdomain.basedirectory + @"\cert\certificates_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 + url\n + 请求时间戳\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、苹果手机不是默认浏览器会跳到默认浏览器 无解
发表评论