324 lines
15 KiB
C#
324 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 New_College.Services;
|
|
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 ID_UserSettingBaseServices v_UserSettingBaseServices;
|
|
|
|
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,
|
|
ID_UserSettingBaseServices v_UserSettingBaseServices)
|
|
{
|
|
v_OrderInfoRepository = IV_OrderInfoRepository;
|
|
v_CustomerInfoRepository = IV_CustomerInfoRepository;
|
|
v_VipCardInfoRepository = IV_VipCardInfoRepository;
|
|
v_VipCardTypeRepository = IV_VipCardTypeRepository;
|
|
logger = loggers;
|
|
this.v_UserSettingBaseServices = v_UserSettingBaseServices;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 下订单
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
[HttpPost]
|
|
public async Task<WeixinPayResult> UnifiedOrder(UnifiedOrderQuery query)
|
|
{
|
|
var resp = new WeixinPayResult();
|
|
try
|
|
{
|
|
var vipinfo = await v_VipCardTypeRepository.QueryById(5);
|
|
query.total_fee = vipinfo.Money;
|
|
|
|
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;
|
|
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);
|
|
});
|
|
await v_UserSettingBaseServices.SyncBaseInfo(new UserSettingBaseRequest() { CustomerId = oneinfo.CustomerId });
|
|
//支付成功后根据用户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();
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|