NewGaoKaoApi/New_College.Api/Controllers/Front/WeixinPayController.cs

315 lines
15 KiB
C#

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<V_OrderInfo> logger;
public WeixinPayController(IV_OrderInfoRepository IV_OrderInfoRepository
, IV_CustomerInfoRepository IV_CustomerInfoRepository
, IV_VipCardInfoRepository IV_VipCardInfoRepository
, IV_VipCardTypeRepository IV_VipCardTypeRepository
, ILogger<V_OrderInfo> loggers)
{
v_OrderInfoRepository = IV_OrderInfoRepository;
v_CustomerInfoRepository = IV_CustomerInfoRepository;
v_VipCardInfoRepository = IV_VipCardInfoRepository;
v_VipCardTypeRepository = IV_VipCardTypeRepository;
logger = loggers;
}
/// <summary>
/// 下订单
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<WeixinPayResult> 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;
}
/// <summary>
/// 支付返回值
/// </summary>
/// <returns></returns>
[HttpPost]
[AllowAnonymous]
public async Task<IActionResult> 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<WxPayCallbackViewModel> 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<WxPayNotifyModel>(str);
var resource = wxPayNotifyModel?.resource ?? new WxPayResourceModel();
var decryptStr = AesGcmHelper.AesGcmDecrypt(resource.associated_data, resource.nonce, resource.ciphertext, WeixinConfig.APIv3Key);
var decryptModel = JsonConvert.DeserializeObject<WxPayResourceDecryptModel>(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;
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 状态
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();
}
}
}