using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Http; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using New_College.Common; using New_College.Common.Helper; using New_College.IRepository; using New_College.IServices; using New_College.Model; using New_College.Model.Models; using New_College.Model.ViewModels; using Newtonsoft.Json; namespace New_College.Api.Controllers.Front { [Route("api/front/[controller]/[action]")] [ApiController] [Authorize] public class WeixinPayController : ControllerBase { private readonly IV_OrderInfoRepository v_OrderInfoRepository; private readonly IV_CustomerInfoRepository v_CustomerInfoRepository; private readonly IV_VipCardInfoRepository v_VipCardInfoRepository; private readonly IV_VipCardTypeRepository v_VipCardTypeRepository; private readonly ILogger logger; public WeixinPayController(IV_OrderInfoRepository IV_OrderInfoRepository , IV_CustomerInfoRepository IV_CustomerInfoRepository , IV_VipCardInfoRepository IV_VipCardInfoRepository , IV_VipCardTypeRepository IV_VipCardTypeRepository , ILogger loggers) { v_OrderInfoRepository = IV_OrderInfoRepository; v_CustomerInfoRepository = IV_CustomerInfoRepository; v_VipCardInfoRepository = IV_VipCardInfoRepository; v_VipCardTypeRepository = IV_VipCardTypeRepository; logger = loggers; } /// /// 下订单 /// /// [HttpPost] public async Task UnifiedOrder(UnifiedOrderQuery query) { var resp = new WeixinPayResult(); try { DingHookHelper.DingTalkHookMessage("UnifiedOrder=>发起支付", JsonConvert.SerializeObject(query)); Random rd = new Random(); //HttpContext.GetClientUserIp(); //外部商户订单号 var payNum = DateTime.Now.ToString("yyyyMMddHHmmss") + rd.Next(0, 1000).ToString().PadLeft(3, '0'); var data = new WxPayData(); data.SetValue("body", "六纬志愿VIP"); data.SetValue("out_trade_no", payNum); data.SetValue("detail", "六纬志愿VIP卡"); data.SetValue("total_fee", Convert.ToInt32(query.total_fee * 100)); data.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss")); //data.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss")); data.SetValue("notify_url", WeixinConfig.NotifyUrl); //data.SetValue("goods_tag", "test"); data.SetValue("trade_type", "JSAPI"); data.SetValue("openid", query.OpenId); //可以将用户Id和订单Id同时封装在attach中 data.SetValue("attach", string.Format("{0}|{1}", query.OpenId, payNum)); WxPayData result = WeChatPayV3.UnifiedOrder(data); if (!result.IsSet("appid") || !result.IsSet("prepay_id") || result.GetValue("prepay_id").ToString() == "") { resp.err_code_des = result.GetValue("err_code_des").ToString(); resp.err_code = result.GetValue("err_code").ToString(); resp.result_code = result.GetValue("result_code").ToString(); return resp; } else { resp.nonce_str = result.GetValue("nonce_str").ToString(); resp.appid = result.GetValue("appid").ToString(); resp.mchi_id = result.GetValue("mch_id").ToString(); resp.result_code = result.GetValue("result_code").ToString(); resp.prepay_id = "prepay_id=" + result.GetValue("prepay_id").ToString(); //resp.code_url = result.GetValue("code_url").ToString(); resp.trade_type = result.GetValue("trade_type").ToString(); var signType = "MD5"; var timeStamp = ((DateTime.Now.Ticks - TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)).Ticks) / 10000).ToString(); WxPayData applet = new WxPayData(); applet.SetValue("appId", resp.appid); applet.SetValue("nonceStr", resp.nonce_str); applet.SetValue("package", resp.prepay_id); applet.SetValue("signType", signType); applet.SetValue("timeStamp", timeStamp); resp.sign = applet.MakeSign(); resp.timeStamp = timeStamp; //NLogHelper.WriteInfo("Signurl" + Newtonsoft.Json.JsonConvert.SerializeObject(resp), DevAuthorNameEnum.Michael, false); // WebHookHelper.WebHookmarkdownSend("Signurl" + Newtonsoft.Json.JsonConvert.SerializeObject(resp)); var customer = await v_CustomerInfoRepository.Query(x => x.OpenId == query.OpenId && x.IsDelete == false); if (customer.Count <= 0) return new WeixinPayResult() { err_code_des = "用户出现错误" }; //添加一张卡 var cardtype = await v_VipCardTypeRepository.QueryById(query.CardTypeId); if (cardtype == null) return new WeixinPayResult() { err_code_des = "卡出现错误" }; var code = RadomHelper.GetGuid(); var addcard = await v_VipCardInfoRepository.Add(new V_VipCardInfo() { CardTypeId = query.CardTypeId, CardTypeName = cardtype.Name, Code = code, IsBind = 1, Money = query.total_fee, Day = cardtype.Day, EndTime = DateTime.Now.AddDays(cardtype.Day) }); string OrderNo = OrderGenerateHelper.GenerateOrderNo("ZY"); var baseResult = await v_OrderInfoRepository.Add(new V_OrderInfo { out_trade_no = payNum, PayType = 0, CardTypeId = query.CardTypeId, OrderId = OrderNo, Status = EnumOrderType.payment, CustomerId = customer.FirstOrDefault().Id, Price = query.total_fee, PayPrice = query.total_fee, Name = "六纬志愿VIP", CardNo = code, CardId = addcard }); if (baseResult > 0) { //订单号 applet.SetValue("orderid", baseResult); resp.orderid = baseResult.ToString(); } } } catch (Exception ex) { //WebHookHelper.WebHookmarkdownSend(ex.ToString()); //NLogHelper.WriteError(ex, DevAuthorNameEnum.Michael, false); } return resp; } /// /// 支付返回值 /// /// [HttpPost] [AllowAnonymous] public async Task OldPayNotify() { logger.LogInformation("开始回调PayNotify"); DingHookHelper.DingTalkHookMessage("开始回调PayNotify", "开始回调PayNotify"); WxPayData res = new WxPayData(); //接收从微信后台POST过来的数据 //转换数据格式并验证签名 WxPayData data = new WxPayData(); using (var reader = new StreamReader(Request.Body)) { var builder = reader.ReadToEnd(); //WebHookHelper.WebHookmarkdownSend(builder.ToString()); DingHookHelper.DingTalkHookMessage("xml", builder.ToString()); try { data.FromXml(builder.ToString()); } catch (Exception ex) { //若签名错误,则立即返回结果给微信支付后台 DingHookHelper.DingTalkHookMessage("回调PayNotify", ex.Message); res.SetValue("return_code", "FAIL"); res.SetValue("return_msg", ex.Message); // NLogHelper.WriteError("Sign check error : " + res.ToXml(), DevAuthorNameEnum.Michael, false); //WebHookHelper.WebHookmarkdownSend(string.Format("return_msg:{0}", ex.Message)); return Content(res.ToXml(), "text/xml"); } }; // 执行订单状态操作 string out_trade_no = data.GetValue("out_trade_no").ToString(); logger.LogInformation("开始回调PayNotify" + out_trade_no); DingHookHelper.DingTalkHookMessage("回调PayNotify", "开始回调PayNotify" + out_trade_no); var info = await v_OrderInfoRepository.Query(x => x.out_trade_no == out_trade_no); if (info.Count <= 0) { res.SetValue("return_code", "FAIL"); res.SetValue("return_msg", "在自有平台未找到该订单号"); DingHookHelper.DingTalkHookMessage("回调PayNotify", "在自有平台未找到该订单号" + out_trade_no); //WebHookHelper.WebHookmarkdownSend("支付结果中微信订单号不存在"); return Content(res.ToXml(), "text/xml"); } var oneinfo = info.FirstOrDefault(); oneinfo.Status = EnumOrderType.payoff; var rep = await v_OrderInfoRepository.Update(oneinfo); if (rep) { DingHookHelper.DingTalkHookMessage("支付回调成功", oneinfo.out_trade_no + ":修改为VIP"); //修改用户信息 修改为VIp var customerinfo = await v_CustomerInfoRepository.QueryById(oneinfo.CustomerId); customerinfo.IsVIP = true; customerinfo.VipCode = oneinfo.CardNo; await v_CustomerInfoRepository.Update(customerinfo); var oldorderlist = await v_OrderInfoRepository.Query(c => c.CustomerId == oneinfo.CustomerId && c.Status == EnumOrderType.payment); oldorderlist.ForEach(async a => { a.Status = EnumOrderType.Cancel; await v_OrderInfoRepository.Update(a); }); //支付成功后根据用户code找到对应用户修改vip 状态 res.SetValue("return_code", "SUCCESS"); res.SetValue("return_msg", "OK"); } else { // string attach = data.GetValue("attach").ToString(); // WebHookHelper.WebHookmarkdownSend(attach); DingHookHelper.DingTalkHookMessage("回调PayNotify", "在自有平台未找到该订单号" + out_trade_no); res.SetValue("return_code", "FAIL"); res.SetValue("return_msg", "在自有平台未找到该订单号"); } return Content(res.ToXml(), "text/xml"); } [HttpPost] [AllowAnonymous] public async Task PayNotify() { var buffer = new MemoryStream(); Request.Body.CopyTo(buffer); var str = Encoding.UTF8.GetString(buffer.GetBuffer()); DingHookHelper.DingTalkHookMessage("PayNotify-buffer", str); var wxPayNotifyModel = JsonConvert.DeserializeObject(str); var resource = wxPayNotifyModel?.resource ?? new WxPayResourceModel(); var decryptStr = AesGcmHelper.AesGcmDecrypt(resource.associated_data, resource.nonce, resource.ciphertext, WeixinConfig.APIv3Key); var decryptModel = JsonConvert.DeserializeObject(decryptStr); var viewModel = new WxPayCallbackViewModel(); if (decryptModel != null && decryptModel.trade_state == "SUCCESS") { DingHookHelper.DingTalkHookMessage("PayNotify-decryptModel", decryptModel.ToJson()); var info = await v_OrderInfoRepository.Query(x => x.out_trade_no == decryptModel.out_trade_no); if (info.Count <= 0) { viewModel.message = "在自有平台未找到该订单号"; viewModel.code = "FAIL"; DingHookHelper.DingTalkHookMessage("回调PayNotify", "在自有平台未找到该订单号" + decryptModel.out_trade_no); return viewModel; } var oneinfo = info.FirstOrDefault(); oneinfo.Status = EnumOrderType.payoff; oneinfo.ModifyTime = DateTime.Now; var rep = await v_OrderInfoRepository.Update(oneinfo); if (rep) { DingHookHelper.DingTalkHookMessage("支付回调成功", oneinfo.out_trade_no); //修改用户信息 修改为VIp var customerinfo = await v_CustomerInfoRepository.QueryById(oneinfo.CustomerId); customerinfo.IsVIP = true; customerinfo.VipCode = oneinfo.CardNo; await v_CustomerInfoRepository.Update(customerinfo); var oldorderlist = await v_OrderInfoRepository.Query(c => c.CustomerId == oneinfo.CustomerId && c.Status == EnumOrderType.payment); oldorderlist.ForEach(async a => { a.Status = EnumOrderType.Cancel; await v_OrderInfoRepository.Update(a); }); //支付成功后根据用户code找到对应用户修改vip 状态 viewModel.message = "SUCCESS"; viewModel.code = "OK"; } else { DingHookHelper.DingTalkHookMessage("回调PayNotify", "在自有平台未找到该订单号" + decryptModel.out_trade_no); viewModel.message = "在自有平台未找到该订单号"; viewModel.code = "FAIL"; } return viewModel; } viewModel.code = "FAIL"; viewModel.message = "数据解密失败"; return new WxPayCallbackViewModel(); } } }