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

436 lines
20 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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");
}
};
// WebHookHelper.WebHookmarkdownSend("Check sign success");
//检查支付结果中transaction_id是否存在
//if (!data.IsSet("transaction_id"))
//{
// DingHookHelper.DingTalkHookMessage("回调PayNotify", "支付结果中微信订单号不存在");
// //若transaction_id不存在则立即返回结果给微信支付后台
// res.SetValue("return_code", "FAIL");
// res.SetValue("return_msg", "支付结果中微信订单号不存在");
// //WebHookHelper.WebHookmarkdownSend("支付结果中微信订单号不存在");
// 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();
}
/// <summary>
/// 暂时不用有bug
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
[HttpPost]
[AllowAnonymous]
public async Task<IActionResult> NewPayNotify(WeChatPayCallobject model)
{
DingHookHelper.DingTalkHookMessage("开始回调PayNotify", "开始回调PayNotify");
// 处理微信支付回调数据
if (model.event_type == "TRANSACTION.SUCCESS")
{
DingHookHelper.DingTalkHookMessage("result_code", "SUCCESS");
// 订单支付成功处理逻辑
var info = await v_OrderInfoRepository.Query(x => x.out_trade_no == "");
if (info.Count <= 0)
{
DingHookHelper.DingTalkHookMessage("回调PayNotify", "在自有平台未找到该订单号" + "");
//WebHookHelper.WebHookmarkdownSend("支付结果中微信订单号不存在");
return Content("\"return_code\", \"FAIL\"");
}
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 状态
return Ok("SUCCESS");
}
else
{
// string attach = data.GetValue("attach").ToString();
// WebHookHelper.WebHookmarkdownSend(attach);
DingHookHelper.DingTalkHookMessage("回调PayNotify", "在自有平台未找到该订单号" + "");
//res.SetValue("return_code", "FAIL");
//res.SetValue("return_msg", "在自有平台未找到该订单号");
return Content("\"return_code\", \"FAIL\"");
}
}
//else if (model.result_code == "FAIL")
//{
// DingHookHelper.DingTalkHookMessage("result_code", "订单支付失败处理逻辑");
// 订单支付失败处理逻辑...
//}
return Content("SUCCESS");
}
}
public class WeChatPayCallobject
{
public string id { get; set; }
public DateTime create_time { get; set; }
public string resource_type { get; set; }
public string event_type { get; set; }
public string summary { get; set; }
public Resource resource { get; set; }
}
public class Resource
{
public string original_type { get; set; }
public string algorithm { get; set; }
public string ciphertext { get; set; }
public string associated_data { get; set; }
public string nonce { get; set; }
}
public class WeChatPayCallbackModel
{
public string return_code { get; set; }
public string return_msg { get; set; }
public string appid { get; set; }
public string mch_id { get; set; }
public string nonce_str { get; set; }
public string sign { get; set; }
public string result_code { get; set; }
public string openid { get; set; }
public string is_subscribe { get; set; }
public string trade_type { get; set; }
public string bank_type { get; set; }
public string total_fee { get; set; }
public string fee_type { get; set; }
public string transaction_id { get; set; }
public string out_trade_no { get; set; }
public string attach { get; set; }
public string time_end { get; set; }
}
}