You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

280 lines
11 KiB

using GDZZ.Application.Entity;
using GDZZ.Core.Entity;
using GDZZ.Core;
2 years ago
using Microsoft.AspNetCore.Mvc;
using System;
using System.Threading.Tasks;
using Furion.EventBus;
using Microsoft.Extensions.Options;
using Microsoft.AspNetCore.Http;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
2 years ago
using GDZZ.Application.Service.WXPay.Dto;
2 years ago
using TenPayOldV3 = Senparc.Weixin.TenPay.V3.TenPayV3;
using Senparc.Weixin;
using Senparc.Weixin.TenPay.V3;
using Senparc.Weixin.TenPay;
using Senparc.CO2NET.Utilities;
using Senparc.Weixin.Sample.CommonService.TemplateMessage;
using System.IO;
using System.Text;
using Senparc.Weixin.Exceptions;
using Microsoft.AspNetCore.Authorization;
2 years ago
namespace GDZZ.Application.Service.WXPay
{
[ApiDescriptionSettings("Application", Name = "WXPay", Order = 1)]
public class WXPayService : IWXPayService, IDynamicApiController, ITransient
2 years ago
{
2 years ago
private readonly SqlSugarRepository<BaseUser> Baseuser; // wx用户仓储
private readonly SqlSugarRepository<SysUser> _sysUserRep; // 用户表仓储
private readonly SqlSugarRepository<SysTenant> _sysTenantRep; //租户仓储
private readonly SqlSugarRepository<SeIF> self; //职业仓储
private readonly SqlSugarRepository<Balance> balance; //职业仓储
2 years ago
private readonly SqlSugarRepository<MiniRecharge> rechargeRep; //充值仓储
private readonly SqlSugarRepository<MiniPayTake> payTakeRep; //支付仓储
2 years ago
private readonly WechatOAuth _wechatOAuth; //微信权限服务
private readonly IEventPublisher _eventPublisher; //事件写入服务
private readonly IHttpContextAccessor _httpContextAccessor; //http服务
/// <summary>
/// 获取配置文件
/// </summary>
2 years ago
private readonly SenparcWeixinSetting _oauthConfig;
public WXPayService(
IOptions<OAuthOptions> options,
SqlSugarRepository<BaseUser> Baseuser,
SqlSugarRepository<SysTenant> sysTenantRep,
SqlSugarRepository<SysUser> sysUserRep,
SqlSugarRepository<Balance> balance,
SqlSugarRepository<SeIF> Self,
SqlSugarRepository<MiniRecharge> rechargeRep,
SqlSugarRepository<MiniPayTake> payTakeRep,
WechatOAuth wechatOAuth,
IHttpContextAccessor _httpContextAccessor,
IEventPublisher eventPublisher)
{
this.balance = balance;
this.Baseuser = Baseuser;
this._sysUserRep = sysUserRep;
this._sysTenantRep = sysTenantRep;
this.self = Self;
this.rechargeRep = rechargeRep;
this.payTakeRep = payTakeRep;
this._wechatOAuth = wechatOAuth;
this._oauthConfig = options.Value.SenparcWeixin;
this._httpContextAccessor = _httpContextAccessor;
}
/// <summary>
/// 查询余额
/// </summary>
/// <returns></returns>
[HttpGet]
[Route("Mini/v1/GetUserBalance")]
2 years ago
public async Task<BalanceOut> GetUserBalance()
{
var balan = await this.balance.SingleAsync(x => x.UserID == UserManager.UserId);
2 years ago
if (balan == null)
return null;
return new BalanceOut()
{
Amount = balan.Amount,
UserID = UserManager.UserId,
2 years ago
};
}
/// <summary>
///微信小程序支付
/// </summary>
/// <param name="authUserInput">商品Id</param>
/// <returns></returns>
[HttpPost]
2 years ago
[Route("Mini/v1/wxpay")]
public async Task<dynamic> WxPay(AuthUserInput authUserInput)
{
2 years ago
var recharge = await this.rechargeRep.InsertReturnEntityAsync(new MiniRecharge()
{
2 years ago
PaymentMoney = authUserInput.Money,
Status = (int)RechargeEnum.NoFinis,
TotalPrice = authUserInput.Money
});
var payTake = await this.payTakeRep.InsertReturnEntityAsync(new MiniPayTake()
{
2 years ago
PaymentMoney = authUserInput.Money,
OrderId = recharge.Id,
PaySn = "",
PayStatus = (int)PayStatusEnum.NotPaying
});
int pMoney = (int)(authUserInput.Money * 100);
2 years ago
string sp_billno =
$"{Config.SenparcWeixinSetting.TenPayV3_MchId}{SystemTime.Now:yyyyMMddHHmmss}{TenPayV3Util.BuildRandomStr(6)}";
string timeStamp = TenPayV3Util.GetTimestamp();
string nonceStr = TenPayV3Util.GetNoncestr();
2 years ago
TenPayV3UnifiedorderRequestData xmlDataInfo = new TenPayV3UnifiedorderRequestData(Config.SenparcWeixinSetting.WxOpenAppId,
2 years ago
Config.SenparcWeixinSetting.TenPayV3_MchId,"余额充值", sp_billno,
pMoney,
"127.0.0.1",
Config.SenparcWeixinSetting.TenPayV3_TenpayNotify, TenPayV3Type.JSAPI, authUserInput.OpenID,
Config.SenparcWeixinSetting.TenPayV3_Key, nonceStr, null, null, null, null, payTake.OrderId.ToString());
2 years ago
Console.WriteLine(xmlDataInfo.PackageRequestHandler.ParseXML());
var result = TenPayOldV3.Unifiedorder(xmlDataInfo);//调用统一订单接口
string packageStr = "prepay_id=" + result.prepay_id;
2 years ago
return new
{
success = true,
result.prepay_id,
appId = Config.SenparcWeixinSetting.WxOpenAppId,
timeStamp,
nonceStr,
package = packageStr,
signType = "MD5",
paySign = TenPayV3.GetJsPaySign(Config.SenparcWeixinSetting.WxOpenAppId, timeStamp, nonceStr,
packageStr, Config.SenparcWeixinSetting.TenPayV3_Key)
};
2 years ago
}
/// <summary>
/// 微信小程序支付回调
/// </summary>
/// <returns></returns>
[HttpPost]
[Route("/Mini/NotifyUrl")]
[UnifyResult(typeof(string))]
[AllowAnonymous]
public async Task<string> NotifyUrl()
{
try
{
ResponseHandler resHandler = new ResponseHandler(this._httpContextAccessor.HttpContext);
string return_code = resHandler.GetParameter("return_code");
string return_msg = resHandler.GetParameter("return_msg");
string res = null;
resHandler.SetKey(Config.SenparcWeixinSetting.TenPayV3_Key);
//验证请求是否从微信发过来(安全)
if (resHandler.IsTenpaySign() && return_code.ToUpper() == "SUCCESS")
{
res = "success";//正确的订单处理
//直到这里,才能认为交易真正成功了,可以进行数据库操作,但是别忘了返回规定格式的消息!
2 years ago
Console.WriteLine("回调成功");
//attach
var paymentId = long.Parse(resHandler.GetParameter("attach"));
//业务处理
var paytake = await this.payTakeRep.Where(x => x.OrderId == paymentId).SingleAsync();
if (!paytake.IsEmpty())
{
paytake.PayStatus = (int)PayStatusEnum.Paying;
this.payTakeRep.Update(paytake);
}
var recharge = await this.rechargeRep.Where(x => x.Id == paymentId).SingleAsync();
if (!recharge.IsEmpty())
{
recharge.Status = (int)RechargeEnum.Finish;
this.rechargeRep.Update(recharge);
2 years ago
var balan = await this.balance.AsQueryable().Filter("TenantId", true).Where(x => x.UserID == paytake.CreatedUserId).SingleAsync();
if (!balan.IsEmpty())
{
2 years ago
balan.Amount = recharge.PaymentMoney;
this.balance.Update(balan);
}
2 years ago
else
{
this.balance.Insert(new Balance()
{
Amount = recharge.PaymentMoney,
UserID = (long)paytake.CreatedUserId
});
}
}
}
else
{
2 years ago
Console.WriteLine("回调失败");
res = "wrong";//错误的订单处理
}
/* 这里可以进行订单处理的逻辑 */
//发送支付成功的模板消息
try
{
string appId = Config.SenparcWeixinSetting.TenPayV3_AppId;//与微信公众账号后台的AppId设置保持一致区分大小写。
string openId = resHandler.GetParameter("openid");
var templateData = new WeixinTemplate_PaySuccess("https://weixin.senparc.com", "微信支付 V2 购买商品", "状态:" + return_code);
Senparc.Weixin.WeixinTrace.SendCustomLog("支付成功模板消息参数", appId + " , " + openId);
var result = Senparc.Weixin.MP.AdvancedAPIs.TemplateApi.SendTemplateMessage(appId, openId, templateData);
}
catch (Exception ex)
{
Senparc.Weixin.WeixinTrace.SendCustomLog("支付成功模板消息", ex.ToString());
}
#region 记录日志
var logDir = ServerUtility.ContentRootMapPath(string.Format("~/App_Data/TenPayNotify/{0}", SystemTime.Now.ToString("yyyyMMdd")));
if (!Directory.Exists(logDir))
{
Directory.CreateDirectory(logDir);
}
var logPath = Path.Combine(logDir, string.Format("{0}-{1}-{2}.txt", SystemTime.Now.ToString("yyyyMMdd"), SystemTime.Now.ToString("HHmmss"), Guid.NewGuid().ToString("n").Substring(0, 8)));
using (var fileStream = System.IO.File.OpenWrite(logPath))
{
var notifyXml = resHandler.ParseXML();
fileStream.Write(Encoding.Default.GetBytes(notifyXml), 0, Encoding.Default.GetByteCount(notifyXml));
fileStream.Close();
}
#endregion
string xml = string.Format(@"<xml>
<return_code><![CDATA[{0}]]></return_code>
<return_msg><![CDATA[{1}]]></return_msg>
</xml>", return_code, return_msg);
return xml;
}
catch (Exception ex)
{
WeixinTrace.WeixinExceptionLog(new WeixinException(ex.Message, ex));
throw;
}
}
2 years ago
}
}