WeChatFunction.cs 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772
  1. using System;
  2. using System.Collections.Generic;
  3. using Library;
  4. using System.Security.Cryptography.X509Certificates;
  5. using System.Security.Cryptography;
  6. using Microsoft.AspNetCore.Http;
  7. using System.Text;
  8. using System.IO;
  9. using System.Linq;
  10. using MySystem.Models;
  11. using LitJson;
  12. using System.Net;
  13. using Org.BouncyCastle.Crypto.Modes;
  14. using Org.BouncyCastle.Crypto.Parameters;
  15. using Org.BouncyCastle.Crypto.Engines;
  16. namespace MySystem
  17. {
  18. public class WeChatFunction
  19. {
  20. private HttpContext _context;
  21. public WeChatFunction(HttpContext context)
  22. {
  23. _context = context;
  24. }
  25. #region 服务商平台商户进件提交申请单API
  26. public string MerchantCreate(MerchantAddInfo info, MerchantInfo merchant)
  27. {
  28. // pubkey = GetPublicKey();
  29. Dictionary<string, object> result = new Dictionary<string, object>();
  30. result.Add("business_code", info.BusinessCode); //业务申请编号
  31. //超级管理员信息
  32. Dictionary<string, object> contact_info = new Dictionary<string, object>();
  33. contact_info.Add("contact_name", RSAEncrypt(info.ContactName)); //超级管理员姓名
  34. contact_info.Add("contact_id_number", RSAEncrypt(info.ContactIdNumber)); //超级管理员身份证件号码
  35. // contact_info.Add("openid", info.OpenId); //超级管理员微信openid
  36. contact_info.Add("mobile_phone", RSAEncrypt(info.MobilePhone)); //联系手机
  37. contact_info.Add("contact_email", RSAEncrypt(info.ContactEmail)); //联系邮箱
  38. result.Add("contact_info", contact_info);
  39. //主体资料
  40. Dictionary<string, object> subject_info = new Dictionary<string, object>();
  41. subject_info.Add("subject_type", info.SubjectType); //主体类型
  42. Dictionary<string, object> business_license_info = new Dictionary<string, object>();
  43. business_license_info.Add("license_copy", GetMediaId(info.LicenseCopy)); //营业执照照片
  44. business_license_info.Add("license_number", info.LicenseNumber); //注册号/统一社会信用代码
  45. business_license_info.Add("merchant_name", merchant.Name); //商户名称
  46. business_license_info.Add("legal_person", info.LegalPerson); //个体户经营者/法人姓名
  47. subject_info.Add("business_license_info", business_license_info); //营业执照
  48. // Dictionary<string, object> certificate_info = new Dictionary<string, object>();
  49. // certificate_info.Add("cert_copy", GetMediaId(info.CertCopy)); //登记证书照片
  50. // certificate_info.Add("cert_type", info.CertType); //登记证书类型
  51. // certificate_info.Add("cert_number", info.CertNumber); //证书号
  52. // certificate_info.Add("merchant_name", info.CertMerchantName); //商户名称
  53. // certificate_info.Add("company_address", info.CompanyAddress); //注册地址
  54. // certificate_info.Add("legal_person", info.CertLegalPerson); //法人姓名
  55. // certificate_info.Add("period_begin", CheckForever(info.PeriodBegin)); //有效期限开始日期
  56. // certificate_info.Add("period_end", CheckForever(info.PeriodEnd)); //有效期限结束日期
  57. // subject_info.Add("certificate_info", certificate_info); //登记证书
  58. // Dictionary<string, object> organization_info = new Dictionary<string, object>();
  59. // organization_info.Add("organization_copy", GetMediaId(info.OrganizationCopy)); //组织机构代码证照片
  60. // organization_info.Add("organization_code", info.OrganizationCode); //组织机构代码
  61. // organization_info.Add("org_period_begin", CheckForever(info.OrgPeriodBegin)); //组织机构代码证有效期开始日期
  62. // organization_info.Add("org_period_end", CheckForever(info.OrgPeriodEnd)); //组织机构代码证有效期结束日期
  63. // subject_info.Add("organization_info", organization_info); //组织机构代码证
  64. // subject_info.Add("certificate_letter_copy", GetMediaId(info.CertificateLetterCopy)); //单位证明函照片
  65. Dictionary<string, object> identity_info = new Dictionary<string, object>();
  66. identity_info.Add("id_doc_type", info.IdDocType); //证件类型
  67. Dictionary<string, object> id_card_info = new Dictionary<string, object>();
  68. id_card_info.Add("id_card_copy", GetMediaId(info.IdCardCopy)); //身份证人像面照片
  69. id_card_info.Add("id_card_national", GetMediaId(info.IdCardNational)); //身份证人像面照片
  70. id_card_info.Add("id_card_name", RSAEncrypt(info.IdCardName)); //身份证姓名
  71. id_card_info.Add("id_card_number", RSAEncrypt(info.IdCardNumber)); //身份证号码
  72. id_card_info.Add("card_period_begin", CheckForever(info.CardPeriodBegin)); //身份证有效期开始时间
  73. id_card_info.Add("card_period_end", CheckForever(info.CardPeriodEnd)); //身份证有效期结束时间
  74. identity_info.Add("id_card_info", id_card_info); //身份证信息
  75. identity_info.Add("owner", info.Owner == 1 ? true : false); //经营者/法人是否为受益人
  76. subject_info.Add("identity_info", identity_info); //经营者/法人身份证件
  77. if (info.Owner == 0)
  78. {
  79. Dictionary<string, object> ubo_info = new Dictionary<string, object>();
  80. ubo_info.Add("id_type", info.UboInfoIdType); //证件类型
  81. ubo_info.Add("id_card_copy", GetMediaId(info.UboInfoIdCardCopy)); //身份证人像面照片
  82. ubo_info.Add("id_card_national", GetMediaId(info.UboInfoIdCardNational)); //身份证国徽面照片
  83. ubo_info.Add("id_doc_copy", GetMediaId(info.UboInfoIdDocCopy)); //证件照片
  84. ubo_info.Add("name", RSAEncrypt(info.UboInfoName)); //受益人姓名
  85. ubo_info.Add("id_number", RSAEncrypt(info.UboInfoIdNumber)); //证件号码
  86. ubo_info.Add("id_period_begin", CheckForever(info.UboInfoIdPeriodBegin)); //证件有效期开始时间
  87. ubo_info.Add("id_period_end", CheckForever(info.UboInfoIdPeriodEnd)); //证件有效期结束时间
  88. subject_info.Add("ubo_info", ubo_info); //最终受益人信息(UBO)
  89. }
  90. result.Add("subject_info", subject_info);
  91. //经营资料
  92. Dictionary<string, object> business_info = new Dictionary<string, object>();
  93. business_info.Add("merchant_shortname", info.MerchantShortname); //商户简称
  94. business_info.Add("service_phone", info.ServicePhone); //客服电话
  95. Dictionary<string, object> sales_info = new Dictionary<string, object>();
  96. sales_info.Add("sales_scenes_type", info.SalesScenesType.Split(',').ToList()); //经营场景类型
  97. Dictionary<string, object> biz_store_info = new Dictionary<string, object>();
  98. biz_store_info.Add("biz_store_name", info.BizStoreName); //门店名称
  99. biz_store_info.Add("biz_address_code", info.BizAddressCode); //门店省市编码
  100. biz_store_info.Add("biz_store_address", info.BizStoreAddress); //门店地址
  101. List<string> store_entrance_pic = new List<string>();
  102. store_entrance_pic.Add(GetMediaId(info.StoreEntrancePic));
  103. biz_store_info.Add("store_entrance_pic", store_entrance_pic); //门店门头照片
  104. List<string> indoor_pic = new List<string>();
  105. indoor_pic.Add(GetMediaId(info.IndoorPic));
  106. biz_store_info.Add("indoor_pic", indoor_pic); //店内环境照片
  107. biz_store_info.Add("biz_sub_appid", info.BizSubAppid); //线下场所对应的商家APPID
  108. sales_info.Add("biz_store_info", biz_store_info); //线下门店场景
  109. // Dictionary<string, object> mp_info = new Dictionary<string, object>();
  110. // mp_info.Add("mp_appid", info.MpAppid); //服务商公众号APPID
  111. // mp_info.Add("mp_sub_appid", info.MpSubAppid); //商家公众号APPID
  112. // mp_info.Add("mp_pics", GetMediaId(info.MpPics)); //公众号页面截图
  113. // sales_info.Add("mp_info", mp_info); //公众号场景
  114. // Dictionary<string, object> mini_program_info = new Dictionary<string, object>();
  115. // mini_program_info.Add("mini_program_appid", info.MiniProgramAppid); //服务商小程序APPID
  116. // mini_program_info.Add("mini_program_sub_appid", info.MiniProgramSubAppid); //商家小程序APPID
  117. // mini_program_info.Add("mini_program_pics", GetMediaId(info.MiniProgramPics)); //小程序截图
  118. // sales_info.Add("mini_program_info", mini_program_info); //小程序场景
  119. // Dictionary<string, object> app_info = new Dictionary<string, object>();
  120. // app_info.Add("app_appid", info.AppAppid); //服务商应用APPID
  121. // app_info.Add("app_sub_appid", info.AppSubAppid); //商家应用APPID
  122. // app_info.Add("app_pics", GetMediaId(info.AppPics)); //商家应用APPID
  123. // sales_info.Add("app_info", app_info); //APP场景
  124. // Dictionary<string, object> web_info = new Dictionary<string, object>();
  125. // web_info.Add("domain", info.WebDomain); //互联网网站域名
  126. // web_info.Add("web_authorisation", GetMediaId(info.WebAuthorisation)); //网站授权函
  127. // web_info.Add("web_appid", info.WebAppId); //互联网网站对应的商家APPID
  128. // sales_info.Add("web_info", web_info); //互联网网站场景
  129. // Dictionary<string, object> wework_info = new Dictionary<string, object>();
  130. // wework_info.Add("sub_corp_id", info.SubCorpId); //商家企业微信CorpID
  131. // wework_info.Add("wework_pics", GetMediaId(info.WeworkPics)); //企业微信页面截图
  132. // sales_info.Add("wework_info", wework_info); //企业微信场景
  133. business_info.Add("sales_info", sales_info); //经营场景
  134. result.Add("business_info", business_info);
  135. //结算规则
  136. Dictionary<string, object> settlement_info = new Dictionary<string, object>();
  137. settlement_info.Add("settlement_id", info.SettlementId); //入驻结算规则ID
  138. settlement_info.Add("qualification_type", info.QualificationType); //所属行业
  139. List<string> Qualifications = new List<string>();
  140. Qualifications.Add(GetMediaId(info.Qualifications));
  141. settlement_info.Add("qualifications", Qualifications); //特殊资质图片
  142. settlement_info.Add("activities_id", info.ActivitiesId); //优惠费率活动ID
  143. settlement_info.Add("activities_rate", info.ActivitiesRate); //优惠费率活动值
  144. result.Add("settlement_info", settlement_info);
  145. //结算银行账户
  146. Dictionary<string, object> bank_account_info = new Dictionary<string, object>();
  147. bank_account_info.Add("bank_account_type", info.BankAccountType); //账户类型
  148. bank_account_info.Add("account_name", RSAEncrypt(info.AccountName)); //开户名称
  149. bank_account_info.Add("account_bank", info.AccountBank); //开户银行
  150. bank_account_info.Add("bank_address_code", info.BankAddressCode); //开户银行省市编码
  151. bank_account_info.Add("bank_branch_id", info.BankBranchId); //开户银行联行号
  152. bank_account_info.Add("bank_name", info.BankName); //开户银行全称(含支行)
  153. bank_account_info.Add("account_number", RSAEncrypt(info.AccountNumber)); //银行账号
  154. result.Add("bank_account_info", bank_account_info);
  155. string req = Newtonsoft.Json.JsonConvert.SerializeObject(result);
  156. Dictionary<string, string> header = new Dictionary<string, string>();
  157. // 如何查看证书序列号?
  158. // 登陆商户平台【API安全】->【API证书】->【查看证书】,可查看商户API证书序列号。
  159. // 商户API证书和微信支付平台证书均可以使用第三方的证书解析工具,查看证书内容。或者使用openssl命令行工具查看证书序列号。
  160. // $ openssl x509 -in 1900009191_20180326_cert.pem -noout -serial
  161. // serial=1DDE55AD98ED71D6EDD4A4A16996DE7B47773A8C
  162. string merchantId = "1611167423"; //商户号
  163. string serialNo = "62B64854B768D344249FDB9E6EF4A1232C000E84"; //证书编号
  164. string resp = postJson("https://api.mch.weixin.qq.com/v3/applyment4sub/applyment/", req, prikey, merchantId, serialNo);
  165. return resp;
  166. }
  167. #endregion
  168. #region 服务商平台查询申请单状态API
  169. public Dictionary<string, object> QueryMerchant(string BusinessCode)
  170. {
  171. Dictionary<string, object> return_result = new Dictionary<string, object>();
  172. try
  173. {
  174. string merchantId = "1611167423"; //商户号
  175. string serialNo = "62B64854B768D344249FDB9E6EF4A1232C000E84"; //证书编号
  176. string result = postJson("https://api.mch.weixin.qq.com/v3/applyment4sub/applyment/business_code/" + BusinessCode, "", prikey, merchantId, serialNo, "GET");
  177. //{\"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\"}
  178. JsonData jsonObj = JsonMapper.ToObject(result);
  179. return_result.Add("applyment_id", jsonObj["applyment_id"].ToString()); //微信支付申请单号
  180. return_result.Add("applyment_state", jsonObj["applyment_state"].ToString()); //申请单状态
  181. return_result.Add("applyment_state_msg", jsonObj["applyment_state_msg"].ToString()); //申请状态描述
  182. if (jsonObj["applyment_state"].ToString() == "APPLYMENT_STATE_REJECTED")
  183. {
  184. List<Dictionary<string, string>> audit_detail = new List<Dictionary<string, string>>();
  185. JsonData auditObj = jsonObj["audit_detail"]; //驳回原因详情
  186. for (int i = 0; i < auditObj.Count; i++)
  187. {
  188. Dictionary<string, string> row = new Dictionary<string, string>();
  189. row.Add("field", auditObj[i]["field"].ToString()); //字段名
  190. row.Add("field_name", auditObj[i]["field_name"].ToString()); //字段名称
  191. row.Add("reject_reason", auditObj[i]["reject_reason"].ToString()); //驳回原因
  192. audit_detail.Add(row);
  193. }
  194. return_result.Add("audit_detail", audit_detail); //申请状态描述
  195. }
  196. if (result.Contains("\"sign_url\":"))
  197. {
  198. return_result.Add("sign_url", jsonObj["sign_url"].ToString()); //进件通过申请,待商家签约的地址
  199. }
  200. }
  201. catch (Exception ex)
  202. {
  203. function.WriteLog(DateTime.Now.ToString() + "\r\n" + ex.ToString(), "服务商平台查询申请单状态API异常");
  204. }
  205. return return_result;
  206. }
  207. #endregion
  208. #region 创建会员卡
  209. public string CardCreate(UserCardForWeChat card)
  210. {
  211. string token = new WeChat.WeChatPublicClass(_context).getWXToken("wx8e980f3614b8ee6d", "8ca8ccaaa8d27b30efcc775eb47c3b95");
  212. Dictionary<string, object> result = new Dictionary<string, object>();
  213. Dictionary<string, object> root = new Dictionary<string, object>();
  214. root.Add("card_type", card.CardType); //会员卡类型
  215. Dictionary<string, object> member_card = new Dictionary<string, object>();
  216. Dictionary<string, object> base_info = new Dictionary<string, object>();
  217. base_info.Add("logo_url", card.LogoUrl); //卡券的商户logo
  218. base_info.Add("code_type", card.CodeType); //Code展示类型
  219. base_info.Add("brand_name", card.BrandName); //商户名字
  220. base_info.Add("title", card.Title); //卡券名
  221. base_info.Add("color", card.Color); //券颜色。按色彩规范标注填写Color010-Color100
  222. base_info.Add("notice", card.Notice); //卡券使用提醒
  223. base_info.Add("description", card.Description); //卡券使用说明
  224. Dictionary<string, object> sku = new Dictionary<string, object>();
  225. sku.Add("quantity", card.Quantity); //卡券库存的数量
  226. base_info.Add("sku", sku); //商品信息
  227. Dictionary<string, object> date_info = new Dictionary<string, object>();
  228. date_info.Add("type", card.DateType); //使用时间的类型
  229. base_info.Add("date_info", ""); //使用日期,有效期的信息
  230. member_card.Add("base_info", base_info); //会员卡特权说明
  231. root.Add("member_card", member_card);
  232. root.Add("prerogative", card.Prerogative); //基本的卡券数据
  233. root.Add("supply_bonus", card.SupplyBonus); //显示积分
  234. root.Add("supply_balance", card.SupplyBalance); //是否支持储值
  235. root.Add("name", card.EnterName); //入口名称
  236. root.Add("tips", card.EnterTips); //入口右侧提示语
  237. root.Add("url", card.EnterUrl); //入口跳转链接
  238. result.Add("card", root);
  239. string req = Newtonsoft.Json.JsonConvert.SerializeObject(result);
  240. string merchantId = "1611167423"; //商户号
  241. string serialNo = "62B64854B768D344249FDB9E6EF4A1232C000E84"; //证书编号
  242. string resp = postJson("https://api.weixin.qq.com/card/create?access_token=" + token, req, prikey, merchantId, serialNo);
  243. // string resp = function.PostWebRequest("https://api.weixin.qq.com/card/create?access_token=" + token, req, "application/json");
  244. return resp;
  245. }
  246. #endregion
  247. #region 服务商平台JSAPI下单
  248. public Dictionary<string, string> Pay(string AppId, string MchId, string SubMchId, decimal PayMoney, string OrderNo, string Description, string OpenId, string Key, string NotifyUrl)
  249. {
  250. Dictionary<string, string> return_result = new Dictionary<string, string>();
  251. int amount = (int)(PayMoney * 100);
  252. //具体请求参数
  253. SortedList<string, object> par = new SortedList<string, object>();
  254. par.Add("sp_appid", AppId); //服务商应用ID
  255. par.Add("sp_mchid", MchId); //服务商户号
  256. par.Add("sub_mchid", SubMchId); //子商户号
  257. par.Add("description", Description); //商品描述
  258. par.Add("out_trade_no", OrderNo); //商户订单号
  259. par.Add("notify_url", NotifyUrl); //服务商应用ID
  260. Dictionary<string, object> amountDic = new Dictionary<string, object>();
  261. amountDic.Add("total", amount); //总金额
  262. par.Add("amount", amountDic); //订单金额
  263. Dictionary<string, object> payer = new Dictionary<string, object>();
  264. payer.Add("sp_openid", OpenId); //用户在服务商appid下的唯一标识
  265. par.Add("payer", payer); //支付者
  266. string req = Newtonsoft.Json.JsonConvert.SerializeObject(par);
  267. try
  268. {
  269. string merchantId = "1611167423"; //商户号
  270. string serialNo = "62B64854B768D344249FDB9E6EF4A1232C000E84"; //证书编号
  271. string result = postJson("https://api.mch.weixin.qq.com/v3/pay/partner/transactions/jsapi", req, prikey, merchantId, serialNo);
  272. JsonData jsonObj = JsonMapper.ToObject(result);
  273. string timeStamp = function.ConvertDateTimeInt(DateTime.Now).ToString();
  274. string nonce_str = function.get_Random(12);
  275. string package = "prepay_id=" + jsonObj["prepay_id"].ToString();
  276. var pay_param = new SortedList<string, string>
  277. {
  278. {"appId", AppId},
  279. {"timeStamp", timeStamp},
  280. {"nonceStr", nonce_str},
  281. {"package", package},
  282. {"signType", "MD5"}
  283. };
  284. var pay_param_str = String.Join("&", pay_param.Select(item => String.Format("{0}={1}", item.Key.Trim(), item.Value)).ToArray());
  285. var pay_param_str_sign = pay_param_str + "&key=" + Key;
  286. string paySign = function.MD532(pay_param_str_sign).ToUpper();
  287. return_result.Add("appId", AppId);
  288. return_result.Add("timeStamp", timeStamp);
  289. return_result.Add("nonce_str", nonce_str);
  290. return_result.Add("package", package);
  291. return_result.Add("paySign", paySign);
  292. }
  293. catch (Exception ex)
  294. {
  295. function.WriteLog(DateTime.Now.ToString() + "\r\n" + ex.ToString(), "服务商品台JSAPI下单异常");
  296. }
  297. return return_result;
  298. }
  299. #endregion
  300. #region 服务商平台申请退款API
  301. public Dictionary<string, string> Refund(string AppId, string MchId, string SubMchId, decimal RefundMoney, decimal TotalMoney, string OrderNo, string RefundNo, string Description, string OpenId, string Key, string NotifyUrl)
  302. {
  303. Dictionary<string, string> return_result = new Dictionary<string, string>();
  304. int refund = (int)(RefundMoney * 100);
  305. int amount = (int)(TotalMoney * 100);
  306. //具体请求参数
  307. SortedList<string, object> par = new SortedList<string, object>();
  308. par.Add("sub_mchid", SubMchId); //子商户号
  309. par.Add("out_trade_no", OrderNo); //商户订单号
  310. par.Add("out_refund_no", RefundNo); //商户退款单号
  311. Dictionary<string, object> amountDic = new Dictionary<string, object>();
  312. amountDic.Add("refund", refund); //退款金额
  313. amountDic.Add("total", amount); //原订单金额
  314. amountDic.Add("currency", "CNY"); //退款币种
  315. par.Add("amount", amountDic); //金额信息
  316. string req = Newtonsoft.Json.JsonConvert.SerializeObject(par);
  317. function.WriteLog(req, "服务商平台申请退款API");
  318. try
  319. {
  320. string merchantId = MchId; //商户号
  321. string serialNo = "62B64854B768D344249FDB9E6EF4A1232C000E84"; //证书编号
  322. string result = postJson("https://api.mch.weixin.qq.com/v3/refund/domestic/refunds", req, prikey, merchantId, serialNo);
  323. function.WriteLog(result, "服务商平台申请退款API");
  324. JsonData jsonObj = JsonMapper.ToObject(result);
  325. return_result.Add("refund_id", jsonObj["refund_id"].ToString()); //微信支付退款单号
  326. return_result.Add("channel", jsonObj["channel"].ToString()); //退款渠道
  327. return_result.Add("user_received_account", jsonObj["user_received_account"].ToString()); //退款入账账户
  328. return_result.Add("status", jsonObj["status"].ToString()); //退款状态
  329. return_result.Add("payer_total", jsonObj["amount"]["payer_total"].ToString()); //用户支付金额
  330. return_result.Add("payer_refund", jsonObj["amount"]["payer_refund"].ToString()); //用户退款金额
  331. return_result.Add("settlement_refund", jsonObj["amount"]["settlement_refund"].ToString()); //应结退款金额
  332. return_result.Add("settlement_total", jsonObj["amount"]["settlement_total"].ToString()); //应结订单金额
  333. return_result.Add("discount_refund", jsonObj["amount"]["discount_refund"].ToString()); //优惠退款金额
  334. }
  335. catch (Exception ex)
  336. {
  337. function.WriteLog(DateTime.Now.ToString() + "\r\n" + ex.ToString(), "服务商平台申请退款API异常");
  338. }
  339. return return_result;
  340. }
  341. #endregion
  342. #region 服务商平台查询单笔退款API
  343. public Dictionary<string, string> QueryRefund(string RefundNo)
  344. {
  345. Dictionary<string, string> return_result = new Dictionary<string, string>();
  346. try
  347. {
  348. string result = function.GetWebRequest("https://api.mch.weixin.qq.com/v3/refund/domestic/refunds/" + RefundNo);
  349. JsonData jsonObj = JsonMapper.ToObject(result);
  350. return_result.Add("refund_id", jsonObj["refund_id"].ToString()); //微信支付退款单号
  351. return_result.Add("transaction_id", jsonObj["transaction_id"].ToString()); //微信支付订单号
  352. return_result.Add("out_trade_no", jsonObj["out_trade_no"].ToString()); //商户订单号
  353. return_result.Add("channel", jsonObj["channel"].ToString()); //退款渠道
  354. return_result.Add("user_received_account", jsonObj["user_received_account"].ToString()); //退款入账账户
  355. return_result.Add("status", jsonObj["status"].ToString()); //退款状态
  356. return_result.Add("total", jsonObj["amount"]["total"].ToString()); //订单金额
  357. return_result.Add("refund", jsonObj["amount"]["refund"].ToString()); //退款金额
  358. return_result.Add("payer_total", jsonObj["amount"]["payer_total"].ToString()); //用户支付金额
  359. return_result.Add("payer_refund", jsonObj["amount"]["payer_refund"].ToString()); //用户退款金额
  360. return_result.Add("settlement_refund", jsonObj["amount"]["settlement_refund"].ToString()); //应结退款金额
  361. return_result.Add("settlement_total", jsonObj["amount"]["settlement_total"].ToString()); //应结订单金额
  362. return_result.Add("discount_refund", jsonObj["amount"]["discount_refund"].ToString()); //优惠退款金额
  363. }
  364. catch (Exception ex)
  365. {
  366. function.WriteLog(DateTime.Now.ToString() + "\r\n" + ex.ToString(), "服务商平台查询单笔退款API异常");
  367. }
  368. return return_result;
  369. }
  370. #endregion
  371. #region 服务商平台请求分账API
  372. public string ProfitShare(string SubMchId, string AppId, string TradeNo, string OrderNo, ReceiverList Receivers)
  373. {
  374. Dictionary<string, object> result = new Dictionary<string, object>();
  375. result.Add("sub_mchid", SubMchId); //子商户号
  376. result.Add("appid", AppId); //应用ID
  377. result.Add("transaction_id", TradeNo); //微信订单号
  378. result.Add("out_order_no", OrderNo); //商户分账单号
  379. result.Add("receivers", Receivers); //分账接收方列表
  380. result.Add("unfreeze_unsplit", true); //是否解冻剩余未分资金
  381. string req = Newtonsoft.Json.JsonConvert.SerializeObject(result);
  382. string resp = function.PostWebRequest("https://api.mch.weixin.qq.com/v3/profitsharing/orders", req, "application/json");
  383. return resp;
  384. }
  385. #endregion
  386. #region 服务商平台查询分账结果API
  387. public string QueryProfitShare(string SubMchId, string TradeNo, string OrderNo)
  388. {
  389. string resp = function.GetWebRequest("https://api.mch.weixin.qq.com/v3/profitsharing/orders/" + OrderNo + "?sub_mchid=" + SubMchId + "&transaction_id=" + TradeNo);
  390. return resp;
  391. }
  392. #endregion
  393. #region 服务商平台解冻剩余资金API
  394. public string Unfreeze(string SubMchId, string TradeNo, string OrderNo, string Description)
  395. {
  396. Dictionary<string, object> result = new Dictionary<string, object>();
  397. result.Add("sub_mchid", SubMchId); //子商户号
  398. result.Add("transaction_id", TradeNo); //微信订单号
  399. result.Add("out_order_no", OrderNo); //商户分账单号
  400. result.Add("description", Description); //分账描述
  401. string req = Newtonsoft.Json.JsonConvert.SerializeObject(result);
  402. string resp = function.PostWebRequest("https://api.mch.weixin.qq.com/v3/profitsharing/orders/unfreeze", req, "application/json");
  403. return resp;
  404. }
  405. #endregion
  406. #region 微信客服
  407. public string CustomerServiceChat()
  408. {
  409. return "需要对接";
  410. }
  411. #endregion
  412. #region 获取平台证书
  413. public string GetPlatCert()
  414. {
  415. string merchantId = "1611167423"; //商户号
  416. string serialNo = "62B64854B768D344249FDB9E6EF4A1232C000E84"; //证书编号
  417. string result = postJson("https://api.mch.weixin.qq.com/v3/certificates", "", prikey, merchantId, serialNo, "GET");
  418. return result;
  419. //{"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"}]}
  420. }
  421. public string AesGcmDecrypt(string associatedData, string nonce, string ciphertext)
  422. {
  423. GcmBlockCipher gcmBlockCipher = new GcmBlockCipher(new AesEngine());
  424. AeadParameters aeadParameters = new AeadParameters(
  425. new KeyParameter(Encoding.UTF8.GetBytes("VyULlqfAW2gBfCNfLdupcL7zlha7d93F")),
  426. 128,
  427. Encoding.UTF8.GetBytes(nonce),
  428. Encoding.UTF8.GetBytes(associatedData));
  429. gcmBlockCipher.Init(false, aeadParameters);
  430. byte[] data = Convert.FromBase64String(ciphertext);
  431. byte[] plaintext = new byte[gcmBlockCipher.GetOutputSize(data.Length)];
  432. int length = gcmBlockCipher.ProcessBytes(data, 0, data.Length, plaintext, 0);
  433. gcmBlockCipher.DoFinal(plaintext, length);
  434. return Encoding.UTF8.GetString(plaintext);
  435. }
  436. public string GetPublicKey()
  437. {
  438. var result = Newtonsoft.Json.JsonConvert.DeserializeObject<certModel>(GetPlatCert());
  439. var cmodel = result.data.OrderByDescending(t => t.expire_time).FirstOrDefault();
  440. string pubkey = AesGcmDecrypt(cmodel.encrypt_certificate.associated_data, cmodel.encrypt_certificate.nonce, cmodel.encrypt_certificate.ciphertext);
  441. pubkey = pubkey.Replace("-----BEGIN CERTIFICATE-----", "").Replace("-----END CERTIFICATE-----", "").Replace("\n", "");
  442. return pubkey;
  443. }
  444. #endregion
  445. #region 敏感信息加密
  446. // string pubkey = "MIIBCgKCAQEAxK9K2ElQ0rUMwNFW4xMx7kmkpDlp7WGQ8VffXLpudJBIrRVFWJN7dlinCGu67ZATf+/GZvLSSzQPWejHEsI9vUp9ej0x5iZDHGc9/shNUjd03ORkKo/Ohj3Ju19RzX4mh+GoinKGiuKX8CdGPXPe7UObKWyETrDcxrit6VCJQjE604aNtVeAUE+41mOpCLGzTgAKt4psfHxsBRtqlveH4cH/51ip+cGkC/u36gfDMKaRluVfFO3ETxDkI94BwNtnthcA4WDKha+wjtB6HIJ5xxHV550+cfdkl4j8UKU6pB+C5JRNgvjAf6ljg/TF+cGF1d8C6IbYYodYKloqN2DzrwIDAQAB"; //公钥
  447. string pubkey = "MIID3DCCAsSgAwIBAgIUU0FlQhvigU3sCPjQC9q5lEsTZGwwDQYJKoZIhvcNAQELBQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsTFFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3QgQ0EwHhcNMjEwNjMwMDMwOTA5WhcNMjYwNjI5MDMwOTA5WjBuMRgwFgYDVQQDDA9UZW5wYXkuY29tIHNpZ24xEzARBgNVBAoMClRlbnBheS5jb20xHTAbBgNVBAsMFFRlbnBheS5jb20gQ0EgQ2VudGVyMQswCQYDVQQGDAJDTjERMA8GA1UEBwwIU2hlblpoZW4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC64SIwN1afgge2pjFeNZAlKz5ZdJw8W/hisaIJnkzbE/1oG5n+SgtbMLfBLBFp0zMyT5SP5ve5aJAvUjwnRwQoDG+4z3jE8vLyjFLxoy5sWGex8+FBC5hs81oAUHuazigi5NcSH9Ji/8Lq3zFh8Az4+ZchQ14SFhSGTifSZfdTX5wYDEv3DKDYgQvvAgDgjBF1Uj91NpVD7ruQjAJ7MwZvUX7rnYFnQggFQwIBWazNXaGa7OpO6Xbf+uNtbl436My7WQX+ffjmtYmcgND60mgn/rFQMg5r+Q+J8mDgIaAzCmr3xW31OIvAD1iYV0ksTyQntD5pOzCYdHZPDOZCqYlHAgMBAAGjgYEwfzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIE8DBlBgNVHR8EXjBcMFqgWKBWhlRodHRwOi8vZXZjYS5pdHJ1cy5jb20uY24vcHVibGljL2l0cnVzY3JsP0NBPTFCRDQyMjBFNTBEQkMwNEIwNkFEMzk3NTQ5ODQ2QzAxQzNFOEVCRDIwDQYJKoZIhvcNAQELBQADggEBAEgXlFe4MpFUUnj6gJt5KoPpzLTNOXDHsglUrAobq/HlmDBOF8yCUFvtbRaJxUSQVFfo/2zag8J57YNMo2If1HkD1LMEGAcPGNS+aho9SgCFbLG+c82nNICl8g8oe1HNS7IpRjacSfrKIYt5VL5lHHC5ZJaKq0Ez9c7bfPGC6CaA8WDnApFZut5qhYNMBUYZZjAMVIZ2G/kIsxbo1oUpVEnQq5YQxPUDWdYKxdTvo7uXXpWv6qo761Hid24R7mdrGEuHZNBfxYCt1wJQNlcGVgCjk8PPo73mO0zYRwV0x7pNkFFbiP7aetf6RB82YUbuNkvql83Ox+e22ByMi8lOUZo=";
  448. 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"; //私钥
  449. public string RSAEncrypt(string text)
  450. {
  451. byte[] publicKey = Convert.FromBase64String(pubkey);
  452. // var rsa = RSA.Create();
  453. // rsa.ImportRSAPublicKey(publicKey, out _);
  454. // var buff = rsa.Encrypt(Encoding.UTF8.GetBytes(text), RSAEncryptionPadding.OaepSHA1);
  455. // return Convert.ToBase64String(buff);
  456. using (var x509 = new X509Certificate2(publicKey))
  457. {
  458. using (var rsa = x509.GetRSAPublicKey())
  459. {
  460. var buff = rsa.Encrypt(Encoding.UTF8.GetBytes(text), RSAEncryptionPadding.OaepSHA1);
  461. return Convert.ToBase64String(buff);
  462. }
  463. }
  464. }
  465. public string postJson(string url, string postData, string privateKey, string merchantId, string serialNo, string method = "POST")
  466. {
  467. HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
  468. request.Method = method;
  469. request.ContentType = "application/json;charset=UTF-8";
  470. 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";
  471. request.Accept = "application/json";
  472. string Authorization = GetAuthorization(url, method, postData, privateKey, merchantId, "62B64854B768D344249FDB9E6EF4A1232C000E84");
  473. request.Headers.Add("Authorization", Authorization);
  474. request.Headers.Add("Wechatpay-Serial", serialNo);
  475. if (!string.IsNullOrEmpty(postData))
  476. {
  477. byte[] paramJsonBytes;
  478. paramJsonBytes = System.Text.Encoding.UTF8.GetBytes(postData);
  479. request.ContentLength = paramJsonBytes.Length;
  480. Stream writer;
  481. try
  482. {
  483. writer = request.GetRequestStream();
  484. }
  485. catch (Exception)
  486. {
  487. writer = null;
  488. Console.Write("连接服务器失败!");
  489. }
  490. writer.Write(paramJsonBytes, 0, paramJsonBytes.Length);
  491. writer.Close();
  492. }
  493. HttpWebResponse response;
  494. try
  495. {
  496. response = (HttpWebResponse)request.GetResponse();
  497. }
  498. catch (WebException ex)
  499. {
  500. response = ex.Response as HttpWebResponse;
  501. }
  502. Stream resStream = response.GetResponseStream();
  503. StreamReader reader = new StreamReader(resStream);
  504. string text = reader.ReadToEnd();
  505. return text;
  506. //{\"code\":\"PARAM_ERROR\",\"message\":\"请确认待处理的消息是否为加密后的密文\"}
  507. //{\"applyment_id\":2000002247709762}
  508. }
  509. #endregion
  510. #region 图片上传
  511. public string GetMediaId(string imgPath)
  512. {
  513. if (string.IsNullOrEmpty(imgPath))
  514. {
  515. return "";
  516. }
  517. string key = "wechatpic:" + function.MD5_16(imgPath);
  518. string media_id = RedisDbconn.Instance.Get<string>(key);
  519. if (!string.IsNullOrEmpty(media_id))
  520. {
  521. return media_id;
  522. }
  523. string filePath = function.getPath(imgPath);
  524. var filename = Path.GetFileName(filePath);
  525. FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
  526. Byte[] imgBytesIn = new Byte[fs.Length];
  527. fs.Read(imgBytesIn, 0, imgBytesIn.Length);
  528. fs.Close();
  529. byte[] hash = SHA256Managed.Create().ComputeHash(imgBytesIn);
  530. StringBuilder builder = new StringBuilder();
  531. for (int i = 0; i < hash.Length; i++)
  532. {
  533. builder.Append(hash[i].ToString("x2"));
  534. }
  535. var sha256 = builder.ToString();
  536. string metaStr = "{\"filename\":\""+ filename + "\",\"sha256\":\"" + sha256 + "\"}";
  537. media_id = UploadImgApi(metaStr, imgBytesIn, filename);
  538. RedisDbconn.Instance.Set(key, media_id);
  539. return media_id;
  540. }
  541. public string UploadImgApi(string metaStr, Byte[] imgBytesIn,string filename)
  542. {
  543. string url = "https://api.mch.weixin.qq.com/v3/merchant/media/upload";
  544. string merchantId = "1611167423"; //商户号
  545. string serialNo = "62B64854B768D344249FDB9E6EF4A1232C000E84"; //证书编号
  546. string privateKey = prikey;
  547. #region 定义请求体中的内容 并转成二进制
  548. string boundary = "lc199aecd61b4653ef";
  549. string Enter = "\r\n";
  550. string campaignIDStr1
  551. = "--" + boundary
  552. + Enter
  553. + "Content-Disposition: form-data; name=\"meta\";"
  554. + Enter
  555. + "Content-Type:application/json;"
  556. + Enter
  557. + Enter
  558. + metaStr
  559. + Enter
  560. + "--" + boundary
  561. + Enter
  562. + "Content-Disposition:form-data;name=\"file\";filename=\""+ filename + "\";"
  563. + Enter
  564. + "Content-Type:image/jpeg"
  565. + Enter
  566. + Enter;
  567. byte[] byteData2
  568. = imgBytesIn;
  569. string campaignIDStr3
  570. = Enter
  571. + "--" + boundary
  572. + Enter;
  573. var byteData1 = System.Text.Encoding.UTF8.GetBytes(campaignIDStr1);
  574. var byteData3 = System.Text.Encoding.UTF8.GetBytes(campaignIDStr3);
  575. #endregion
  576. string transactionsResponse = UploadImg_postJson(url, byteData1, byteData2, byteData3, metaStr, privateKey, merchantId, serialNo, boundary, "POST");
  577. var result=JsonMapper.ToObject(transactionsResponse);
  578. return result["media_id"].ToString();
  579. }
  580. 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")
  581. {
  582. HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
  583. request.Method = method;
  584. //request.ContentType = "application/json;charset=UTF-8";
  585. request.ContentType = "multipart/form-data;boundary=" + boundary;
  586. 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";
  587. request.Accept = "application/json";
  588. string Authorization = GetAuthorization(url, method, metaStr, privateKey, merchantId, serialNo);
  589. request.Headers.Add("Authorization", Authorization);
  590. Stream writer;
  591. try
  592. {
  593. writer = request.GetRequestStream();
  594. }
  595. catch (Exception)
  596. {
  597. writer = null;
  598. }
  599. writer.Write(b1, 0, b1.Length);
  600. writer.Write(b2, 0, b2.Length);
  601. writer.Write(b3, 0, b3.Length);
  602. writer.Close();
  603. HttpWebResponse response;
  604. try
  605. {
  606. response = (HttpWebResponse)request.GetResponse();
  607. }
  608. catch (WebException ex)
  609. {
  610. response = ex.Response as HttpWebResponse;
  611. }
  612. Stream resStream = response.GetResponseStream();
  613. StreamReader reader = new StreamReader(resStream);
  614. string text = reader.ReadToEnd();
  615. return text;
  616. }
  617. protected string GetAuthorization(string url, string method, string jsonParame, string privateKey, string merchantId, string serialNo)
  618. {
  619. var uri = new Uri(url);
  620. string urlPath = uri.PathAndQuery;
  621. string nonce = Guid.NewGuid().ToString();
  622. var timestamp = DateTimeOffset.Now.ToUnixTimeSeconds();
  623. //数据签名 HTTP请求方法\n接口地址的url\n请求时间戳\n请求随机串\n请求报文主体\n
  624. method = string.IsNullOrEmpty(method) ? "" : method;
  625. string message = string.Format("{0}\n{1}\n{2}\n{3}\n{4}\n", method, urlPath, timestamp, nonce, jsonParame);
  626. string signTxt = Sign(message, privateKey);
  627. //Authorization和格式
  628. string authorzationTxt = string.Format("WECHATPAY2-SHA256-RSA2048 mchid=\"{0}\",nonce_str=\"{1}\",timestamp=\"{2}\",serial_no=\"{3}\",signature=\"{4}\"",
  629. merchantId,
  630. nonce,
  631. timestamp,
  632. serialNo,
  633. signTxt
  634. );
  635. return authorzationTxt;
  636. }
  637. protected string Sign(string message, string privateKey)
  638. {
  639. byte[] keyData = Convert.FromBase64String(privateKey);
  640. byte[] data = System.Text.Encoding.UTF8.GetBytes(message);
  641. var rsa = RSA.Create();
  642. rsa.ImportPkcs8PrivateKey(keyData, out _);
  643. return Convert.ToBase64String(rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
  644. // using (CngKey cngKey = CngKey.Import(keyData, CngKeyBlobFormat.Pkcs8PrivateBlob))
  645. // using (RSACng rsa = new RSACng(cngKey))
  646. // {
  647. // return Convert.ToBase64String(rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
  648. // }
  649. }
  650. #endregion
  651. #region 获取文件sha256
  652. public string GetSha256(FileStream stream)
  653. {
  654. using (SHA256 mySHA256 = SHA256.Create())
  655. {
  656. byte[] hashValue = mySHA256.ComputeHash(stream);
  657. return Encoding.UTF8.GetString(hashValue);
  658. }
  659. }
  660. #endregion
  661. #region 判断长期
  662. public string CheckForever(DateTime? time)
  663. {
  664. if (time == null)
  665. {
  666. return "";
  667. }
  668. if (time.Value.Year >= 2050)
  669. {
  670. return "长期";
  671. }
  672. return time.Value.ToString("yyyy-MM-dd");
  673. }
  674. #endregion
  675. }
  676. }