123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520 |
- using System;
- using System.Collections.Generic;
- using System.Drawing.Imaging;
- using System.IO;
- using System.Linq;
- using System.Text;
- using System.Web;
- using System.Web.Mvc;
- using Autofac;
- using EMIS.Utility;
- using EMIS.ViewModel;
- using EMIS.Utility.OnlinePay.WeChat;
- using Senparc.Weixin;
- using Senparc.Weixin.MP;
- using Senparc.Weixin.MP.Entities.Request;
- using Senparc.Weixin.MP.MvcExtension;
- using Senparc.Weixin.TenPay;
- using Senparc.Weixin.TenPay.V3;
- using Senparc.Weixin.MP.Containers;
- using Senparc.Weixin.MP.AdvancedAPIs;
- using System.Configuration;
- using Senparc.Weixin.MP.Helpers;
- using System.Xml.Linq;
- using EMIS.ViewModel.WechatModel;
- using Bowin.Common.Log;
- namespace EMIS.Utility.OnlinePay
- {
- public class WechatHelper
- {
- private static readonly string Token = Config.SenparcWeixinSetting.Token == null ? ConfigurationManager.AppSettings["WeixinToken"] : Config.SenparcWeixinSetting.Token;//与微信公众账号后台的Token设置保持一致,区分大小写。
- private static readonly string EncodingAESKey = Config.SenparcWeixinSetting.EncodingAESKey == null ? ConfigurationManager.AppSettings["WeixinEncodingAESKey"] : Config.SenparcWeixinSetting.EncodingAESKey;//与微信公众账号后台的EncodingAESKey设置保持一致,区分大小写。
- private static readonly string AppId = Config.SenparcWeixinSetting.WeixinAppId == null ? ConfigurationManager.AppSettings["WeixinAppId"] : Config.SenparcWeixinSetting.WeixinAppId;//与微信公众账号后台的AppId设
- private static readonly string TenPayV3_MchId = Config.SenparcWeixinSetting.TenPayV3_MchId == null ? ConfigurationManager.AppSettings["TenPayV3_MchId"] : Config.SenparcWeixinSetting.TenPayV3_MchId;
- private static readonly string TenPayV3_Key = Config.SenparcWeixinSetting.TenPayV3_Key == null ? ConfigurationManager.AppSettings["TenPayV3_Key"] : Config.SenparcWeixinSetting.TenPayV3_Key;
- private static readonly string TenPayV3_AppId = Config.SenparcWeixinSetting.TenPayV3_AppId == null ? ConfigurationManager.AppSettings["TenPayV3_AppId"] : Config.SenparcWeixinSetting.TenPayV3_AppId;
- private static readonly string TenPayV3_AppSecret = Config.SenparcWeixinSetting.TenPayV3_AppSecret == null ? ConfigurationManager.AppSettings["TenPayV3_AppSecret"] : Config.SenparcWeixinSetting.TenPayV3_AppSecret;
- private static readonly string TenPayV3_TenpayNotify = Config.SenparcWeixinSetting.TenPayV3_TenpayNotify == null ? ConfigurationManager.AppSettings["TenPayV3_TenpayNotify"] : Config.SenparcWeixinSetting.TenPayV3_TenpayNotify;
- private static readonly string TenPayV3_RefundNotify = ConfigurationManager.AppSettings["TenPayV3_RefundNotify"];
- #region 公众号基础处理
- public static ActionResult EventHandler(PostModel postModel, string echostr)
- {
- if (CheckSignature.Check(postModel.Signature, postModel.Timestamp, postModel.Nonce, Token))
- {
- return new ContentResult() { Content = echostr }; //返回随机字符串则表示验证通过
- }
- else
- {
- return new ContentResult()
- {
- Content = "failed:" + postModel.Signature + "," + Senparc.Weixin.MP.CheckSignature.GetSignature(postModel.Timestamp, postModel.Nonce, Token) + "。" +
- "如果你在浏览器中看到这句话,说明此地址可以被作为微信公众账号后台的Url,请注意保持Token一致。"
- };
- }
- }
- public static ActionResult PostEventHandler(PostModel postModel)
- {
- if (!CheckSignature.Check(postModel.Signature, postModel.Timestamp, postModel.Nonce, Token))
- {
- return new ContentResult() { Content = "参数错误!" };
- }
- postModel.Token = Token;//根据自己后台的设置保持一致
- postModel.EncodingAESKey = EncodingAESKey;//根据自己后台的设置保持一致
- postModel.AppId = AppId;//根据自己后台的设置保持一致
- //自定义MessageHandler,对微信请求的详细判断操作都在这里面。
- var messageHandler = new CustomMessageHandler(HttpContext.Current.Request.InputStream, postModel);//接收消息
- messageHandler.Execute();//执行微信处理过程
- return new FixWeixinBugWeixinResult(messageHandler);//返回结果
- }
- public static void SendAnnouncement(string title, string content, IList<string> openIDList, string examinationProjectName = null, DateTime? startTime = null)
- {
- if (openIDList.Count > 0)
- {
- var templateID = ConfigurationManager.AppSettings["WxMp_NoticeTemplateID"];
- var result = AccessTokenContainer.TryGetAccessToken(Config.SenparcWeixinSetting.WeixinAppId, Config.SenparcWeixinSetting.WeixinAppSecret);
- foreach (var openID in openIDList)
- {
- if (openID != null && openID != "null")
- {
- TemplateApi.SendTemplateMessage(result, openID, templateID, null, new
- {
- first = new WxTemplateMessageData
- {
- value = (examinationProjectName != null ? examinationProjectName + "项目" : "") + "通知",
- color = "#FF0000"
- },
- remark = new WxTemplateMessageData
- {
- value = HttpUtility.HtmlDecode(content)
- },
- keyword1 = new WxTemplateMessageData
- {
- value = "广东岭南职业技术学院"
- },
- keyword2 = new WxTemplateMessageData
- {
- value = "鉴定中心"
- //startTime.HasValue ? startTime.Value.ToString("yyyy年MM月dd日 HH时mm分") : ""
- },
- keyword3 = new WxTemplateMessageData
- {
- value = startTime.HasValue ? startTime.Value.ToString("yyyy年MM月dd日 HH时mm分") : ""
- },
- keyword4 = new WxTemplateMessageData
- {
- value = title
- },
- });
- }
- }
- }
- }
- public static void SendAnnouncementGDCX(string title, string content,string userName, IList<string> openIDList, string examinationProjectName = null, DateTime? startTime = null)
- {
- if (openIDList.Count > 0)
- {
- var templateID = ConfigurationManager.AppSettings["WxMp_NoticeTemplateID"];
- var result = AccessTokenContainer.TryGetAccessToken(Config.SenparcWeixinSetting.WeixinAppId, Config.SenparcWeixinSetting.WeixinAppSecret);
- foreach (var openID in openIDList)
- {
- if (openID != null && openID != "null")
- {
- TemplateApi.SendTemplateMessage(result, openID, templateID, null, new
- {
- first = new WxTemplateMessageData
- {
- value = title,
- color = "#FF0000"
- },
-
- keyword1 = new WxTemplateMessageData
- {
- value = "广东创新科技职业学院"
- },
- keyword2 = new WxTemplateMessageData
- {
- value = "继续教育学院"
- //startTime.HasValue ? startTime.Value.ToString("yyyy年MM月dd日 HH时mm分") : ""
- },
- keyword3 = new WxTemplateMessageData
- {
- value = userName
- },
- keyword4 = new WxTemplateMessageData
- {
- value = startTime.HasValue ? startTime.Value.ToString("yyyy年MM月dd日 HH时mm分") : ""
- },
- remark = new WxTemplateMessageData
- {
- value = HttpUtility.HtmlDecode(content)
- },
- });
- }
- }
- }
- }
- public static JsSdkUiPackage GetJSConfigData(string url)
- {
- try
- {
- return JSSDKHelper.GetJsSdkUiPackage(TenPayV3_AppId, TenPayV3_AppSecret, url);
- }
- catch (Exception ex)
- {
- LogHelper.WriteLog(LogType.ServiceLog, ex.Message);
- throw;
- }
- }
- public static string GetBaseAuthorizeUrl(string url,string state = null)
- {
- var stateStr = "";
- if (state != null)
- {
- stateStr = state;
- }
- return OAuthApi.GetAuthorizeUrl(TenPayV3_AppId, url, stateStr, OAuthScope.snsapi_base) + "&v=" + DateTime.Now.ToFileTime().ToString();
- }
- public static string GetUserInfoAuthorizeUrl(string url,string state = null)
- {
- var stateStr = "";
- if (state != null)
- {
- stateStr = state;
- }
- return OAuthApi.GetAuthorizeUrl(TenPayV3_AppId, url, stateStr, OAuthScope.snsapi_userinfo) + "&v=" + DateTime.Now.ToFileTime().ToString();
- }
- public static string GetOpenID(string code)
- {
- return OAuthApi.GetAccessToken(TenPayV3_AppId, TenPayV3_AppSecret, code).openid;
- }
- public static string DownloadMedia(string mediaID)
- {
- var stream = new MemoryStream();
- try
- {
-
- MediaApi.Get(TenPayV3_AppId, mediaID, stream);
- return FileUploadHelper.UploadFile(stream, ".png");
- }
- catch (Exception)
- {
- throw;
- }
-
- }
- #endregion
- #region 支付
- public static FileContentResult GetPayQRCode(string productId, decimal fee, string feeTypeName, out string payUrl)
- {
- string timestamp = TenPayV3Util.GetTimestamp();
- string nonceString = TenPayV3Util.GetNoncestr();
- int intFee = Convert.ToInt32(Math.Round(fee * 100, 0));
- TenPayV3UnifiedorderRequestData orderData = new TenPayV3UnifiedorderRequestData(TenPayV3_AppId, TenPayV3_MchId, feeTypeName, productId, intFee, HttpContext.Current.Request.UserHostAddress,
- TenPayV3_TenpayNotify, Senparc.Weixin.TenPay.TenPayV3Type.NATIVE, null, TenPayV3_Key, nonceString);
- //TenPayV3UnifiedorderRequestData orderData = new TenPayV3UnifiedorderRequestData(TenPayV3_AppId, TenPayV3_MchId, feeTypeName, productId, 1, HttpContext.Current.Request.UserHostAddress,
- // TenPayV3_TenpayNotify, Senparc.Weixin.TenPay.TenPayV3Type.NATIVE, null, TenPayV3_Key, nonceString);
- UnifiedorderResult result = TenPayV3.Unifiedorder(orderData);
- if (result.return_code == "SUCCESS")
- {
- var memoryStream = new MemoryStream();
- var qrcodeImage = QRCodeHelper.GenerateQRCode(result.code_url);
- qrcodeImage.Save(memoryStream, ImageFormat.Png);
- payUrl = result.code_url;
- return new FileContentResult(memoryStream.GetBuffer(), "image/png");
- }
- else
- {
- throw new Exception("生成二维码失败:调用统一下单接口失败。");
- }
- }
- public static JSPayView JsPay(string productId, decimal fee, string feeTypeName, string openId)
- {
- var result = new JSPayView();
- result.AppID = TenPayV3_AppId;
- result.TimeStamp = TenPayV3Util.GetTimestamp();
- result.NonceStr = TenPayV3Util.GetNoncestr();
- int intFee = Convert.ToInt32(Math.Round(fee * 100, 0));
- TenPayV3UnifiedorderRequestData orderData = new TenPayV3UnifiedorderRequestData(TenPayV3_AppId, TenPayV3_MchId, feeTypeName, productId, intFee, HttpContext.Current.Request.UserHostAddress,
- TenPayV3_TenpayNotify, Senparc.Weixin.TenPay.TenPayV3Type.JSAPI, openId, TenPayV3_Key, result.NonceStr);
- UnifiedorderResult orderResult = TenPayV3.Unifiedorder(orderData);
- if (orderResult.return_code == "SUCCESS")
- {
- result.Package = "prepay_id=" + orderResult.prepay_id;
- result.PaySign = TenPayV3.GetJsPaySign(TenPayV3_AppId, result.TimeStamp, result.NonceStr, result.Package, TenPayV3_Key);
- }
- else
- {
- throw new Exception("支付失败:调用统一下单接口失败。" + orderResult.return_msg);
- }
- return result;
- }
- public static bool CloseOrder(string productId)
- {
- bool isOK = true;
- string timestamp = TenPayV3Util.GetTimestamp();
- string nonceString = TenPayV3Util.GetNoncestr();
- TenPayV3CloseOrderRequestData orderData = new TenPayV3CloseOrderRequestData(TenPayV3_AppId, TenPayV3_MchId, productId, TenPayV3_Key, nonceString);
- CloseOrderResult result = TenPayV3.CloseOrder(orderData);
- if (result.return_code != "SUCCESS")
- {
- isOK = false;
- //throw new Exception("关闭重复订单失败:" + result.return_msg);
- }
- else if (result.result_code != "SUCCESS")
- {
- isOK = false;
- //throw new Exception("关闭重复订单失败:" + result.result_msg);
- }
- return isOK;
- }
- /// <summary>
- /// 接收微信支付返回信息
- /// </summary>
- /// <returns></returns>
- public static PayNotifyView PayNotify()
- {
- ResponseHandler resHandler = new ResponseHandler(null);
- resHandler.Init();
- resHandler.SetKey(TenPayV3_Key);
- var response = HttpContext.Current.Response;
- response.Clear();
- //判断签名
- if (resHandler.IsTenpaySign())
- {
- PayNotifyView payNotifyView = new PayNotifyView();
- //商户在收到后台通知后根据通知ID向财付通发起验证确认,采用后台系统调用交互模式
- payNotifyView.NotifyID = resHandler.GetParameter("notify_id");
- //取结果参数做业务处理
- payNotifyView.OrderID = resHandler.GetParameter("out_trade_no");
- //财付通订单号
- payNotifyView.WechatOrderID = resHandler.GetParameter("transaction_id");
- //金额,以分为单位
- payNotifyView.TotalFee = resHandler.GetParameter("total_fee");
- //如果有使用折扣券,discount有值,total_fee+discount=原请求的total_fee
- payNotifyView.Discount = resHandler.GetParameter("discount");
- //支付结果
- payNotifyView.ResultCode = resHandler.GetParameter("result_code");
- //范例上有个trade_state参数,估计是旧版接口……
- payNotifyView.TradeState = resHandler.GetParameter("trade_state");
- //即时到账
- if ("SUCCESS".Equals(payNotifyView.ResultCode))
- {
- return payNotifyView;
- }
- else
- {
- string exceptionMessage = "支付失败";
- response.Write("<xml><return_code>FAIL</return_code><return_msg>exceptionMessage</return_msg></xml>");
- response.End();
- throw new Exception(exceptionMessage);
- }
- }
- else
- {//md5签名失败
- string exceptionMessage = "MD5签名失败:" + resHandler.GetDebugInfo();
- response.Write("<xml><return_code>FAIL</return_code><return_msg>exceptionMessage</return_msg></xml>");
- response.End();
- throw new Exception(exceptionMessage);
- }
- }
- public static ActionResult PayNotifySuccess
- {
- get
- {
- return new ContentResult() { Content = "<xml><return_code>SUCCESS</return_code><return_msg>OK</return_msg></xml>", ContentEncoding = Encoding.UTF8 };
- }
- }
- public static ActionResult PayNotifyFail(string errorMessage)
- {
- return new ContentResult() { Content = "<xml><return_code>FAIL</return_code><return_msg>" + errorMessage + "</return_msg></xml>", ContentEncoding = Encoding.UTF8 };
- }
- public static OrderQueryResult OrderQuery(string productId)
- {
- string nonceStr = TenPayV3Util.GetNoncestr();
- RequestHandler packageReqHandler = new RequestHandler(null);
- //设置package订单参数
- var datainfo = new TenPayV3OrderQueryRequestData(TenPayV3_AppId, TenPayV3_MchId, "", nonceStr, productId, TenPayV3_Key);
- var result = TenPayV3.OrderQuery(datainfo);
- return result;
- }
- #endregion
- #region 退款
- public static void Refund(string orderID, decimal totalFee, decimal fee)
- {
- //totalFee = (decimal)0.01;
- //fee = (decimal)0.01;
- //orderID = "20190801000019";
- if (fee > totalFee)
- {
- throw new Exception("退款金额不能大于总金额。");
- }
- string nonceStr = TenPayV3Util.GetNoncestr();
- string outTradeNo = orderID;
- string outRefundNo = "RN-" + orderID + SystemTime.Now.Ticks;
- int totalFeeInt = Convert.ToInt32(Math.Round(totalFee * 100, 0));
- int refundFeeInt = Convert.ToInt32(Math.Round(fee * 100, 0));
- string opUserId = TenPayV3_MchId;
- var notifyUrl = TenPayV3_RefundNotify;
- var dataInfo = new TenPayV3RefundRequestData(TenPayV3_AppId, TenPayV3_MchId, TenPayV3_Key,
- null, nonceStr, null, outTradeNo, outRefundNo, totalFeeInt, refundFeeInt, opUserId, null, notifyUrl: notifyUrl);
- var cert = @"D:\webs\jdks\wechatpay\cert\apiclient_cert.p12";//根据自己的证书位置修改
- //var cert = @"H:\surfacepro备份\开发项目\教务管理系统\岭南职业技术学院源码\1544542811_20190802_cert\apiclient_cert.p12";
- var password = TenPayV3_MchId;//默认为商户号,建议修改
- var result = TenPayV3.Refund(dataInfo, cert, password);
- if (result.return_code != "SUCCESS")
- {
- throw new Exception(result.return_msg);
- }
- if (result.result_code != "SUCCESS")
- {
- if (result.err_code == "NOTENOUGH")
- {
- dataInfo = new TenPayV3RefundRequestData(TenPayV3_AppId, TenPayV3_MchId, TenPayV3_Key,
- null, nonceStr, null, outTradeNo, outRefundNo, totalFeeInt, refundFeeInt, opUserId, "REFUND_SOURCE_RECHARGE_FUNDS", notifyUrl: notifyUrl);
- result = TenPayV3.Refund(dataInfo, cert, password);
- if (result.return_code != "SUCCESS")
- {
- throw new Exception(result.return_msg);
- }
- if (result.result_code != "SUCCESS")
- {
- throw new Exception("(" + result.err_code + ")" + result.err_code_des);
- }
- }
- else
- {
- throw new Exception("(" + result.err_code + ")" + result.err_code_des);
- }
- }
- }
- /// <summary>
- /// 退款通知处理
- /// </summary>
- /// <returns></returns>
- public static RefundNodifyView RefundNotify()
- {
- ResponseHandler resHandler = new ResponseHandler(null);
- string return_code = resHandler.GetParameter("return_code");
- string return_msg = resHandler.GetParameter("return_msg");
- if (return_code == "SUCCESS")
- {
- string appId = resHandler.GetParameter("appid");
- string mch_id = resHandler.GetParameter("mch_id");
- string nonce_str = resHandler.GetParameter("nonce_str");
- string req_info = resHandler.GetParameter("req_info");
- var decodeReqInfo = TenPayV3Util.DecodeRefundReqInfo(req_info, TenPayV3_Key);
- var decodeDoc = XDocument.Parse(decodeReqInfo);
- //获取接口中需要用到的信息
- var refundNodifyView = new RefundNodifyView();
- refundNodifyView.WechatOrderID = decodeDoc.Root.Element("transaction_id").Value;
- refundNodifyView.OrderID = decodeDoc.Root.Element("out_trade_no").Value;
- refundNodifyView.WechatRefundOrderID = decodeDoc.Root.Element("refund_id").Value;
- refundNodifyView.RefundOrderID = decodeDoc.Root.Element("out_refund_no").Value;
- refundNodifyView.Fee = decimal.Parse(decodeDoc.Root.Element("refund_fee").Value) / 100;
- return refundNodifyView;
- }
- else
- {
- throw new Exception(return_msg);
- }
- }
- #endregion
- public static PayNotifyView SearchWechatOrderStatus()
- {
- ResponseHandler resHandler = new ResponseHandler(null);
- resHandler.Init();
- resHandler.SetKey(TenPayV3_Key);
- var response = HttpContext.Current.Response;
- response.Clear();
- //判断签名
- if (resHandler.IsTenpaySign())
- {
- PayNotifyView payNotifyView = new PayNotifyView();
- //商户在收到后台通知后根据通知ID向财付通发起验证确认,采用后台系统调用交互模式
- payNotifyView.NotifyID = resHandler.GetParameter("notify_id");
- //取结果参数做业务处理
- payNotifyView.OrderID = resHandler.GetParameter("out_trade_no");
- //财付通订单号
- payNotifyView.WechatOrderID = resHandler.GetParameter("transaction_id");
- //金额,以分为单位
- payNotifyView.TotalFee = resHandler.GetParameter("total_fee");
- //如果有使用折扣券,discount有值,total_fee+discount=原请求的total_fee
- payNotifyView.Discount = resHandler.GetParameter("discount");
- //支付结果
- payNotifyView.ResultCode = resHandler.GetParameter("result_code");
- //范例上有个trade_state参数,估计是旧版接口……
- //即时到账
- if ("SUCCESS".Equals(payNotifyView.ResultCode))
- {
- return payNotifyView;
- }
- else
- {
- string exceptionMessage = "支付失败";
- response.Write("<xml><return_code>FAIL</return_code><return_msg>exceptionMessage</return_msg></xml>");
- response.End();
- throw new Exception(exceptionMessage);
- }
- }
- else
- {//md5签名失败
- string exceptionMessage = "MD5签名失败:" + resHandler.GetDebugInfo();
- response.Write("<xml><return_code>FAIL</return_code><return_msg>exceptionMessage</return_msg></xml>");
- response.End();
- throw new Exception(exceptionMessage);
- }
- }
- }
- }
|