WeChatFunctionForHD.cs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. using System;
  2. using System.Collections.Generic;
  3. using Library;
  4. using LitJson;
  5. using System.Linq;
  6. using System.Security.Cryptography.X509Certificates;
  7. using System.Security.Cryptography;
  8. using System.Text;
  9. using System.IO;
  10. using System.Net;
  11. using System.Web;
  12. using MySystem.Models;
  13. using Org.BouncyCastle.Crypto.Modes;
  14. using Org.BouncyCastle.Crypto.Parameters;
  15. using Org.BouncyCastle.Crypto.Engines;
  16. using MySystem.Models.Main;
  17. namespace MySystem
  18. {
  19. public class WeChatFunctionForHD
  20. {
  21. public readonly static WeChatFunctionForHD Instance = new WeChatFunctionForHD();
  22. private WeChatFunctionForHD()
  23. { }
  24. public string MchId = "178590308";
  25. public string ApiKey = "XTH7TLTSJH4SOZC3NVFQJ726B5VRNVO6"; //AesGcmDecrypt解密使用
  26. public string serialNo = "5293C873581457469F1BE1839EA127B08ADE2D7B";
  27. public string getSerialNo = "7C6E6AD5DA1F7EB4A1071F2333C2FED0D8CC3A46"; //平台证书序列号Wechatpay-Serial
  28. // string pubkey = "MIIEJzCCAw+gAwIBAgIUUpPIc1gUV0afG+GDnqEnsIreLXswDQYJKoZIhvcNAQELBQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsTFFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3QgQ0EwHhcNMjMwODE3MTA0NzAyWhcNMjgwODE1MTA0NzAyWjCBgDESMBAGA1UEAwwJMTc4NTkwMzA4MRswGQYDVQQKDBLlvq7kv6HllYbmiLfns7vnu58xLTArBgNVBAsMJOWbm+W3neecgea2puinguexs+enkeaKgOaciemZkOWFrOWPuDELMAkGA1UEBgwCQ04xETAPBgNVBAcMCFNoZW5aaGVuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy6sn15bA09Umbch+Zd1rr23y7WRJ3UPc/LpPCLL7okjZRH4w3F3/pCDtZ659fyjz99WcDrP+rXkcFk31ysuXEbnyK3qUQJJ2aua1Qe9kzuAV4aF9PYedzIh6gZHaRmg36FEfgMPXBu/CIzV9Ap4YrIBWmPW2J8IM1L6Klmrt5G3XWA3A9Nu4R/ANgbe0/wskgC0Ytf0bY+B+5RVw3+93u+6Z3SNQBKpKlxY5su5sYvSqWC5AlFRh1lblemfzQsD3PGU+us5dr62y3rcWVOft9cgb8nK8nMf8sOXWmY8nbRRwU/8+9caZbLW18qGAvI7Egd02b6oVnwzo17tTE3jbowIDAQABo4G5MIG2MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgP4MIGbBgNVHR8EgZMwgZAwgY2ggYqggYeGgYRodHRwOi8vZXZjYS5pdHJ1cy5jb20uY24vcHVibGljL2l0cnVzY3JsP0NBPTFCRDQyMjBFNTBEQkMwNEIwNkFEMzk3NTQ5ODQ2QzAxQzNFOEVCRDImc2c9SEFDQzQ3MUI2NTQyMkUxMkIyN0E5RDMzQTg3QUQxQ0RGNTkyNkUxNDAzNzEwDQYJKoZIhvcNAQELBQADggEBAFzuYjsoefA5eBNGEvD4s6tH7RjK7a6rdCnybJlfO60ZyS16cR0Y1I0tRuBWlAcCCnRyu+uQyN4sAyvEHHDbTMFKQFKIPY+caGMCluORqVJdQ7pDzOydQCWMlBNI6e0KsczLG9gwgEstnpvGwzkGH2iN/dUl6JVwkXRLKpArzuNccibXHla7TjBTzBBRDqs3w02+bz9R4WofWCw1OHzryPG+Ue3R5p8cQkKqNdAQuukkVn4qDsBU9zaREKXxWq7T2sQp21b1J1ZCHcJLYSmBgueGzLrdt3GSgWOZHnkjm8WE50OtMwmluZYlY4b5oppnHuDxE5hXz2wBswJ7UGxvyAA="; //公钥
  29. string pubkey = "MIIEFDCCAvygAwIBAgIUfG5q1doffrShBx8jM8L+0NjMOkYwDQYJKoZIhvcNAQELBQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsTFFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3QgQ0EwHhcNMjMwODE3MTA0NzAxWhcNMjgwODE1MTA0NzAxWjBuMRgwFgYDVQQDDA9UZW5wYXkuY29tIHNpZ24xEzARBgNVBAoMClRlbnBheS5jb20xHTAbBgNVBAsMFFRlbnBheS5jb20gQ0EgQ2VudGVyMQswCQYDVQQGDAJDTjERMA8GA1UEBwwIU2hlblpoZW4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC7z1k/J0F1FK8ZC2zKyHhhCHPJX8YEFg4Ruaj4XDU4eoBzbTXS+wN1gJCLqXMw5uam6L5NO3jXaHHC6izTKhAog1jiO+mfcXKpno/EtZ1be2xKOguqPNIOrw7aPDoAcytrUy2wsLCpM6+LFIa+tBXwzOuVauXtcWqtXrL75Wo/NEMMcfe4lsFxPatdkF90BodDfMB6niVQyNkVqBhtdQQzBrPOjpNBX4f2WpcMpEy7TSge5VxCXGGSYW+E5xYzmiloRR0d1eJA7tdJ8VOdNbvaZSPSPHARZM7LsNC43bXMQJUpymRTf2wpV+imiB4XYL6Vx1gk2G77jdWPtLXLbZ8LAgMBAAGjgbkwgbYwCQYDVR0TBAIwADALBgNVHQ8EBAMCA/gwgZsGA1UdHwSBkzCBkDCBjaCBiqCBh4aBhGh0dHA6Ly9ldmNhLml0cnVzLmNvbS5jbi9wdWJsaWMvaXRydXNjcmw/Q0E9MUJENDIyMEU1MERCQzA0QjA2QUQzOTc1NDk4NDZDMDFDM0U4RUJEMiZzZz1IQUNDNDcxQjY1NDIyRTEyQjI3QTlEMzNBODdBRDFDREY1OTI2RTE0MDM3MTANBgkqhkiG9w0BAQsFAAOCAQEAEFh9Tm1uH1ZbQ3Nz/bxRlkYb6Y/O5buAoptMMJb95QIiTODtRx8+f8eXHVQ+slP2MuzrEGfGuoJ2c/clcEmjG4WGMm3h8hTXlL/jBKn8jW2qKj1gVlHdn+V9qdhy2gaS9VV6ZSdtpZmkqCYxfg9DI4GF+CjNxCxfpYH9Qd/gKe/anA5ps4j1j/ZUnQtIBhgcRyXhh7e5NOa6LM+1ui+wNb1uUSiick6oYiSo6FlnblBRQ6Yvx9OSJasqqD/5rl59eikibUhX2qgBeRlIsJOBUvUkl+Pdl/b86e+jirclYqxIWApv79BLR7akw6y94XEgMXOuGt5Xf1LzN3AW3OmKAQ=="; //公钥(通过GetPlatCert方法获取证书,解密得到)
  30. // string prikey = "MIIEpAIBAAKCAQEAy6sn15bA09Umbch+Zd1rr23y7WRJ3UPc/LpPCLL7okjZRH4w3F3/pCDtZ659fyjz99WcDrP+rXkcFk31ysuXEbnyK3qUQJJ2aua1Qe9kzuAV4aF9PYedzIh6gZHaRmg36FEfgMPXBu/CIzV9Ap4YrIBWmPW2J8IM1L6Klmrt5G3XWA3A9Nu4R/ANgbe0/wskgC0Ytf0bY+B+5RVw3+93u+6Z3SNQBKpKlxY5su5sYvSqWC5AlFRh1lblemfzQsD3PGU+us5dr62y3rcWVOft9cgb8nK8nMf8sOXWmY8nbRRwU/8+9caZbLW18qGAvI7Egd02b6oVnwzo17tTE3jbowIDAQABAoIBADrgCk9vG+TgjBBWUfuea1+2F/B5+kRFNt+z997a5pT+HBiJphQ99AV9I0PClDKrIwN0s30omSmKhg0IklICUnRkXVYmRC76Z9L1SFZ8HpcS/iBQb4TW7E3Q8iD8ia2quOamdMXjVwiBTIyjDLUyAI31N5NWDEcn+E+TmTpsRMKwXXZX0M84eBjNdxhA7zFFkOzfugCqECirUx02iOg6F9/f/lUf16cC8pBI27+CH2MnjanPFHWzgeIIYnTDS/coR+UGM0RwOBvUWNXHSjR959JO81S07cAhe2XNpUYmzoVNrvjM5c21gdcGEul8RnBiJFxjlElB6e+F8GrWITdBOTECgYEA+U5S8oAz1OsxpaW92CtrWpTUz7wpQnwkm7I+iWlcUq2BIGHljbN8jVqugI8SUsIDy6F5znYb9JEwGUTFG9xAJ0UcUsjya3k2wDfi2yyJ39LkKklAQFt9gegl9aBhxucVM8us7GJ90JCk78U+kTcc5fCw5mYZPNPrxPG1pSPWS/sCgYEA0SMhSRV3xz0MdP9dm6pHPJi0jVhqjtTncTKFGJXe1B14GzbrDNsOH/907L2R0lhMALT+AX3nrhH5lzzCvDvJL6xJm1v7bG90meXdU07ZsW+C1RYDJNOQWOBv12i1+AcHKizzJMyda97x5fOrt3Kgi8tD82+01C4BGiio8Lz4NnkCgYEAsUe0DkOCGBdDT6KjdDOz/E63Yh1QTbnPonPGqpokj5pXpzpWLUSD/lSMoFic1AKpBkWGQ32TdX9E78MKUzx01jf74xaH5Erm1xsmk2qBhIsHutYp/VnRzu3RCHCK9xDd794W0mVbSFODJglh64uAXjag5MWXjry3/G1RGOR5/78CgYAqt2wzC0l9zoBe3VH3W55VSDOIs0iAiAgF3PXGgcYTuTkxBdSYuZ1296ygNlA0kIhllJJVJ6xMp6s9MtHrtKJxNFWMgAsoqNM+I+9C9tYMIeStNWPK/9N5882kR+TzFixmduvq1khJIi5yc4TdYXJdW1UzwdtDg2oCN8/Z7B8esQKBgQDaKmfe7KEdvpQlscGmuMKzW+AzS4CNZMvdaNy6SBR/5V94KwqTQXnvROpFtl6Enuz1IfP1s0DMbcmBGL7fc/kD1nFIwo7PbHsXJP6PkU01QTOibTsCm1EM7ENG1FEhQCMNaHxq7kDB7f9r+DgxRgjSORUsuGa7lhpjdndrd7jD/A=="; //私钥
  31. string prikey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDLqyfXlsDT1SZtyH5l3WuvbfLtZEndQ9z8uk8IsvuiSNlEfjDcXf+kIO1nrn1/KPP31ZwOs/6teRwWTfXKy5cRufIrepRAknZq5rVB72TO4BXhoX09h53MiHqBkdpGaDfoUR+Aw9cG78IjNX0CnhisgFaY9bYnwgzUvoqWau3kbddYDcD027hH8A2Bt7T/CySALRi1/Rtj4H7lFXDf73e77pndI1AEqkqXFjmy7mxi9KpYLkCUVGHWVuV6Z/NCwPc8ZT66zl2vrbLetxZU5+31yBvycrycx/yw5daZjydtFHBT/z71xplstbXyoYC8jsSB3TZvqhWfDOjXu1MTeNujAgMBAAECggEAOuAKT28b5OCMEFZR+55rX7YX8Hn6REU237P33trmlP4cGImmFD30BX0jQ8KUMqsjA3SzfSiZKYqGDQiSUgJSdGRdViZELvpn0vVIVnwelxL+IFBvhNbsTdDyIPyJraq45qZ0xeNXCIFMjKMMtTIAjfU3k1YMRyf4T5OZOmxEwrBddlfQzzh4GM13GEDvMUWQ7N+6AKoQKKtTHTaI6DoX39/+VR/XpwLykEjbv4IfYyeNqc8UdbOB4ghidMNL9yhH5QYzRHA4G9RY1cdKNH3n0k7zVLTtwCF7Zc2lRibOhU2u+MzlzbWB1wYS6XxGcGIkXGOUSUHp74XwatYhN0E5MQKBgQD5TlLygDPU6zGlpb3YK2talNTPvClCfCSbsj6JaVxSrYEgYeWNs3yNWq6AjxJSwgPLoXnOdhv0kTAZRMUb3EAnRRxSyPJreTbAN+LbLInf0uQqSUBAW32B6CX1oGHG5xUzy6zsYn3QkKTvxT6RNxzl8LDmZhk80+vE8bWlI9ZL+wKBgQDRIyFJFXfHPQx0/12bqkc8mLSNWGqO1OdxMoUYld7UHXgbNusM2w4f/3TsvZHSWEwAtP4BfeeuEfmXPMK8O8kvrEmbW/tsb3SZ5d1TTtmxb4LVFgMk05BY4G/XaLX4BwcqLPMkzJ1r3vHl86u3cqCLy0Pzb7TULgEaKKjwvPg2eQKBgQCxR7QOQ4IYF0NPoqN0M7P8TrdiHVBNuc+ic8aqmiSPmlenOlYtRIP+VIygWJzUAqkGRYZDfZN1f0TvwwpTPHTWN/vjFofkSubXGyaTaoGEiwe61in9WdHO7dEIcIr3EN3v3hbSZVtIU4MmCWHri4BeNqDkxZeOvLf8bVEY5Hn/vwKBgCq3bDMLSX3OgF7dUfdbnlVIM4izSICICAXc9caBxhO5OTEF1Ji5nXb3rKA2UDSQiGWUklUnrEynqz0y0eu0onE0VYyACyio0z4j70L21gwh5K01Y8r/03nzzaRH5PMWLGZ26+rWSEkiLnJzhN1hcl1bVTPB20ODagI3z9nsHx6xAoGBANoqZ97soR2+lCWxwaa4wrNb4DNLgI1ky91o3LpIFH/lX3grCpNBee9E6kW2XoSe7PUh8/WzQMxtyYEYvt9z+QPWcUjCjs9sexck/o+RTTVBM6JtOwKbUQzsQ0bUUSFAIw1ofGruQMHt/2v4ODFGCNI5FSy4ZruWGmN2d2t3uMP8"; //私钥
  32. #region 间连商户开户意愿确认(提交申请单)
  33. public string MerchantApply(MerchantAddInfo info)
  34. {
  35. Dictionary<string, object> result = new Dictionary<string, object>();
  36. string business_code = DateTime.Now.ToString("yyyyMMddHHmmssfff") + function.get_Random(8);
  37. if (!string.IsNullOrEmpty(info.WeChatMerchantId))
  38. {
  39. result.Add("channel_id", info.WeChatMerchantId); //渠道商户号
  40. }
  41. result.Add("business_code", business_code); //业务申请编号
  42. WebCMSEntities dbpxc = new WebCMSEntities();
  43. //超级管理员信息
  44. Dictionary<string, object> contact_info = new Dictionary<string, object>();
  45. contact_info.Add("contact_type", "LEGAL"); //联系人类型
  46. contact_info.Add("name", RSAEncrypt(info.CertLegalPerson)); //联系人姓名
  47. contact_info.Add("id_card_number", RSAEncrypt(info.IdCardNumber)); //超级管理员身份证件号码
  48. contact_info.Add("contact_id_doc_type", "IDENTIFICATION_TYPE_IDCARD"); //联系人证件类型
  49. contact_info.Add("mobile", RSAEncrypt(info.MobilePhone)); //联系手机
  50. result.Add("contact_info", contact_info);
  51. //主体资料
  52. Dictionary<string, object> subject_info = new Dictionary<string, object>();
  53. string SubjectType = info.SubjectType;
  54. if (SubjectType == "SUBJECT_TYPE_SMALL") SubjectType = "SUBJECT_TYPE_MICRO";
  55. subject_info.Add("subject_type", SubjectType); //主体类型
  56. Dictionary<string, object> business_licence_info = new Dictionary<string, object>();
  57. string CertMerchantName = info.CertMerchantName;
  58. if (info.SubjectType == "SUBJECT_TYPE_SMALL")
  59. {
  60. info.LicenseCopy = info.IdCardCopy;
  61. for (int i = 0; i < 9; i++)
  62. {
  63. CertMerchantName = CertMerchantName.Replace(i.ToString(), "");
  64. }
  65. }
  66. if (info.SubjectType != "SUBJECT_TYPE_SMALL")
  67. {
  68. business_licence_info.Add("licence_number", info.LicenseNumber); //注册号/统一社会信用代码
  69. business_licence_info.Add("licence_copy", GetMediaId("/" + info.LicenseCopy)); //营业执照照片
  70. business_licence_info.Add("merchant_name", CertMerchantName); //商户名称
  71. business_licence_info.Add("legal_person", info.CertLegalPerson); //个体户经营者/法人姓名
  72. business_licence_info.Add("company_address", info.BizStoreAddress); //注册地址
  73. string PeriodEnd = info.PeriodEnd.Value.ToString("yyyy-MM-dd");
  74. // if (PeriodEnd.Substring(0, 4) == "2050")
  75. if (PeriodEnd.Substring(0, 4) == "9999")
  76. {
  77. // PeriodEnd = "forever";
  78. PeriodEnd = "长期";
  79. }
  80. business_licence_info.Add("licence_valid_date", "[\"" + info.PeriodBegin.Value.ToString("yyyy-MM-dd") + "\",\"" + PeriodEnd + "\"]"); //营业执照有效日期
  81. subject_info.Add("business_licence_info", business_licence_info); //营业执照
  82. }
  83. if (info.SubjectType == "SUBJECT_TYPE_SMALL")
  84. {
  85. Dictionary<string, object> assist_prove_info = new Dictionary<string, object>();
  86. string micro_biz_type = "MICRO_TYPE_STORE";
  87. var placeType = info.PlaceType; // 小微商户经营场所类型(0 固定场所-MICRO_TYPE_STORE 1 流动摊贩-MICRO_TYPE_MOBILE)
  88. if (placeType == 1)
  89. {
  90. micro_biz_type = "MICRO_TYPE_MOBILE";
  91. }
  92. assist_prove_info.Add("micro_biz_type", micro_biz_type); //小微经营类型
  93. assist_prove_info.Add("store_name", info.BizStoreName); //门店名称
  94. assist_prove_info.Add("store_address_code", info.AreaNo); //门店省市编码
  95. assist_prove_info.Add("store_address", info.BizStoreAddress); //门店地址
  96. assist_prove_info.Add("store_header_copy", GetMediaId("/" + info.StoreEntrancePic)); //门店门头照片
  97. assist_prove_info.Add("store_indoor_copy", GetMediaId("/" + info.IndoorPic)); //店内环境照片
  98. subject_info.Add("assist_prove_info", assist_prove_info); //辅助证明材料信息
  99. }
  100. result.Add("subject_info", subject_info);
  101. Dictionary<string, object> identification_info = new Dictionary<string, object>();
  102. identification_info.Add("id_holder_type", "LEGAL"); //证件持有人类型
  103. identification_info.Add("identification_type", "IDENTIFICATION_TYPE_IDCARD"); //证件类型
  104. identification_info.Add("identification_name", RSAEncrypt(info.CertLegalPerson)); //身份证姓名
  105. identification_info.Add("identification_number", RSAEncrypt(info.IdCardNumber)); //身份证号码
  106. string CardPeriodEnd = info.CardPeriodEnd.Value.ToString("yyyy-MM-dd");
  107. if (CardPeriodEnd.Substring(0, 4) == "2050")
  108. {
  109. CardPeriodEnd = "forever";
  110. // CardPeriodEnd = "长期";
  111. }
  112. identification_info.Add("identification_valid_date", "[\"" + info.CardPeriodBegin.Value.ToString("yyyy-MM-dd") + "\",\"" + CardPeriodEnd + "\"]"); //身份证有效期
  113. identification_info.Add("identification_front_copy", GetMediaId("/" + info.IdCardCopy)); //身份证件正面照片
  114. identification_info.Add("identification_back_copy", GetMediaId("/" + info.IdCardNational)); //身份证件反面照片
  115. bool owner = true;
  116. if (info.SubjectType == "SUBJECT_TYPE_ENTERPRISE")
  117. {
  118. identification_info.Add("identification_address", RSAEncrypt(info.IdCardAddress)); //身份证居住地址
  119. identification_info.Add("owner", owner);
  120. }
  121. result.Add("identification_info", identification_info); //经营者/法人身份证件
  122. //最终受益人信息列表(UBO)----仅企业需要填写
  123. if (info.SubjectType == "SUBJECT_TYPE_ENTERPRISE" && !owner)
  124. {
  125. List<Dictionary<string, object>> ubo_info_list = new List<Dictionary<string, object>>();
  126. Dictionary<string, object> ubo_info_list_item = new Dictionary<string, object>();
  127. ubo_info_list_item.Add("ubo_id_doc_type", "IDENTIFICATION_TYPE_IDCARD"); //证件类型
  128. ubo_info_list_item.Add("ubo_id_doc_copy", GetMediaId("/" + info.IdCardCopy)); //身份证件正面照片
  129. ubo_info_list_item.Add("ubo_id_doc_copy_back", GetMediaId("/" + info.IdCardNational)); //身份证件反面照片
  130. ubo_info_list_item.Add("ubo_id_doc_name", RSAEncrypt(info.CertLegalPerson)); //身份证姓名
  131. ubo_info_list_item.Add("ubo_id_doc_number", RSAEncrypt(info.IdCardNumber)); //身份证号码
  132. ubo_info_list_item.Add("ubo_id_doc_address", RSAEncrypt(info.IdCardAddress)); //身份证居住地址
  133. ubo_info_list_item.Add("ubo_period_begin", info.CardPeriodBegin.Value.ToString("yyyy-MM-dd")); //身份证有效期
  134. if (CardPeriodEnd == "forever")
  135. {
  136. CardPeriodEnd = "长期";
  137. }
  138. ubo_info_list_item.Add("ubo_period_end", CardPeriodEnd); //身份证有效期
  139. ubo_info_list.Add(ubo_info_list_item);
  140. result.Add("ubo_info_list", ubo_info_list);
  141. }
  142. dbpxc.Dispose();
  143. string req = Newtonsoft.Json.JsonConvert.SerializeObject(result);
  144. // 如何查看证书序列号?
  145. // 登陆商户平台【API安全】->【API证书】->【查看证书】,可查看商户API证书序列号。
  146. // 商户API证书和微信支付平台证书均可以使用第三方的证书解析工具,查看证书内容。或者使用openssl命令行工具查看证书序列号。
  147. // $ openssl x509 -in 1900009191_20180326_cert.pem -noout -serial
  148. // serial=1DDE55AD98ED71D6EDD4A4A16996DE7B47773A8C
  149. LogHelper.Instance.WriteLog(req, "间连商户开户意愿确认");
  150. string resp = postJson("https://api.mch.weixin.qq.com/v3/apply4subject/applyment", req);
  151. LogHelper.Instance.WriteLog(resp + "\n\n", "间连商户开户意愿确认");
  152. return resp;
  153. }
  154. #endregion
  155. #region 间连商户开户意愿确认(提交申请单)查询申请单状态
  156. public string QueryMerchant(string BusinessCode)
  157. {
  158. string result = "";
  159. try
  160. {
  161. result = postJson("https://api.mch.weixin.qq.com/v3/apply4subject/applyment?applyment_id=" + BusinessCode, "", "GET");
  162. //"{\"applyment_state\":\"APPLYMENT_STATE_REJECTED\",\"reject_param\":\"licence_valid_date|cert_valid_date\",\"reject_reason\":\"有效期开始日期填写有误,请填写与营业执照上一致的开始日期,如影印件上无开始日期请填写成立日期/注册日期;有效期结束日期填写有误,请填写与营业执照上一致的日期,如影印件上无结束日期请填写“长期”\"}"
  163. //{\"applyment_id\":2000002247709762,\"applyment_state\":\"APPLYMENT_STATE_FINISHED\",\"applyment_state_msg\":\"商户入驻申请已完成\",\"audit_detail\":[],\"business_code\":\"0123456789\",\"sign_url\":\"https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=gQFv7zwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyUXE1czkzb3JlUjIxZHpXbTF5Y2YAAgRjbe9hAwQAjScA\",\"sub_mchid\":\"1619775262\"}
  164. LogHelper.Instance.WriteLog(BusinessCode, "间连商户开户意愿确认(提交申请单)查询申请单状态-请求参数");
  165. LogHelper.Instance.WriteLog(result, "间连商户开户意愿确认(提交申请单)查询申请单状态");
  166. }
  167. catch (Exception ex)
  168. {
  169. LogHelper.Instance.WriteLog(DateTime.Now.ToString() + "\r\n" + ex.ToString(), "间连商户开户意愿确认(提交申请单)查询申请单状态异常");
  170. }
  171. return result;
  172. }
  173. #endregion
  174. #region 获取商户开户意愿确认状态
  175. public string QueryAuthMerchant(string MchId)
  176. {
  177. string result = "";
  178. try
  179. {
  180. result = postJson("https://api.mch.weixin.qq.com/v3/apply4subject/applyment/merchants/" + MchId + "/state", "", "GET");
  181. //{\"authorize_state\":\"AUTHORIZE_STATE_AUTHORIZED\"}
  182. LogHelper.Instance.WriteLog(MchId, "获取商户开户意愿确认状态");
  183. LogHelper.Instance.WriteLog(result, "获取商户开户意愿确认状态");
  184. }
  185. catch (Exception ex)
  186. {
  187. LogHelper.Instance.WriteLog(DateTime.Now.ToString() + "\r\n" + ex.ToString(), "获取商户开户意愿确认状态异常");
  188. }
  189. return result;
  190. }
  191. #endregion
  192. #region 获取平台证书
  193. public string GetPlatCert()
  194. {
  195. string merchantId = MchId; //商户号
  196. string result = postJson("https://api.mch.weixin.qq.com/v3/certificates", "", "GET");
  197. return result;
  198. }
  199. #endregion
  200. #region 敏感信息加密
  201. public string RSAEncrypt(string text)
  202. {
  203. byte[] publicKey = Convert.FromBase64String(pubkey);
  204. // var rsa = RSA.Create();
  205. // rsa.ImportRSAPublicKey(publicKey, out _);
  206. // var buff = rsa.Encrypt(Encoding.UTF8.GetBytes(text), RSAEncryptionPadding.OaepSHA1);
  207. // return Convert.ToBase64String(buff);
  208. using (var x509 = new X509Certificate2(publicKey))
  209. {
  210. using (var rsa = x509.GetRSAPublicKey())
  211. {
  212. var buff = rsa.Encrypt(Encoding.UTF8.GetBytes(text), RSAEncryptionPadding.OaepSHA1);
  213. return Convert.ToBase64String(buff);
  214. }
  215. }
  216. }
  217. // public string RSADecrypt(string text)
  218. // {
  219. // byte[] key = Encoding.UTF8.GetBytes(AppConfig.WeChatParam.AesGemKey);
  220. // byte[] nonce = Encoding.UTF8.GetBytes("1234567890ab");
  221. // byte[] ciphertext = Convert.FromBase64String(text);
  222. // AesGcm aes = new AesGcm(key);
  223. // byte[] plaintext = new byte[ciphertext.Length];
  224. // aes.Decrypt(nonce, ciphertext, plaintext, null);
  225. // return Encoding.UTF8.GetString(plaintext);
  226. // }
  227. public string AesGcmDecrypt(string associatedData, string nonce, string ciphertext)
  228. {
  229. // GcmBlockCipher gcmBlockCipher = new GcmBlockCipher(new AesEngine());
  230. // AeadParameters aeadParameters = new AeadParameters(
  231. // new KeyParameter(Encoding.UTF8.GetBytes(AppConfig.WeChatParam.AesGemKey)),
  232. // 128,
  233. // Encoding.UTF8.GetBytes(nonce),
  234. // Encoding.UTF8.GetBytes(associatedData));
  235. // gcmBlockCipher.Init(false, aeadParameters);
  236. // byte[] data = Convert.FromBase64String(ciphertext);
  237. // byte[] plaintext = new byte[gcmBlockCipher.GetOutputSize(data.Length)];
  238. // int length = gcmBlockCipher.ProcessBytes(data, 0, data.Length, plaintext, 0);
  239. // gcmBlockCipher.DoFinal(plaintext, length);
  240. // return Encoding.UTF8.GetString(plaintext);
  241. byte[] key = Encoding.UTF8.GetBytes(ApiKey); // 256-bit key
  242. byte[] nonceByte = Encoding.UTF8.GetBytes(nonce); // 96-bit nonce
  243. byte[] cipherByte = Convert.FromBase64String(ciphertext);
  244. byte[] associatedByte = Encoding.UTF8.GetBytes(associatedData);
  245. GcmBlockCipher cipher = new GcmBlockCipher(new AesEngine());
  246. AeadParameters parameters = new AeadParameters(new KeyParameter(key), 128, nonceByte, associatedByte);
  247. cipher.Init(false, parameters);
  248. byte[] plaintext = new byte[cipher.GetOutputSize(cipherByte.Length)];
  249. int len = cipher.ProcessBytes(cipherByte, 0, cipherByte.Length, plaintext, 0);
  250. cipher.DoFinal(plaintext, len);
  251. return Encoding.UTF8.GetString(plaintext);
  252. }
  253. public string postJson(string url, string postData, string method = "POST")
  254. {
  255. HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
  256. request.Method = method;
  257. request.ContentType = "application/json;charset=UTF-8";
  258. 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";
  259. request.Accept = "application/json";
  260. string Authorization = GetAuthorization(url, method, postData, prikey, MchId, serialNo);
  261. request.Headers.Add("Authorization", Authorization);
  262. request.Headers.Add("Wechatpay-Serial", getSerialNo);
  263. if (!string.IsNullOrEmpty(postData))
  264. {
  265. byte[] paramJsonBytes;
  266. paramJsonBytes = System.Text.Encoding.UTF8.GetBytes(postData);
  267. request.ContentLength = paramJsonBytes.Length;
  268. Stream writer;
  269. try
  270. {
  271. writer = request.GetRequestStream();
  272. }
  273. catch (Exception ex)
  274. {
  275. writer = null;
  276. LogHelper.Instance.WriteLog(DateTime.Now.ToString() + "\n" + ex.ToString(), "http请求异常");
  277. }
  278. writer.Write(paramJsonBytes, 0, paramJsonBytes.Length);
  279. writer.Close();
  280. }
  281. HttpWebResponse response;
  282. try
  283. {
  284. response = (HttpWebResponse)request.GetResponse();
  285. }
  286. catch (WebException ex)
  287. {
  288. response = ex.Response as HttpWebResponse;
  289. }
  290. Stream resStream = response.GetResponseStream();
  291. StreamReader reader = new StreamReader(resStream);
  292. string text = reader.ReadToEnd();
  293. return text;
  294. //{\"code\":\"PARAM_ERROR\",\"message\":\"请确认待处理的消息是否为加密后的密文\"}
  295. //{\"applyment_id\":2000002247709762}
  296. }
  297. #endregion
  298. #region 图片上传
  299. public string GetMediaId(string imgPath)
  300. {
  301. if (string.IsNullOrEmpty(imgPath))
  302. {
  303. return "";
  304. }
  305. if (imgPath.Contains(","))
  306. {
  307. imgPath = imgPath.Split(',')[0];
  308. }
  309. string key = "wechatpic:" + function.MD5_16(imgPath);
  310. string media_id = RedisDbconn.Instance.Get<string>(key);
  311. if (!string.IsNullOrEmpty(media_id))
  312. {
  313. return media_id;
  314. }
  315. string filePath = function.getPath(imgPath);
  316. var filename = Path.GetFileName(filePath);
  317. // FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
  318. // Byte[] imgBytesIn = new Byte[fs.Length];
  319. // fs.Read(imgBytesIn, 0, imgBytesIn.Length);
  320. // fs.Close();
  321. byte[] imgBytesIn = PublicFunction.GetNetFileData(AppConfig.Base.OssHost + imgPath);
  322. byte[] hash = SHA256Managed.Create().ComputeHash(imgBytesIn);
  323. StringBuilder builder = new StringBuilder();
  324. for (int i = 0; i < hash.Length; i++)
  325. {
  326. builder.Append(hash[i].ToString("x2"));
  327. }
  328. var sha256 = builder.ToString();
  329. string metaStr = "{\"filename\":\"" + filename + "\",\"sha256\":\"" + sha256 + "\"}";
  330. media_id = UploadImgApi(metaStr, imgBytesIn, filename);
  331. RedisDbconn.Instance.Set(key, media_id);
  332. return media_id;
  333. }
  334. public string UploadImgApi(string metaStr, Byte[] imgBytesIn, string filename)
  335. {
  336. string url = "https://api.mch.weixin.qq.com/v3/merchant/media/upload";
  337. string merchantId = MchId; //商户号
  338. string privateKey = prikey;
  339. #region 定义请求体中的内容 并转成二进制
  340. string boundary = "lc199aecd61b4653ef";
  341. string Enter = "\r\n";
  342. string campaignIDStr1
  343. = "--" + boundary
  344. + Enter
  345. + "Content-Disposition: form-data; name=\"meta\";"
  346. + Enter
  347. + "Content-Type:application/json;"
  348. + Enter
  349. + Enter
  350. + metaStr
  351. + Enter
  352. + "--" + boundary
  353. + Enter
  354. + "Content-Disposition:form-data;name=\"file\";filename=\"" + filename + "\";"
  355. + Enter
  356. + "Content-Type:image/jpeg"
  357. + Enter
  358. + Enter;
  359. byte[] byteData2
  360. = imgBytesIn;
  361. string campaignIDStr3
  362. = Enter
  363. + "--" + boundary
  364. + Enter;
  365. var byteData1 = System.Text.Encoding.UTF8.GetBytes(campaignIDStr1);
  366. var byteData3 = System.Text.Encoding.UTF8.GetBytes(campaignIDStr3);
  367. #endregion
  368. string transactionsResponse = UploadImg_postJson(url, byteData1, byteData2, byteData3, metaStr, privateKey, merchantId, serialNo, boundary, "POST");
  369. var result = JsonMapper.ToObject(transactionsResponse);
  370. return result["media_id"].ToString();
  371. }
  372. 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")
  373. {
  374. HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
  375. request.Method = method;
  376. //request.ContentType = "application/json;charset=UTF-8";
  377. request.ContentType = "multipart/form-data;boundary=" + boundary;
  378. 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";
  379. request.Accept = "application/json";
  380. string Authorization = GetAuthorization(url, method, metaStr, privateKey, merchantId, serialNo);
  381. request.Headers.Add("Authorization", Authorization);
  382. Stream writer;
  383. try
  384. {
  385. writer = request.GetRequestStream();
  386. }
  387. catch (Exception)
  388. {
  389. writer = null;
  390. }
  391. writer.Write(b1, 0, b1.Length);
  392. writer.Write(b2, 0, b2.Length);
  393. writer.Write(b3, 0, b3.Length);
  394. writer.Close();
  395. HttpWebResponse response;
  396. try
  397. {
  398. response = (HttpWebResponse)request.GetResponse();
  399. }
  400. catch (WebException ex)
  401. {
  402. response = ex.Response as HttpWebResponse;
  403. }
  404. Stream resStream = response.GetResponseStream();
  405. StreamReader reader = new StreamReader(resStream);
  406. string text = reader.ReadToEnd();
  407. return text;
  408. }
  409. protected string GetAuthorization(string url, string method, string jsonParame, string privateKey, string merchantId, string serialNo)
  410. {
  411. var uri = new Uri(url);
  412. string urlPath = uri.PathAndQuery;
  413. string nonce = Guid.NewGuid().ToString();
  414. var timestamp = DateTimeOffset.Now.ToUnixTimeSeconds();
  415. //数据签名 HTTP请求方法\n接口地址的url\n请求时间戳\n请求随机串\n请求报文主体\n
  416. method = string.IsNullOrEmpty(method) ? "" : method;
  417. string message = string.Format("{0}\n{1}\n{2}\n{3}\n{4}\n", method, urlPath, timestamp, nonce, jsonParame);
  418. string signTxt = Sign(message, privateKey);
  419. //Authorization和格式
  420. string authorzationTxt = string.Format("WECHATPAY2-SHA256-RSA2048 mchid=\"{0}\",nonce_str=\"{1}\",timestamp=\"{2}\",serial_no=\"{3}\",signature=\"{4}\"",
  421. merchantId,
  422. nonce,
  423. timestamp,
  424. serialNo,
  425. signTxt
  426. );
  427. return authorzationTxt;
  428. }
  429. protected string Sign(string message, string privateKey)
  430. {
  431. byte[] keyData = Convert.FromBase64String(privateKey);
  432. byte[] data = System.Text.Encoding.UTF8.GetBytes(message);
  433. var rsa = RSA.Create();
  434. rsa.ImportPkcs8PrivateKey(keyData, out _);
  435. return Convert.ToBase64String(rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
  436. // using (CngKey cngKey = CngKey.Import(keyData, CngKeyBlobFormat.Pkcs8PrivateBlob))
  437. // using (RSACng rsa = new RSACng(cngKey))
  438. // {
  439. // return Convert.ToBase64String(rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
  440. // }
  441. }
  442. #endregion
  443. #region 获取文件sha256
  444. public string GetSha256(FileStream stream)
  445. {
  446. using (SHA256 mySHA256 = SHA256.Create())
  447. {
  448. byte[] hashValue = mySHA256.ComputeHash(stream);
  449. return Encoding.UTF8.GetString(hashValue);
  450. }
  451. }
  452. #endregion
  453. #region 判断长期
  454. public string CheckForever(DateTime? time)
  455. {
  456. if (time == null)
  457. {
  458. return "";
  459. }
  460. if (time.Value.Year >= 2050)
  461. {
  462. return "长期";
  463. }
  464. return time.Value.ToString("yyyy-MM-dd");
  465. }
  466. #endregion
  467. }
  468. }