using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Edu.Common;
using Edu.Common.API;
using Edu.Common.Plugin;
using Edu.Common.WeChatPayAPIv3;
using Edu.Common.WeChatPayAPIv3.Model;
using Edu.Common.WeChatPayAPIv3.Model.GenerateOrder;
using Edu.Common.WeChatPayAPIv3.Model.QueryOrder;
using Edu.Common.WeChatPayAPIv3.Model.QueryRefunds;
using Edu.Common.WeChatPayAPIv3.Model.Refunds;
using Edu.Common.WeChatPayAPIv3.Model.RefundsCallback;
using Edu.Common.WeChatPayAPIv3.Model.WxPayCallback;
using Edu.Model.Entity.Finance;
using Edu.Model.ViewModel.Finance;
using Edu.Module.Course;
using Edu.Module.User;
using Edu.WebApi.Filter;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;
namespace Edu.WebApi.Controllers.WeChatPay
{
[Route("api/[controller]/[action]")]
[ApiExceptionFilter]
[ApiController]
[EnableCors("AllowCors")]
public class WeChatPayController : BaseController
{
///
/// 订单处理类对象
///
private readonly EducationContractModule educationContractModule = AOP.AOPHelper.CreateAOPObject();
///
/// 订单处理类对象
///
private readonly EmployeeModule employeeModule = AOP.AOPHelper.CreateAOPObject();
///
/// 订单处理类对象
///
private readonly OrderModule orderModule = AOP.AOPHelper.CreateAOPObject();
private readonly object _lock = new object();
///
/// 统一下单接口
///
///
[HttpPost]
[AllowAnonymous]
public ApiResult GenerateOrder()
{
JObject jobj = JObject.Parse(RequestParm.Msg.ToString());
int contractId = jobj.GetInt("contractId");
var orderModle = educationContractModule.GetEducationContractModule(contractId);
if (orderModle.Status == 4)
{
return ApiResult.Failed("合同已取消");
}
var orderNumber = $"{DateTime.Now:yyyyMMddHHmmssfff}{contractId}";
LogHelper.WriteInfo("合同Id:" + contractId + " 商户订单号:" + orderNumber);
var helper = new WxPayHelper(WxPayConst.appid, WxPayConst.mchid, WxPayConst.serialNo, WxPayConst.privateKey);
var notify_url = Config.sTenpayNotifyUrl;//ConfigurationManager.AppSettings["notify_url"]; //这个放在配置文件,从配置文件读取比较灵活,或者写到数据库中
Task payodel = helper.UnionGenerateOrder(orderModle.CourseName, Convert.ToInt32(orderModle.Money * 100), orderNumber, notify_url, orderModle.OrderId.ToString());
#region 调用微信支付
var signModel = WxPayForAppHelper.GetSign(WxPayConst.appid, payodel.Result.code_url, WxPayConst.privateKey);
#endregion
return ApiResult.Success(data: signModel);
}
///
/// 微信支付成功结果回调接口
///
/// 退款通知http应答码为200且返回状态码为SUCCESS才会当做商户接收成功,否则会重试。注意:重试过多会导致微信支付端积压过多通知而堵塞,影响其他正常通知。
[HttpPost]
[HttpGet]
[AllowAnonymous]
public WxPayCallbackRespModel WxPayCallback(WxPayNotifyModel wxPayNotifyModel)
{
var viewModel = new WxPayCallbackRespModel();
try
{
// var wxPayNotifyModel = Common.Plugin.JsonHelper.DeserializeObject(Request.Body.ToString()); //str.ToObject();
var resource = wxPayNotifyModel?.resource ?? new WxPayResourceModel();
var decryptStr = AesGcmHelper.AesGcmDecrypt(resource.associated_data, resource.nonce, resource.ciphertext, WxPayConst.APIV3Key);
LogHelper.WriteInfo("订单回调信息decryptStr" + decryptStr);
var payModel = Common.Plugin.JsonHelper.DeserializeObject(decryptStr); //decryptStr.ToObject();
if (payModel.trade_state == "SUCCESS")
{
viewModel.code = "SUCCESS";
viewModel.message = "";
}
if (string.IsNullOrEmpty(payModel.out_trade_no))
{
viewModel.code = "FAIL";
viewModel.message = "数据解密失败";
}
else
{
if (payModel != null && payModel.trade_state == "SUCCESS")//生成财务单据
{ //然后进行数据库更新处理……等等其他操作
UpdateFinance(payModel);//生成财务单据以及生成支付记录
viewModel.code = "SUCCESS";
viewModel.message = "";
}
}
}
catch (Exception ex)
{
Common.Plugin.LogHelper.Write(ex, "WxPayCallback");
viewModel.code = "FAIL";
viewModel.message = "数据解密失败";
}
return viewModel;
}
///
/// 生成财务单据以及生成支付记录
///
///
///
[AllowAnonymous]
public void UpdateFinance(WxPayResourceDecryptModel payModel)
{
LogHelper.WriteInfo("我是回调" + System.DateTime.Now);
int contractId = Convert.ToInt32(payModel.out_trade_no[17..]);
bool isAdd = false;
if (!Cache.User.UserReidsCache.Exists(Cache.CacheKey.WeChatPay_Callback_Key + payModel.out_trade_no))
{
LogHelper.WriteInfo(payModel.out_trade_no + "我是回调:" + System.DateTime.Now);
Cache.User.UserReidsCache.Set(Cache.CacheKey.WeChatPay_Callback_Key + payModel.out_trade_no, payModel.out_trade_no, 1800);
isAdd = true;
Cache.User.UserReidsCache.Set(Cache.CacheKey.WeChatPay_Callback_Key + payModel.out_trade_no, payModel.out_trade_no, 1800);
var oldOrderRecordModel = educationContractModule.GetOrderRecordList(new RB_Finance_OrderRecord { ContractId = contractId, OutTradeNo = payModel.out_trade_no, Type = 1 }).FirstOrDefault();
if (oldOrderRecordModel == null || oldOrderRecordModel.ID == 0)
{
isAdd = true;
}
if (isAdd)
{
LogHelper.WriteInfo(payModel.out_trade_no + "我要新增财务单据啦...." + System.DateTime.Now);
var orderModle = educationContractModule.GetEducationContractModule(contractId);
var orderModel = orderModule.GetClassOrderInfoModule(orderModle.OrderId);
var financeConfig = educationContractModule.GetFinanceConfigList(new RB_Finance_Config_ViewModel { Group_Id = orderModle.Group_Id, Type = Common.Enum.Course.FinanceConfigTypeEnum.Tuition }).FirstOrDefault();
if (financeConfig == null)
{
financeConfig = new RB_Finance_Config_ViewModel();
}
var userInfo = employeeModule.GetEmployeeListModule(new Model.ViewModel.User.Employee_ViewModel { Id = orderModel.EnterID, Group_Id = orderModel.Group_Id }).ToList().FirstOrDefault();
var OriginalFee = Math.Round((Convert.ToDecimal(Config.SettlementRate) / 100) * (Convert.ToDecimal(payModel.amount.payer_total) / 100), 2, MidpointRounding.AwayFromZero);//手续费
RB_Online_Trade_Detail model = new RB_Online_Trade_Detail();
RB_Finance_OrderRecord orderRecordModel = new RB_Finance_OrderRecord
{
ID = 0,
Type = 1,
FinanceId = 0,
OrderId = orderModle.OrderId,
ContractId = orderModle.Id,
CreateDate = System.DateTime.Now,
RB_Group_Id = orderModle.Group_Id,
RB_School_Id = orderModle.School_Id,
OutTradeNo = payModel.out_trade_no,
TransactionId = payModel.transaction_id,
TotalPrice = Convert.ToDecimal(payModel.amount.payer_total) / 100,
ServiceFee = OriginalFee
};
#region 财务单据数据组装
var detailList = new List