436 lines
20 KiB
C#
436 lines
20 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");
|
||
}
|
||
|
||
};
|
||
// 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; }
|
||
}
|
||
}
|