using System; using System.Collections.Generic; using Library; using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography; using Microsoft.AspNetCore.Http; using System.Text; using System.IO; using System.Linq; using MySystem; using LitJson; using System.Net; using Org.BouncyCastle.Crypto.Modes; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Crypto.Engines; namespace MySystem { public class WeChatFunction { private HttpContext _context; public WeChatFunction(HttpContext context) { _context = context; } #region 领取会员卡 public Dictionary GetUserCard(int MerchantId) { string token = new WeChat.WeChatPublicClass(_context).getWXToken("wx5417e0770bb19c4e", "b853caabd367e1f3fd729c259ac8bee6"); string resp = function.GetWebRequest("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + token + "&type=wx_card"); JsonData jsonObj = JsonMapper.ToObject(resp); string ticket = jsonObj["ticket"].ToString(); string timeStamp = function.ConvertDateTimeInt(DateTime.Now).ToString(); string nonce_str = function.get_Random(12); var pay_param = new SortedList { {"timeStamp", timeStamp}, {"nonceStr", nonce_str}, {"ticket", ticket} }; var pay_param_str = String.Join("&", pay_param.Select(item => String.Format("{0}={1}", item.Key.Trim(), item.Value)).ToArray()); string signature = new WeChat.WeChatPublicClass(_context).SHA1(pay_param_str); Dictionary cardExt = new Dictionary(); cardExt.Add("timestamp", timeStamp); cardExt.Add("nonce_str", nonce_str); cardExt.Add("signature", signature); return cardExt; } #endregion #region 服务商平台JSAPI下单 public Dictionary Pay(string AppId, string MchId, string SubMchId, decimal PayMoney, string OrderNo, string Description, string OpenId, string Key, string NotifyUrl) { Dictionary return_result = new Dictionary(); int amount = (int)(PayMoney * 100); //具体请求参数 SortedList par = new SortedList(); par.Add("sp_appid", AppId); //服务商应用ID par.Add("sp_mchid", MchId); //服务商户号 par.Add("sub_mchid", SubMchId); //子商户号 par.Add("description", Description); //商品描述 par.Add("out_trade_no", OrderNo); //商户订单号 par.Add("notify_url", NotifyUrl); //服务商应用ID Dictionary amountDic = new Dictionary(); amountDic.Add("total", amount); //总金额 par.Add("amount", amountDic); //订单金额 Dictionary payer = new Dictionary(); payer.Add("sp_openid", OpenId); //用户在服务商appid下的唯一标识 par.Add("payer", payer); //支付者 string req = Newtonsoft.Json.JsonConvert.SerializeObject(par); function.WriteLog(req, "服务商平台JSAPI下单请求参数"); try { string merchantId = MchId; //商户号 string serialNo = "62B64854B768D344249FDB9E6EF4A1232C000E84"; //证书编号 function.WriteLog(serialNo, "服务商平台JSAPI下单请求参数"); function.WriteLog(Newtonsoft.Json.JsonConvert.SerializeObject(par), "服务商平台JSAPI下单请求参数"); string result = postJson("https://api.mch.weixin.qq.com/v3/pay/partner/transactions/jsapi", req, prikey, merchantId, serialNo); function.WriteLog(result, "服务商平台JSAPI下单请求参数"); JsonData jsonObj = JsonMapper.ToObject(result); string timeStamp = function.ConvertDateTimeInt(DateTime.Now).ToString(); string nonce_str = function.get_Random(12); string package = "prepay_id=" + jsonObj["prepay_id"].ToString(); var pay_param = new SortedList { {"appId", AppId}, {"timeStamp", timeStamp}, {"nonceStr", nonce_str}, {"package", package}, {"signType", "RSA"} }; var pay_param_str = ""; pay_param_str += AppId + "\n"; pay_param_str += timeStamp + "\n"; pay_param_str += nonce_str + "\n"; pay_param_str += package + "\n"; string paySign = Sign(pay_param_str, prikey); return_result.Add("appId", AppId); return_result.Add("timeStamp", timeStamp); return_result.Add("nonceStr", nonce_str); return_result.Add("package", package); return_result.Add("paySign", paySign); } catch (Exception ex) { function.WriteLog(DateTime.Now.ToString() + "\r\n" + ex.ToString(), "服务商品台JSAPI下单异常"); } return return_result; } #endregion #region 服务商平台申请退款API public Dictionary Refund(string AppId, string MchId, string SubMchId, decimal RefundMoney, decimal TotalMoney, string OrderNo, string RefundNo, string Description, string OpenId, string Key, string NotifyUrl) { Dictionary return_result = new Dictionary(); int refund = (int)(RefundMoney * 100); int amount = (int)(TotalMoney * 100); //具体请求参数 SortedList par = new SortedList(); par.Add("sub_mchid", SubMchId); //子商户号 par.Add("out_trade_no", OrderNo); //商户订单号 par.Add("out_refund_no", RefundNo); //商户退款单号 Dictionary amountDic = new Dictionary(); amountDic.Add("refund", refund); //退款金额 amountDic.Add("total", amount); //原订单金额 amountDic.Add("currency", "CNY"); //退款币种 par.Add("amount", amountDic); //金额信息 string req = Newtonsoft.Json.JsonConvert.SerializeObject(par); function.WriteLog(req, "服务商平台申请退款API"); try { string merchantId = MchId; //商户号 string serialNo = "62B64854B768D344249FDB9E6EF4A1232C000E84"; //证书编号 string result = postJson("https://api.mch.weixin.qq.com/v3/refund/domestic/refunds", req, prikey, merchantId, serialNo); function.WriteLog(result, "服务商平台申请退款API"); JsonData jsonObj = JsonMapper.ToObject(result); return_result.Add("refund_id", jsonObj["refund_id"].ToString()); //微信支付退款单号 return_result.Add("channel", jsonObj["channel"].ToString()); //退款渠道 return_result.Add("user_received_account", jsonObj["user_received_account"].ToString()); //退款入账账户 return_result.Add("status", jsonObj["status"].ToString()); //退款状态 return_result.Add("payer_total", jsonObj["amount"]["payer_total"].ToString()); //用户支付金额 return_result.Add("payer_refund", jsonObj["amount"]["payer_refund"].ToString()); //用户退款金额 return_result.Add("settlement_refund", jsonObj["amount"]["settlement_refund"].ToString()); //应结退款金额 return_result.Add("settlement_total", jsonObj["amount"]["settlement_total"].ToString()); //应结订单金额 return_result.Add("discount_refund", jsonObj["amount"]["discount_refund"].ToString()); //优惠退款金额 } catch (Exception ex) { function.WriteLog(DateTime.Now.ToString() + "\r\n" + ex.ToString(), "服务商平台申请退款API异常"); } return return_result; } #endregion #region 服务商平台查询单笔退款API public Dictionary QueryRefund(string RefundNo) { Dictionary return_result = new Dictionary(); try { string result = function.GetWebRequest("https://api.mch.weixin.qq.com/v3/refund/domestic/refunds/" + RefundNo); JsonData jsonObj = JsonMapper.ToObject(result); return_result.Add("refund_id", jsonObj["refund_id"].ToString()); //微信支付退款单号 return_result.Add("transaction_id", jsonObj["transaction_id"].ToString()); //微信支付订单号 return_result.Add("out_trade_no", jsonObj["out_trade_no"].ToString()); //商户订单号 return_result.Add("channel", jsonObj["channel"].ToString()); //退款渠道 return_result.Add("user_received_account", jsonObj["user_received_account"].ToString()); //退款入账账户 return_result.Add("status", jsonObj["status"].ToString()); //退款状态 return_result.Add("total", jsonObj["amount"]["total"].ToString()); //订单金额 return_result.Add("refund", jsonObj["amount"]["refund"].ToString()); //退款金额 return_result.Add("payer_total", jsonObj["amount"]["payer_total"].ToString()); //用户支付金额 return_result.Add("payer_refund", jsonObj["amount"]["payer_refund"].ToString()); //用户退款金额 return_result.Add("settlement_refund", jsonObj["amount"]["settlement_refund"].ToString()); //应结退款金额 return_result.Add("settlement_total", jsonObj["amount"]["settlement_total"].ToString()); //应结订单金额 return_result.Add("discount_refund", jsonObj["amount"]["discount_refund"].ToString()); //优惠退款金额 } catch (Exception ex) { function.WriteLog(DateTime.Now.ToString() + "\r\n" + ex.ToString(), "服务商平台查询单笔退款API异常"); } return return_result; } #endregion #region 服务商平台请求分账API public string ProfitShare(string SubMchId, string AppId, string TradeNo, string OrderNo, ReceiverList Receivers) { Dictionary result = new Dictionary(); result.Add("sub_mchid", SubMchId); //子商户号 result.Add("appid", AppId); //应用ID result.Add("transaction_id", TradeNo); //微信订单号 result.Add("out_order_no", OrderNo); //商户分账单号 result.Add("receivers", Receivers); //分账接收方列表 result.Add("unfreeze_unsplit", true); //是否解冻剩余未分资金 string req = Newtonsoft.Json.JsonConvert.SerializeObject(result); string resp = function.PostWebRequest("https://api.mch.weixin.qq.com/v3/profitsharing/orders", req, "application/json"); return resp; } #endregion #region 服务商平台查询分账结果API public string QueryProfitShare(string SubMchId, string TradeNo, string OrderNo) { string resp = function.GetWebRequest("https://api.mch.weixin.qq.com/v3/profitsharing/orders/" + OrderNo + "?sub_mchid=" + SubMchId + "&transaction_id=" + TradeNo); return resp; } #endregion #region 服务商平台解冻剩余资金API public string Unfreeze(string SubMchId, string TradeNo, string OrderNo, string Description) { Dictionary result = new Dictionary(); result.Add("sub_mchid", SubMchId); //子商户号 result.Add("transaction_id", TradeNo); //微信订单号 result.Add("out_order_no", OrderNo); //商户分账单号 result.Add("description", Description); //分账描述 string req = Newtonsoft.Json.JsonConvert.SerializeObject(result); string resp = function.PostWebRequest("https://api.mch.weixin.qq.com/v3/profitsharing/orders/unfreeze", req, "application/json"); return resp; } #endregion #region 微信客服 public string CustomerServiceChat() { return "需要对接"; } #endregion #region 获取平台证书 public string GetPlatCert() { string merchantId = "1611167423"; //商户号 string serialNo = "62B64854B768D344249FDB9E6EF4A1232C000E84"; //证书编号 string result = postJson("https://api.mch.weixin.qq.com/v3/certificates", "", prikey, merchantId, serialNo, "GET"); return result; //{"data":[{"effective_time":"2022-01-23T14:02:08+08:00","encrypt_certificate":{"algorithm":"AEAD_AES_256_GCM","associated_data":"certificate","ciphertext":"R+Z85w96Lv7GjtL2zGcwTugGAQkmRUnbKqpQ3VYU8cNcdamTTcJIOgFSXLdHykB1OC70onaRcTxX2Tp1RxlSVm8fbiJBtWpHw28qBIvziJDT9n9R8kF3ayofYulh0mE+46a2jnwO3ioccTaqaDM1qVChElmdksZ3ir79JZn+QfyMcn+O7Pw0x4raT9MROoKFNThX4INzMsyUW7x28dC7v6XKiFxw41bbxIF4qPtUqkKZCAOBcoA8zlyfo3uoLmTAkBoT+V/S8GUhSqXVP9hKotWjDhAzgy8js+R8I3aU6FY2hBK/wOvSSEyleD2YANZNe9Mh8mNoqjuJu8XRNE3n7iJKFcsaFjWHYGABU375xmJngVrqd70fL0TLuMwM+zXOgq3H8HP8TpAhrnQ1yLHd8LJR+KGhlU0Ef89AdLA0Uo/eyaf7EXozWSEqbdmS8EdOse9n4XAEVcx4jNa9rSgg5MggdCwjCye/CbzeucevpEo0Qyl+kGiu1kDsRyaLH8XmgqXXxxiH9WkjrQSDKTwzYudfqrRNdwG6q0MO4krCk4tRYYleLb3Tvvbyr2ffmly42VirXcp+H/f2B/qeD8iGa2PPxinrb3YZCi+E1g+bevRpz+HhXVNBmbkNceOc0hAmA5ul++t0hEJ5YaI7562CGKY6/bctSHIH+zQk0oAi9Wb5TebagGbNcdUOwuE8nZM1HA1hkN57h8ITA7yrGw/YVCYSsLdDHJS/Mo8Bcus/yCWqfo7/aeAkua29ipsrRCXTGc220nS+PsnS2tYXXpFBh13EW9J1cyPbNaT+i1GOe/LSX1zLYIALuIw1wt6adNJ4CtFWyEUYb/cLxveVlUtP1iUEFM7BMNil69/2SSFz4TTIoEL1ceuPMFvT4R8gL33r9EFdwrc9vo2bmyruyD+n7dLtLNcAh9KoC1rCOoEZHcYCpdQNR3NUb0qRDwb0I19CFZWEgNq4eJqepxkRtMXcF84wpvlhOtLtmbQbjO64JPIUsiQbvfadOLlB+RSYVtaEw/ZGUPyimCakTYffNyUz+aq7emM81Tc1EGT9OOQkY6JYDmIRjK8Q4NTgHmyniovaqD6dp6kW69lL3RfrcN4dOEHqzBcvgcrSkkSKB49sqJckQgmsGHCcm8w/gFxMe6tJY6ol1CYeliYWDl9zl6vPUIeWqUQVADifUk7vrBLcchTqP39+OMJat1KkDE3p1rgwqk/c1DCaFGhtOevnma6E3DMRTPuI7AvUEk+pUKkNUyOEfXJeXA6yr2tHJN1u3Qg5mS/n5maGkhBW0M9fkkNkoC4KGXmGuh5pnl3bPCeugAg7ggtkLD7SqwotdgVbx33Lng2NlsOozJSFGhIZCCicCKwY5BFec73KrQJgo3VtrKppujssB4ag3nA3VcPunPg/ezMTdYbX6sl9/fRxgMafrQzOcKq0JdujwAz4Ecw6HCUyY420+P7qpUijnOhvTNX2ug37OwxhOcqGMzd8d4C4j7246CRgS7dahYOShtV8iBYbiy+F+kzudQgzKY9aD93IMjpNeuUpujzv9KRgqJRwxD9OxwnjMiLz+Mo4psNvl0GTSF3J+AdS6oeF5l4BmhGrXEEMe/KUook3m7s86MkoIKDM4nszNY8HdzzXdjfw+6Qh0oQd7eW0nwFPPtac0yVSjqrLQzKQsqYs4F7zF0eKwWyhRuR5N23Rk4MX49YIYMjXbWB6iiricIRiO1f6HJ8Xf6F66RFJy4dYR1uwWdKGk6kc5ZMSn0HE6zqGBdZQV3BsEkz6wJZ1ZOpFThr0vA9poN0F32c2mJyXDtB1qMytUiEKWyPy2sJ6BIXSB6DsDXQ9U9QGBnKjQ8+yvCglocPjs6JA84cjhXFeR8ElWNmZJ/njUlmlHQ==","nonce":"92306d7e8732"},"expire_time":"2027-01-22T14:02:08+08:00","serial_no":"62B64854B768D344249FDB9E6EF4A1232C000E84"}]} } public string AesGcmDecrypt(string associatedData, string nonce, string ciphertext) { GcmBlockCipher gcmBlockCipher = new GcmBlockCipher(new AesEngine()); AeadParameters aeadParameters = new AeadParameters( new KeyParameter(Encoding.UTF8.GetBytes(AppConfig.WeChatParam.AesGemKey)), 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); } public string GetPublicKey() { var result = Newtonsoft.Json.JsonConvert.DeserializeObject(GetPlatCert()); var cmodel = result.data.OrderByDescending(t => t.expire_time).FirstOrDefault(); string pubkey = AesGcmDecrypt(cmodel.encrypt_certificate.associated_data, cmodel.encrypt_certificate.nonce, cmodel.encrypt_certificate.ciphertext); pubkey = pubkey.Replace("-----BEGIN CERTIFICATE-----", "").Replace("-----END CERTIFICATE-----", "").Replace("\n", ""); return pubkey; } #endregion #region 敏感信息加密 // string pubkey = "MIIBCgKCAQEAxK9K2ElQ0rUMwNFW4xMx7kmkpDlp7WGQ8VffXLpudJBIrRVFWJN7dlinCGu67ZATf+/GZvLSSzQPWejHEsI9vUp9ej0x5iZDHGc9/shNUjd03ORkKo/Ohj3Ju19RzX4mh+GoinKGiuKX8CdGPXPe7UObKWyETrDcxrit6VCJQjE604aNtVeAUE+41mOpCLGzTgAKt4psfHxsBRtqlveH4cH/51ip+cGkC/u36gfDMKaRluVfFO3ETxDkI94BwNtnthcA4WDKha+wjtB6HIJ5xxHV550+cfdkl4j8UKU6pB+C5JRNgvjAf6ljg/TF+cGF1d8C6IbYYodYKloqN2DzrwIDAQAB"; //公钥 string pubkey = "MIID3DCCAsSgAwIBAgIUU0FlQhvigU3sCPjQC9q5lEsTZGwwDQYJKoZIhvcNAQELBQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsTFFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3QgQ0EwHhcNMjEwNjMwMDMwOTA5WhcNMjYwNjI5MDMwOTA5WjBuMRgwFgYDVQQDDA9UZW5wYXkuY29tIHNpZ24xEzARBgNVBAoMClRlbnBheS5jb20xHTAbBgNVBAsMFFRlbnBheS5jb20gQ0EgQ2VudGVyMQswCQYDVQQGDAJDTjERMA8GA1UEBwwIU2hlblpoZW4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC64SIwN1afgge2pjFeNZAlKz5ZdJw8W/hisaIJnkzbE/1oG5n+SgtbMLfBLBFp0zMyT5SP5ve5aJAvUjwnRwQoDG+4z3jE8vLyjFLxoy5sWGex8+FBC5hs81oAUHuazigi5NcSH9Ji/8Lq3zFh8Az4+ZchQ14SFhSGTifSZfdTX5wYDEv3DKDYgQvvAgDgjBF1Uj91NpVD7ruQjAJ7MwZvUX7rnYFnQggFQwIBWazNXaGa7OpO6Xbf+uNtbl436My7WQX+ffjmtYmcgND60mgn/rFQMg5r+Q+J8mDgIaAzCmr3xW31OIvAD1iYV0ksTyQntD5pOzCYdHZPDOZCqYlHAgMBAAGjgYEwfzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIE8DBlBgNVHR8EXjBcMFqgWKBWhlRodHRwOi8vZXZjYS5pdHJ1cy5jb20uY24vcHVibGljL2l0cnVzY3JsP0NBPTFCRDQyMjBFNTBEQkMwNEIwNkFEMzk3NTQ5ODQ2QzAxQzNFOEVCRDIwDQYJKoZIhvcNAQELBQADggEBAEgXlFe4MpFUUnj6gJt5KoPpzLTNOXDHsglUrAobq/HlmDBOF8yCUFvtbRaJxUSQVFfo/2zag8J57YNMo2If1HkD1LMEGAcPGNS+aho9SgCFbLG+c82nNICl8g8oe1HNS7IpRjacSfrKIYt5VL5lHHC5ZJaKq0Ez9c7bfPGC6CaA8WDnApFZut5qhYNMBUYZZjAMVIZ2G/kIsxbo1oUpVEnQq5YQxPUDWdYKxdTvo7uXXpWv6qo761Hid24R7mdrGEuHZNBfxYCt1wJQNlcGVgCjk8PPo73mO0zYRwV0x7pNkFFbiP7aetf6RB82YUbuNkvql83Ox+e22ByMi8lOUZo="; string prikey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQD7f7VmtjtLJaY+oJkMgDN9dDE082ZOgquHorPrtJNEdf7VjRFLMoKOoiQsT4OgVq3lNN2KKndd5ahsegSq7Ng7aYJq7IDH584RWEGbekEn0M10aXThdk9dPSCMXBPFR6y4gMvV4R6pVbPBxoSFMI6ty+EqfZLP9Cxvxx7msIKEB46r2R6gYL7j061ytoURavUxGAZxMXnCAEckbrssiFwhLTmX6TtC8MVPyUfLPUh07ArRZxK2F0hpX35Te0Jda7xkulbWtz4EB8KPXr0bJGO/oUo+Prqpdjy0+zKMfMvBP6NG1Hnh3z7yBhlYIe4vymFQU1Wy0OtrEbrU1OdJiq5XAgMBAAECggEAJ7biAWczc8ltOCSKJpQ0DVKE1rS86hbuWUvTF5x7SOtNI5HUMki2nylxhuHDilVFvpUbis7r7JLwhri59ffSqYcexh20tFyhiNGkApZKpavuVby1bUkOfU3CzwdXQ+bumnAUQCD9g4X6DdZ4ZMPnNACm/Nu5jEcloT0TXyBua8SpmlFMYgo/x8XOTT4dEeubwNsfEpmSeWcQRJLJI5ujGgmmZLiAs7F3VlCJFNtQa1KT3a1EDhD5jajeQAzsPpQ48i/joOqE71RlVr77z4Ethr8o1Cc16K9Md2AtVesMZ6eZNqKkQ/qC3vnxk5Sy25tuVmOCXa81ErIf9Tf/JwhymQKBgQD/TXnYxEzYJCqa7/Ck6QqBHQf4ak1OVz7/NY7bmxYT5ez4eJKzrh+xQYWBq/UmKeEiH5QI6T3MVo7L20tbeuYLQwYpgb+BpOKHFne2ODOgDYreNREB06Ww2qAQYCqwyBnTqt7UthDmcXhcPojwxNLSJAOCQhld9TOOmK1db33PIwKBgQD8L5KiN9XRFCvUH6rhUcs/8lmGR2N8zSTts+BNCwIPGQWE0UvbjroyNxVbq6cXXlZZ6H07vEAgaIrLIkwLgen2IwsuOiyaEMvRP9oGwC+LnpP+9sxbW5w5do1hfyeGiSPPgSYIWZMOOwX+qfqXDMM3whJP1hk4El87kC+kl2URPQKBgQC4kTc8ebWgMI1Ik5wibIN2khlYAum+cB6P/BU6OCU+32NwwiI0mfY5fEfbVgiVvYMP20p3Ir/VgOIdCH2zNecnTx4eVbmwLRbDWH/VEU5pMEEroauY6XyInZVIIW3bfd4GAyqzFqijIHdGIMN5ZKGQ4A5VVhnmrkTGmyQCP37xhwKBgQCaLW+Fc4NqTt240x+Cn6IWV1E6UfzV+QmBtb4E/BznJBIGsHqjIbBeMOUC5X/DPq6mSwf9dEr0RVXNeQtq4aMrEyOrwG8yReCF7naaN/cZcfrjHvmzRN/PFda766Q7kS5ul3OsGS9ZvOYeWsdUf73+Ic1WN/u1Fy5X2P/3rYNhtQKBgAIioAq8psFdy/itpJryaWdmDM6fM6ctp5P6VBWOVp2JGkOzHboiXFToJJBtmi7Rdp8AN1aYBbtVX1o0+RmfEiHqXn84GpSNT6tGirHvARi5ab3jvn+bkUWjZYOGd96hus8GirA+wQb/V92Ms3jS5VUS1HBfHaTGT5G2Slrr8YZu"; //私钥 public string RSAEncrypt(string text) { byte[] publicKey = Convert.FromBase64String(pubkey); // var rsa = RSA.Create(); // rsa.ImportRSAPublicKey(publicKey, out _); // var buff = rsa.Encrypt(Encoding.UTF8.GetBytes(text), RSAEncryptionPadding.OaepSHA1); // return Convert.ToBase64String(buff); using (var x509 = new X509Certificate2(publicKey)) { using (var rsa = x509.GetRSAPublicKey()) { var buff = rsa.Encrypt(Encoding.UTF8.GetBytes(text), RSAEncryptionPadding.OaepSHA1); return Convert.ToBase64String(buff); } } } public string postJson(string url, string postData, string privateKey, string merchantId, string serialNo, string method = "POST") { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Method = method; 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"; string Authorization = GetAuthorization(url, method, postData, privateKey, merchantId, "62B64854B768D344249FDB9E6EF4A1232C000E84"); request.Headers.Add("Authorization", Authorization); request.Headers.Add("Wechatpay-Serial", serialNo); if (!string.IsNullOrEmpty(postData)) { byte[] paramJsonBytes; paramJsonBytes = System.Text.Encoding.UTF8.GetBytes(postData); request.ContentLength = paramJsonBytes.Length; Stream writer; try { writer = request.GetRequestStream(); } catch (Exception) { writer = null; Console.Write("连接服务器失败!"); } 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(); return text; //{\"code\":\"PARAM_ERROR\",\"message\":\"请确认待处理的消息是否为加密后的密文\"} //{\"applyment_id\":2000002247709762} } #endregion #region 图片上传 public string GetMediaId(string imgPath) { if (string.IsNullOrEmpty(imgPath)) { return ""; } string key = "wechatpic:" + function.MD5_16(imgPath); string media_id = RedisDbconn.Instance.Get(key); if (!string.IsNullOrEmpty(media_id)) { return media_id; } string filePath = function.getPath(imgPath); var filename = Path.GetFileName(filePath); FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read); Byte[] imgBytesIn = new Byte[fs.Length]; fs.Read(imgBytesIn, 0, imgBytesIn.Length); fs.Close(); byte[] hash = SHA256Managed.Create().ComputeHash(imgBytesIn); StringBuilder builder = new StringBuilder(); for (int i = 0; i < hash.Length; i++) { builder.Append(hash[i].ToString("x2")); } var sha256 = builder.ToString(); string metaStr = "{\"filename\":\""+ filename + "\",\"sha256\":\"" + sha256 + "\"}"; media_id = UploadImgApi(metaStr, imgBytesIn, filename); return media_id; } public string UploadImgApi(string metaStr, Byte[] imgBytesIn,string filename) { string url = "https://api.mch.weixin.qq.com/v3/merchant/media/upload"; string merchantId = "1611167423"; //商户号 string serialNo = "62B64854B768D344249FDB9E6EF4A1232C000E84"; //证书编号 string privateKey = prikey; #region 定义请求体中的内容 并转成二进制 string boundary = "lc199aecd61b4653ef"; string Enter = "\r\n"; string campaignIDStr1 = "--" + boundary + Enter + "Content-Disposition: form-data; name=\"meta\";" + Enter + "Content-Type:application/json;" + Enter + Enter + metaStr + Enter + "--" + boundary + Enter + "Content-Disposition:form-data;name=\"file\";filename=\""+ filename + "\";" + Enter + "Content-Type:image/jpeg" + Enter + Enter; byte[] byteData2 = imgBytesIn; string campaignIDStr3 = Enter + "--" + boundary + Enter; var byteData1 = System.Text.Encoding.UTF8.GetBytes(campaignIDStr1); var byteData3 = System.Text.Encoding.UTF8.GetBytes(campaignIDStr3); #endregion string transactionsResponse = UploadImg_postJson(url, byteData1, byteData2, byteData3, metaStr, privateKey, merchantId, serialNo, boundary, "POST"); var result=JsonMapper.ToObject(transactionsResponse); return result["media_id"].ToString(); } public string UploadImg_postJson(string url, byte[] b1, byte[] b2, byte[] b3, string metaStr, string privateKey, string merchantId, string serialNo, string boundary, string method = "POST") { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Method = method; //request.ContentType = "application/json;charset=UTF-8"; request.ContentType = "multipart/form-data;boundary=" + boundary; 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"; string Authorization = GetAuthorization(url, method, metaStr, privateKey, merchantId, serialNo); request.Headers.Add("Authorization", Authorization); Stream writer; try { writer = request.GetRequestStream(); } catch (Exception) { writer = null; } writer.Write(b1, 0, b1.Length); writer.Write(b2, 0, b2.Length); writer.Write(b3, 0, b3.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(); return text; } protected string GetAuthorization(string url, string method, string jsonParame, string privateKey, string merchantId, string serialNo) { var uri = new Uri(url); string urlPath = uri.PathAndQuery; string nonce = Guid.NewGuid().ToString(); 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}\n", method, urlPath, timestamp, nonce, jsonParame); 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 ); return authorzationTxt; } protected string Sign(string message, string privateKey) { byte[] keyData = Convert.FromBase64String(privateKey); byte[] data = System.Text.Encoding.UTF8.GetBytes(message); var rsa = RSA.Create(); rsa.ImportPkcs8PrivateKey(keyData, out _); return Convert.ToBase64String(rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)); // using (CngKey cngKey = CngKey.Import(keyData, CngKeyBlobFormat.Pkcs8PrivateBlob)) // using (RSACng rsa = new RSACng(cngKey)) // { // return Convert.ToBase64String(rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)); // } } #endregion #region 获取文件sha256 public string GetSha256(FileStream stream) { using (SHA256 mySHA256 = SHA256.Create()) { byte[] hashValue = mySHA256.ComputeHash(stream); return Encoding.UTF8.GetString(hashValue); } } #endregion #region 判断长期 public string CheckForever(DateTime? time) { if (time == null) { return ""; } if (time.Value.Year >= 2050) { return "长期"; } return time.Value.ToString("yyyy-MM-dd"); } #endregion } }