|
|
|
|
using GDZZ.Application.Entity;
|
|
|
|
|
using GDZZ.Core.Entity;
|
|
|
|
|
using GDZZ.Core;
|
|
|
|
|
using Microsoft.AspNetCore.Authorization;
|
|
|
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
|
|
using Senparc.Weixin;
|
|
|
|
|
using Senparc.Weixin.Exceptions;
|
|
|
|
|
using Senparc.Weixin.Helpers;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using Furion.EventBus;
|
|
|
|
|
using Microsoft.Extensions.Options;
|
|
|
|
|
using Senparc.CO2NET.Extensions;
|
|
|
|
|
using Microsoft.AspNetCore.Http;
|
|
|
|
|
using Senparc.Weixin.TenPay.V3;
|
|
|
|
|
using Senparc.Weixin.TenPay;
|
|
|
|
|
using Furion.DependencyInjection;
|
|
|
|
|
using Furion.DynamicApiController;
|
|
|
|
|
using GDZZ.Application.Service.WXPay.Dto;
|
|
|
|
|
|
|
|
|
|
namespace GDZZ.Application.Service.WXPay
|
|
|
|
|
{
|
|
|
|
|
[ApiDescriptionSettings("Application", Name = "WXPay", Order = 1)]
|
|
|
|
|
public class WXPayService: IWXPayService, IDynamicApiController, ITransient
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
public static readonly string TenPayKey = Config.SenparcWeixinSetting.TenPayV3_Key; //与微信小程序后台的AppId设置保持一致,区分大小写。
|
|
|
|
|
|
|
|
|
|
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; //职业仓储
|
|
|
|
|
|
|
|
|
|
private readonly SqlSugarRepository<MiniRecharge> rechargeRep; //充值仓储
|
|
|
|
|
private readonly SqlSugarRepository<MiniPayTake> payTakeRep; //支付仓储
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private readonly WechatOAuth _wechatOAuth; //微信权限服务
|
|
|
|
|
private readonly IEventPublisher _eventPublisher; //事件写入服务
|
|
|
|
|
private readonly IHttpContextAccessor _httpContextAccessor; //http服务
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static TenPayV3Info _tenPayV3Info;
|
|
|
|
|
public static TenPayV3Info TenPayV3Info
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (_tenPayV3Info == null)
|
|
|
|
|
{
|
|
|
|
|
var key = TenPayHelper.GetRegisterKey(Config.SenparcWeixinSetting);
|
|
|
|
|
|
|
|
|
|
_tenPayV3Info =
|
|
|
|
|
TenPayV3InfoCollection.Data[key];
|
|
|
|
|
}
|
|
|
|
|
return _tenPayV3Info;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取配置文件
|
|
|
|
|
/// </summary>
|
|
|
|
|
private readonly ThirdParty _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.Wechat;
|
|
|
|
|
this._httpContextAccessor = _httpContextAccessor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 查询余额
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
[HttpGet]
|
|
|
|
|
[Route("Mini/v1/GetUserBalance")]
|
|
|
|
|
public async Task<BalanceOut> GetUserBalance()
|
|
|
|
|
{
|
|
|
|
|
var balan = await this.balance.SingleAsync(x => x.UserID == UserManager.UserId);
|
|
|
|
|
if (balan == null)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
return new BalanceOut()
|
|
|
|
|
{
|
|
|
|
|
Amount= balan.Amount,
|
|
|
|
|
UserID= UserManager.UserId,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
///微信小程序支付
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="productId">商品Id</param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
[HttpPost]
|
|
|
|
|
[Route("Mini/v1/wxpay")]
|
|
|
|
|
public async Task<dynamic> WxPay(AuthUserInput authUserInput)
|
|
|
|
|
{
|
|
|
|
|
var recharge = await this.rechargeRep.InsertReturnEntityAsync(new MiniRecharge()
|
|
|
|
|
{
|
|
|
|
|
PaymentMoney = authUserInput.Money,
|
|
|
|
|
Status = (int)RechargeEnum.NoFinis,
|
|
|
|
|
TotalPrice = authUserInput.Money
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var payTake = await this.payTakeRep.InsertReturnEntityAsync(new MiniPayTake()
|
|
|
|
|
{
|
|
|
|
|
PaymentMoney = authUserInput.Money,
|
|
|
|
|
OrderId = recharge.Id,
|
|
|
|
|
PaySn = "",
|
|
|
|
|
PayStatus = (int)PayStatusEnum.NotPaying
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
//序列号
|
|
|
|
|
string sp_billno =
|
|
|
|
|
$"{Config.SenparcWeixinSetting.TenPayV3_MchId}{SystemTime.Now:yyyyMMddHHmmss}{TenPayV3Util.BuildRandomStr(6)}";
|
|
|
|
|
string timeStamp = TenPayV3Util.GetTimestamp();
|
|
|
|
|
string nonceStr = TenPayV3Util.GetNoncestr();
|
|
|
|
|
|
|
|
|
|
TenPayV3UnifiedorderRequestData xmlDataInfo = new TenPayV3UnifiedorderRequestData(this._oauthConfig.app_id,
|
|
|
|
|
Config.SenparcWeixinSetting.TenPayV3_MchId, "充值金额", sp_billno,
|
|
|
|
|
(int)authUserInput.Money * 100,
|
|
|
|
|
"127.0.0.1",
|
|
|
|
|
Config.SenparcWeixinSetting.TenPayV3_WxOpenTenpayNotify, TenPayV3Type.JSAPI, authUserInput.OpenID,
|
|
|
|
|
Config.SenparcWeixinSetting.TenPayV3_Key, nonceStr, null, null, null, null, payTake.OrderId.ToString());
|
|
|
|
|
UnifiedorderResult result = await TenPayV3.UnifiedorderAsync(xmlDataInfo); //调用统一订单接口
|
|
|
|
|
string packageStr = "prepay_id=" + result.prepay_id;
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 微信小程序支付回调
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
[HttpPost]
|
|
|
|
|
[Route("Mini/v1/NotifyUrl")]
|
|
|
|
|
|
|
|
|
|
public async Task<string> NotifyUrl()
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine("");
|
|
|
|
|
ResponseHandler resHandler = new ResponseHandler(_httpContextAccessor.HttpContext);
|
|
|
|
|
string returnCode = resHandler.GetParameter("return_code");
|
|
|
|
|
resHandler.SetKey(TenPayKey);
|
|
|
|
|
if (resHandler.IsTenpaySign() && returnCode.ToUpper() == "SUCCESS")
|
|
|
|
|
{
|
|
|
|
|
//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);
|
|
|
|
|
var balan = await this.balance.Where(x => x.UserID == paytake.CreatedUserId).SingleAsync();
|
|
|
|
|
if (!balan.IsEmpty())
|
|
|
|
|
{
|
|
|
|
|
balan.Amount += recharge.PaymentMoney;
|
|
|
|
|
this.balance.Update(balan);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string xml = "<xml>"
|
|
|
|
|
+ "<return_code>SUCCESS</return_code>"
|
|
|
|
|
+ "<return_msg>OK</return_msg>"
|
|
|
|
|
+ "</xml>";
|
|
|
|
|
return xml;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
string xml = "<xml>"
|
|
|
|
|
+ "<return_code>FAIL</return_code>"
|
|
|
|
|
+ "<return_msg>支付通知失败</return_msg>"
|
|
|
|
|
+ "</xml>";
|
|
|
|
|
return xml;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|