/// <summary> /// 获取平台证书的公钥(会从远程请求,不会缓存) /// </summary> /// <param name="timeOut"></param> /// <returns></returns> public async Task <PublicKeyCollection> GetPublicKeysAsync(/*int timeOut = Config.TIME_OUT*/) { var certificates = await CertificatesAsync(); if (!certificates.ResultCode.Success) { throw new TenpayApiRequestException("获取证书公钥失败:" + certificates.ResultCode.ErrorMessage); } if (certificates.data?.Length == 0) { throw new TenpayApiRequestException("Certificates 获取结果为空"); } PublicKeyCollection keys = new(); //var tenpayV3Setting = Senparc.Weixin.Config.SenparcWeixinSetting.TenpayV3Setting;//TODO:改成从构造函数配置 foreach (var cert in certificates.data) { var publicKey = SecurityHelper.AesGcmDecryptCiphertext(_tenpayV3Setting.TenPayV3_APIv3Key, cert.encrypt_certificate.nonce, cert.encrypt_certificate.associated_data, cert.encrypt_certificate.ciphertext); keys[cert.serial_no] = SecurityHelper.GetUnwrapCertKey(publicKey); } return(keys); }
public void CertificatesTest() { BasePayApis basePayApis = new BasePayApis(); var certs = basePayApis.CertificatesAsync().GetAwaiter().GetResult(); Assert.IsNotNull(certs); Console.WriteLine(certs.ToJson(true)); Assert.IsTrue(certs.ResultCode.Success); Assert.IsNull(certs.VerifySignSuccess);//不参与验证 Console.WriteLine(); var tenpayV3Setting = Senparc.Weixin.Config.SenparcWeixinSetting.TenpayV3Setting; var cert = certs.data.First(); var pubKey = SecurityHelper.AesGcmDecryptCiphertext(tenpayV3Setting.TenPayV3_APIv3Key, cert.encrypt_certificate.nonce, cert.encrypt_certificate.associated_data, cert.encrypt_certificate.ciphertext); Console.WriteLine(pubKey); Assert.IsNotNull(pubKey); }
/// <summary> /// 将返回的结果中的ciphertext进行AEAD_AES_256_GCM解反序列化为实体 /// 签名规则见微信官方文档 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_5.shtml /// </summary> /// <param name="aes_key">这里需要传入apiv3秘钥进行AEAD_AES_256_GCM解密 可空</param> /// <param name="nonce">加密的随机串 可空</param> /// <param name="associated_data">附加数据包 可空</param> /// <returns></returns> // TODO: 本方法持续测试 public async Task <T> AesGcmDecryptGetObjectAsync <T>(string aes_key = null, string nonce = null, string associated_data = null) where T : ReturnJsonBase, new() { aes_key ??= _tenpayV3Setting.TenPayV3_APIv3Key; nonce ??= NotifyRequest.resource.nonce; associated_data ??= NotifyRequest.resource.associated_data; var decrypted_string = SecurityHelper.AesGcmDecryptCiphertext(aes_key, nonce, associated_data, NotifyRequest.resource.ciphertext); T result = decrypted_string.GetObject <T>(); //验证请求签名 var wechatpayTimestamp = _httpContext.Request.Headers?["Wechatpay-Timestamp"]; var wechatpayNonce = _httpContext.Request.Headers?["Wechatpay-Nonce"]; var wechatpaySignature = _httpContext.Request.Headers?["Wechatpay-Signature"]; var wechatpaySerial = _httpContext.Request.Headers?["Wechatpay-Serial"]; result.VerifySignSuccess = await TenPaySignHelper.VerifyTenpaySign(wechatpayTimestamp, wechatpayNonce, wechatpaySignature, Body, wechatpaySerial, this._tenpayV3Setting); result.ResultCode = new TenPayApiResultCode($"{_httpContext.Response.StatusCode} / {_httpContext.Request.Method}", "", "", "", result.VerifySignSuccess == true); return(result); }