提交代码,增加创建微信、支付接口
This commit is contained in:
parent
a6768ca942
commit
5ae53b3cde
|
|
@ -0,0 +1,49 @@
|
|||
using CloudGaming.Api.Base;
|
||||
using CloudGaming.Code.Mall;
|
||||
using CloudGaming.DtoModel.Mall;
|
||||
|
||||
using HuanMeng.DotNetCore.Base;
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace CloudGaming.Api.Controllers;
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class PaymentController : CloudGamingControllerBase
|
||||
{
|
||||
public PaymentController(IServiceProvider _serviceProvider) : base(_serviceProvider)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建订单
|
||||
/// </summary>
|
||||
/// <param name="intentOrder"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[Authorize]
|
||||
public async Task<IntentOrderDto> CreateOrder([FromBody] IntentOrderRequest intentOrder)
|
||||
{
|
||||
OrderBLL orderBLL = new OrderBLL(ServiceProvider);
|
||||
return await orderBLL.CreateOrder(intentOrder.PaymentMethod, intentOrder.ProductId);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取订单状态
|
||||
/// </summary>
|
||||
/// <param name="orderId"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
[Authorize]
|
||||
public async Task<BaseResponse<bool>> GetOrderRewardsInfo(string orderId)
|
||||
{
|
||||
OrderBLL orderBLL = new OrderBLL(ServiceProvider);
|
||||
return await orderBLL.GetOrderRewardsInfo(orderId);
|
||||
}
|
||||
}
|
||||
|
|
@ -389,7 +389,7 @@ namespace CloudGaming.Code.Account
|
|||
// 将用户身份证号设置成 "前四位*后四位"
|
||||
if (!string.IsNullOrEmpty(userInfoDto.IdCard) && userInfoDto.IdCard.Length >= 8)
|
||||
{
|
||||
userInfo.IdCard = userInfoDto.IdCard.Substring(0, 4) + "*********" + userInfoDto.IdCard.Substring(userInfoDto.IdCard.Length - 4);
|
||||
userInfoDto.IdCard = userInfoDto.IdCard.Substring(0, 4) + "*********" + userInfoDto.IdCard.Substring(userInfoDto.IdCard.Length - 4);
|
||||
}
|
||||
return userInfoDto;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -181,6 +181,7 @@ namespace CloudGaming.Code.Account
|
|||
userInfo.IsJuveniles = user.UserRealNameStatus == 2;
|
||||
userInfo.UserName = user.UserName ?? "";
|
||||
userInfo.IdCard = user.IDCard ?? "";
|
||||
userInfo.IsTest = user.IsTest ?? false;
|
||||
|
||||
}
|
||||
if (userData != null)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
using Alipay.EasySDK.Factory;
|
||||
using Alipay.EasySDK.Kernel.Util;
|
||||
|
||||
using CloudGaming.Code.Contract;
|
||||
using CloudGaming.Code.Payment;
|
||||
|
||||
using HuanMeng.DotNetCore.MultiTenant;
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CloudGaming.Code.Aliyun;
|
||||
|
||||
public class AlipayPayment(AppConfig appConfig, int userId) : IPayment
|
||||
{
|
||||
public Task<(string orderId, string order)> CreateOrder(int productId, string productName, decimal price, params object[] args)
|
||||
{
|
||||
if (string.IsNullOrEmpty(productName))
|
||||
{
|
||||
throw new ArgumentNullException($"产品名称不能为空!");
|
||||
}
|
||||
var priceStr = price.ToString();
|
||||
if (string.IsNullOrEmpty(priceStr))
|
||||
{
|
||||
throw new ArgumentNullException($"价格不能为空!");
|
||||
}
|
||||
var orderId = PaymentExtend.GenerateCustomString("ZFB", userId, productId, "001");
|
||||
//.SetOptions(GetConfig());
|
||||
//AsyncNotify
|
||||
//https://pay.shhuanmeng.com/api/${tenant}/zfb/${orderId}
|
||||
string sign = $"{appConfig.Identifier}{orderId}{userId}";
|
||||
sign = MD5Encryption.ComputeMD5Hash(sign);
|
||||
var notifyUrl = appConfig.Payment?.AlipayConfig?.NotifyUrl;
|
||||
if (string.IsNullOrEmpty(notifyUrl))
|
||||
{
|
||||
notifyUrl = "";
|
||||
}
|
||||
var app = appConfig.Payment?.App();
|
||||
if (app == null)
|
||||
{
|
||||
throw new Exception("支付宝配置错误");
|
||||
}
|
||||
notifyUrl = notifyUrl.Replace("${pay}", "zfb").Replace("${orderId}", orderId).Replace("${tenant}", appConfig.Identifier).Replace("${sign}", sign);
|
||||
var response = app.AsyncNotify(notifyUrl).Optional("passback_params", "PaymentType%3Dzfb").Pay(productName, orderId, priceStr);
|
||||
if (!ResponseChecker.Success(response))
|
||||
{
|
||||
throw new Exception("创建订单失败!" + response.Body);
|
||||
}
|
||||
//.PreCreate("Apple iPhone11 128G", "2234567234890", "5799.00");
|
||||
var zfbOrderId = response.Body;
|
||||
return Task.FromResult((orderId, zfbOrderId));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
using CloudGaming.Code.AppExtend.Config;
|
||||
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
|
@ -61,7 +62,7 @@ public class AppConfig
|
|||
/// <summary>
|
||||
/// 项目支付数据
|
||||
/// </summary>
|
||||
//public PaymentModel? Payment { get; set; }
|
||||
public PaymentModel? Payment { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// oss阿里云配置
|
||||
|
|
|
|||
|
|
@ -186,12 +186,14 @@ namespace CloudGaming.Code.AppExtend
|
|||
newAppConfig.ExtConnectionString = appConfig.ExtConnectionString;
|
||||
newAppConfig.PhoneConnectionString = appConfig.PhoneConnectionString;
|
||||
newAppConfig.AliyunConfig = appConfig.AliyunConfig;
|
||||
newAppConfig.DefaultLanguage = appConfig.DefaultLanguage;
|
||||
newAppConfig.DefaultLanguage = appConfig.DefaultLanguage ?? "zh";
|
||||
if (appConfig.UserConfig == null)
|
||||
{
|
||||
appConfig.UserConfig = new UserConfig();
|
||||
}
|
||||
newAppConfig.UserConfig = appConfig.UserConfig;
|
||||
newAppConfig.Payment = appConfig.Payment;
|
||||
|
||||
return newAppConfig;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ using System.Linq;
|
|||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CloudGaming.Code.AppExtend.Config;
|
||||
namespace CloudGaming.Code.AppExtend.ConfigModel;
|
||||
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
using Alipay.EasySDK.Kernel;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using SKIT.FlurlHttpClient.Wechat.TenpayV3;
|
||||
using SKIT.FlurlHttpClient.Wechat.TenpayV3.Models;
|
||||
using SKIT.FlurlHttpClient.Wechat.TenpayV3.Settings;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
namespace CloudGaming.Code.AppExtend.ConfigModel;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class PaymentModel
|
||||
{
|
||||
/// <summary>
|
||||
/// 微信支付数据
|
||||
/// </summary>
|
||||
public WeChatConfig? WeChatConfig { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 支付宝支付数据
|
||||
/// </summary>
|
||||
public Alipay.EasySDK.Kernel.Config? AlipayConfig { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
private WechatTenpayClient _wxClient;
|
||||
/// <summary>
|
||||
/// 微信支付客户端
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public WechatTenpayClient? WxClient
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_wxClient == null)
|
||||
{
|
||||
if (WeChatConfig == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var manager = new InMemoryCertificateManager();
|
||||
/* 仅列出必须配置项。也包含一些诸如超时时间、UserAgent 等的配置项 */
|
||||
var wechatTenpayClientOptions = new WechatTenpayClientOptions()
|
||||
{
|
||||
|
||||
MerchantId = WeChatConfig.MchId,
|
||||
MerchantV3Secret = WeChatConfig.Key,
|
||||
MerchantCertificateSerialNumber = WeChatConfig.MerchantCertificateSerialNumber,
|
||||
MerchantCertificatePrivateKey = WeChatConfig.MerchantCertificatePrivateKey,
|
||||
PlatformCertificateManager = manager
|
||||
};
|
||||
_wxClient = new WechatTenpayClient(wechatTenpayClientOptions);
|
||||
}
|
||||
return _wxClient;
|
||||
}
|
||||
}
|
||||
|
||||
// var conf = appConfig.Payment?.AlipayConfig ?? new Alipay.EasySDK.Kernel.Config();
|
||||
//var context = new Alipay.EasySDK.Kernel.Context(conf, "alipay-easysdk-net-2.1.0");
|
||||
//var app = new Alipay.EasySDK.Payment.App.Client(new Alipay.EasySDK.Kernel.Client(context));
|
||||
|
||||
private Alipay.EasySDK.Kernel.Context _aliPayContext;
|
||||
[JsonIgnore]
|
||||
public Alipay.EasySDK.Kernel.Context AliPayContext
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_aliPayContext == null)
|
||||
{
|
||||
if (AlipayConfig != null)
|
||||
{
|
||||
_aliPayContext = new Alipay.EasySDK.Kernel.Context(AlipayConfig, "alipay-easysdk-net-2.1.0");
|
||||
}
|
||||
}
|
||||
return _aliPayContext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ using System.Linq;
|
|||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CloudGaming.Code.AppExtend.Config;
|
||||
namespace CloudGaming.Code.AppExtend.ConfigModel;
|
||||
|
||||
/// <summary>
|
||||
/// 用户默认配置
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CloudGaming.Code.AppExtend.ConfigModel;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class WeChatConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// appId
|
||||
/// </summary>
|
||||
public string AppId { get; set; }
|
||||
/// <summary>
|
||||
/// appkey
|
||||
/// </summary>
|
||||
public string AppSecret { get; set; }
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Key { get; set; }
|
||||
/// <summary>
|
||||
/// 商户id
|
||||
/// </summary>
|
||||
public string MchId { get; set; }
|
||||
/// <summary>
|
||||
/// 回调地址
|
||||
/// </summary>
|
||||
public string NotifyUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string MerchantCertificateSerialNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string MerchantCertificatePrivateKey { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -12,11 +12,14 @@
|
|||
<PackageReference Include="AgileConfig.Client" Version="1.7.3" />
|
||||
<PackageReference Include="AlibabaCloud.SDK.Cloudauth20190307" Version="3.2.0" />
|
||||
<PackageReference Include="AlibabaCloud.SDK.Dysmsapi20170525" Version="3.1.0" />
|
||||
<PackageReference Include="AlipayEasySDK" Version="2.1.3" />
|
||||
<PackageReference Include="AlipayEasySDK.Kernel" Version="1.0.6" />
|
||||
<PackageReference Include="AutoMapper" Version="13.0.1" />
|
||||
<PackageReference Include="Bogus" Version="35.6.1" />
|
||||
<PackageReference Include="FastMember" Version="1.5.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.10" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.1" />
|
||||
<PackageReference Include="SKIT.FlurlHttpClient.Wechat.TenpayV3" Version="3.9.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
23
src/CloudGaming/Code/CloudGaming.Code/Contract/IPayment.cs
Normal file
23
src/CloudGaming/Code/CloudGaming.Code/Contract/IPayment.cs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CloudGaming.Code.Contract;
|
||||
|
||||
/// <summary>
|
||||
/// 支付接口
|
||||
/// </summary>
|
||||
public interface IPayment
|
||||
{
|
||||
/// <summary>
|
||||
/// 创建订单
|
||||
/// </summary>
|
||||
/// <param name="productId">产品id</param>
|
||||
/// <param name="productName">产品名称</param>
|
||||
/// <param name="price">价格</param>
|
||||
/// <param name="args">其它参数</param>
|
||||
/// <returns></returns>
|
||||
Task<(string orderId, string order)> CreateOrder(int productId, string productName, decimal price, params object[] args);
|
||||
}
|
||||
12
src/CloudGaming/Code/CloudGaming.Code/Extend/OrderExtend.cs
Normal file
12
src/CloudGaming/Code/CloudGaming.Code/Extend/OrderExtend.cs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CloudGaming.Code.Extend
|
||||
{
|
||||
internal class OrderExtend
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -19,5 +19,6 @@ global using Microsoft.EntityFrameworkCore;
|
|||
global using Microsoft.Extensions.Configuration;
|
||||
global using Microsoft.Extensions.DependencyInjection;
|
||||
global using Microsoft.Extensions.Hosting;
|
||||
global using CloudGaming.Code.AppExtend.Config;
|
||||
global using System.Diagnostics;
|
||||
global using System.Diagnostics;
|
||||
|
||||
global using CloudGaming.Code.AppExtend.ConfigModel;
|
||||
108
src/CloudGaming/Code/CloudGaming.Code/Mall/OrderBLL.cs
Normal file
108
src/CloudGaming/Code/CloudGaming.Code/Mall/OrderBLL.cs
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
using CloudGaming.Code.DataAccess;
|
||||
using CloudGaming.Code.Payment;
|
||||
using CloudGaming.DtoModel.Account.User;
|
||||
using CloudGaming.DtoModel.Mall;
|
||||
|
||||
using HuanMeng.DotNetCore.Redis;
|
||||
|
||||
using Microsoft.EntityFrameworkCore.Storage;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CloudGaming.Code.Mall;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 订单数据
|
||||
/// </summary>
|
||||
public class OrderBLL : CloudGamingBase
|
||||
{
|
||||
public OrderBLL(IServiceProvider serviceProvider) : base(serviceProvider)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建订单
|
||||
/// </summary>
|
||||
/// <param name="paymentMethod"></param>
|
||||
/// <param name="productId"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
/// <exception cref="NullReferenceException"></exception>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public async Task<IntentOrderDto> CreateOrder(string paymentMethod, string productId)
|
||||
{
|
||||
if (_UserId == 0)
|
||||
{
|
||||
throw new ArgumentNullException("未登录");
|
||||
}
|
||||
if (string.IsNullOrEmpty(productId))
|
||||
{
|
||||
throw new ArgumentNullException("产品不能为空");
|
||||
}
|
||||
|
||||
var products = Cache.ProductCacheList;
|
||||
var product = products.FirstOrDefault(it => it.ProductId == productId);
|
||||
if (product == null)
|
||||
{
|
||||
throw new NullReferenceException("未找到所属产品");
|
||||
}
|
||||
var redisLock = $"lock:payment:{_UserId}:{productId}";
|
||||
if (!RedisCache.StringSetLock(redisLock, "", 5))
|
||||
{
|
||||
throw new ArgumentNullException("重复创建订单");
|
||||
}
|
||||
|
||||
//productEntityCache.get
|
||||
IntentOrderDto intentOrderDto = null;
|
||||
//创建订单
|
||||
try
|
||||
{
|
||||
var ip = HttpContextAccessor.HttpContext.GetClientIpAddress();
|
||||
var price = product.Price;
|
||||
var payment = PaymentExtend.GetPayment(paymentMethod, this);
|
||||
//UserInfoBLL userInfo = new UserInfoBLL(Dao, _UserId);
|
||||
if (UserInfo.IsTest)
|
||||
{
|
||||
price = (decimal)0.01;
|
||||
}
|
||||
(var orderId, var order) = await payment.CreateOrder(product.Id, product.ProductName, price, product, ip);
|
||||
var t = product.ToIntentOrder(paymentMethod, orderId);
|
||||
t.UserId = _UserId;
|
||||
await Dao.DaoUser.Context.AddAsync(t);
|
||||
await Dao.DaoUser.Context.SaveChangesAsync();
|
||||
intentOrderDto = new IntentOrderDto()
|
||||
{
|
||||
OrderId = orderId,
|
||||
Payment = order
|
||||
};
|
||||
RedisCache.KeyDelete(redisLock);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
RedisCache.KeyDelete(redisLock);
|
||||
throw new Exception("创建订单失败");
|
||||
}
|
||||
|
||||
return intentOrderDto;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取订单状态
|
||||
/// </summary>
|
||||
/// <param name="orderId"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<BaseResponse<bool>> GetOrderRewardsInfo(string orderId)
|
||||
{
|
||||
var tips = await Dao.DaoUser.Context.T_User_OrderItems.Where(it => it.OrderId == orderId).Select(it => it.RewardTips).FirstOrDefaultAsync();
|
||||
if (string.IsNullOrEmpty(tips))
|
||||
{
|
||||
return new BaseResponse<bool>(ResonseCode.Success, "", false);
|
||||
}
|
||||
return new BaseResponse<bool>(ResonseCode.Success, tips, true);
|
||||
}
|
||||
}
|
||||
278
src/CloudGaming/Code/CloudGaming.Code/Payment/PaymentExtend.cs
Normal file
278
src/CloudGaming/Code/CloudGaming.Code/Payment/PaymentExtend.cs
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
using Alipay.EasySDK.Factory;
|
||||
|
||||
using CloudGaming.Code.Aliyun;
|
||||
using CloudGaming.Code.Contract;
|
||||
using CloudGaming.Code.WeChat;
|
||||
using CloudGaming.DtoModel.Mall;
|
||||
using CloudGaming.DtoModel.Payment;
|
||||
|
||||
using SKIT.FlurlHttpClient.Wechat.TenpayV3;
|
||||
using SKIT.FlurlHttpClient.Wechat.TenpayV3.Settings;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CloudGaming.Code.Payment;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static class PaymentExtend
|
||||
{
|
||||
private static WechatTenpayClientOptions wechatTenpayClientOptions { get; set; } = new WechatTenpayClientOptions();
|
||||
private static WeChatConfig weChatConfig { get; set; }
|
||||
private static WechatTenpayClient wxClient { get; set; }
|
||||
/// <summary>
|
||||
/// 支付
|
||||
/// </su0mmary>
|
||||
/// <param name="builder"></param>
|
||||
/// <returns></returns>
|
||||
public static IHostApplicationBuilder AddPayment(this IHostApplicationBuilder builder)
|
||||
{
|
||||
|
||||
AddAlipay(builder.Configuration);
|
||||
AddWeChat(builder.Configuration);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载微信支付
|
||||
/// </summary>
|
||||
/// <param name="configuration"></param>
|
||||
public static void AddWeChat(IConfiguration configuration)
|
||||
{
|
||||
var _weChatConfig = configuration.GetSection("Payment:WeChatConfig").Get<WeChatConfig>();
|
||||
if (_weChatConfig == null)
|
||||
{
|
||||
Console.WriteLine("微信支付失败");
|
||||
//throw new Exception("微信支付失败");
|
||||
return;
|
||||
}
|
||||
weChatConfig = _weChatConfig;
|
||||
var manager = new InMemoryCertificateManager();
|
||||
/* 仅列出必须配置项。也包含一些诸如超时时间、UserAgent 等的配置项 */
|
||||
wechatTenpayClientOptions = new WechatTenpayClientOptions()
|
||||
{
|
||||
|
||||
MerchantId = weChatConfig.MchId,
|
||||
MerchantV3Secret = weChatConfig.Key,
|
||||
MerchantCertificateSerialNumber = weChatConfig.MerchantCertificateSerialNumber,
|
||||
MerchantCertificatePrivateKey = weChatConfig.MerchantCertificatePrivateKey,
|
||||
PlatformCertificateManager = manager
|
||||
};
|
||||
wxClient = new WechatTenpayClient(wechatTenpayClientOptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static Alipay.EasySDK.Kernel.Config AlipayConfig { get; set; }
|
||||
/// <summary>
|
||||
/// 支付
|
||||
/// </summary>
|
||||
/// <param name="configuration"></param>
|
||||
public static void AddAlipay(IConfiguration configuration)
|
||||
{
|
||||
var _config = configuration.GetSection("Payment:AlipayConfig").Get<Alipay.EasySDK.Kernel.Config>();
|
||||
|
||||
if (_config == null)
|
||||
{
|
||||
Console.WriteLine("接入支付失败");
|
||||
return;
|
||||
}
|
||||
var config = new Alipay.EasySDK.Kernel.Config()
|
||||
{
|
||||
Protocol = "https",
|
||||
GatewayHost = "openapi.alipay.com",
|
||||
SignType = "RSA2",
|
||||
AppId = _config.AppId,
|
||||
// 为避免私钥随源码泄露,推荐从文件中读取私钥字符串而不是写入源码中
|
||||
MerchantPrivateKey = _config.MerchantPrivateKey,
|
||||
// 如果采用非证书模式,则无需赋值上面的三个证书路径,改为赋值如下的支付宝公钥字符串即可
|
||||
AlipayPublicKey = _config.AlipayPublicKey,
|
||||
//可设置异步通知接收服务地址(可选)
|
||||
NotifyUrl = _config.NotifyUrl,
|
||||
};
|
||||
AlipayConfig = config;
|
||||
Factory.SetOptions(config);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///获取支付方式
|
||||
/// </summary>
|
||||
/// <param name="payment"></param>
|
||||
/// <returns></returns>
|
||||
public static IPayment GetPayment(string payment, CloudGamingBase cloudGamingBase)
|
||||
{
|
||||
//miaoYuBase.AppConfig.Payment
|
||||
if (payment == "zfb")
|
||||
{
|
||||
return new AlipayPayment(cloudGamingBase.AppConfig, cloudGamingBase._UserId);
|
||||
}
|
||||
|
||||
if (cloudGamingBase.AppConfig != null)
|
||||
{
|
||||
if (cloudGamingBase.AppConfig.Payment == null)
|
||||
{
|
||||
cloudGamingBase.AppConfig.Payment = new PaymentModel()
|
||||
{
|
||||
WeChatConfig = weChatConfig
|
||||
};
|
||||
}
|
||||
if (cloudGamingBase.AppConfig.Payment.WeChatConfig == null)
|
||||
{
|
||||
cloudGamingBase.AppConfig.Payment.WeChatConfig = weChatConfig;
|
||||
}
|
||||
}
|
||||
|
||||
var _weChatConfig = cloudGamingBase.AppConfig.Payment.WeChatConfig ?? weChatConfig;
|
||||
var _wxClient = cloudGamingBase.AppConfig.Payment.WxClient ?? wxClient;
|
||||
if (payment == "xcx")
|
||||
{
|
||||
if (cloudGamingBase._UserId == 0)
|
||||
{
|
||||
throw new Exception("请先登录");
|
||||
}
|
||||
var userAccount = cloudGamingBase.Dao.DaoUser.Context.T_User_MiniProgram_Account.FirstOrDefault(it => it.UserId == cloudGamingBase._UserId);
|
||||
if (userAccount == null)
|
||||
{
|
||||
throw new Exception("未找到人员数据,请先登录");
|
||||
}
|
||||
|
||||
//return new WeChatMiniProgram(_wxClient, _weChatConfig, miaoYuBase.TenantInfo, miaoYuBase._UserId, userAccount.OpenId);
|
||||
}
|
||||
return new WeChatPayment(_wxClient, _weChatConfig, cloudGamingBase.AppConfig, cloudGamingBase._UserId);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取支付包支付接口
|
||||
/// </summary>
|
||||
/// <param name="payment"></param>
|
||||
/// <returns></returns>
|
||||
public static Alipay.EasySDK.Payment.App.Client App(this PaymentModel payment)
|
||||
{
|
||||
return new Alipay.EasySDK.Payment.App.Client(new Alipay.EasySDK.Kernel.Client(payment.AliPayContext));
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="productCache"></param>
|
||||
/// <param name="payment"></param>
|
||||
/// <param name="orderId"></param>
|
||||
/// <returns></returns>
|
||||
public static T_User_IntentOrder ToIntentOrder(this ProductCache productCache, string payment, string orderId)
|
||||
{
|
||||
T_User_IntentOrder t_User_IntentOrder = new T_User_IntentOrder()
|
||||
{
|
||||
Price = productCache.Price,
|
||||
CreatedAt = DateTime.Now,
|
||||
IntentAt = DateTime.Now,
|
||||
Method = payment,
|
||||
Notes = "",
|
||||
ProductId = productCache.ProductId,
|
||||
Quantity = 1,
|
||||
Status = (int)OrderState.已下单,
|
||||
UpdatedAt = DateTime.Now,
|
||||
OrderId = orderId,
|
||||
};
|
||||
return t_User_IntentOrder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成订单编号
|
||||
/// </summary>
|
||||
/// <param name="identifier"></param>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="machineCode"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentException"></exception>
|
||||
public static string GenerateCustomString(string identifier, int userId, int producId, string machineCode)
|
||||
{
|
||||
// 确保标识符为3位,不足补0
|
||||
string identifierPadded = identifier.PadRight(3, '0');
|
||||
|
||||
// 获取当前时间戳
|
||||
long timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
||||
|
||||
// 将用户ID补足6位,不足补0
|
||||
string userIdPadded = userId.ToString().PadLeft(6, '0');
|
||||
// 产品id补足3位
|
||||
string producIdPadded = producId.ToString().PadLeft(3, '0');
|
||||
// 确保机器码为3位,不足补0
|
||||
string machineCodePadded = machineCode.PadLeft(3, '0');
|
||||
|
||||
// 计算随机字符串应占用的位数
|
||||
int randomStringLength = 32 - (identifierPadded.Length + 1 + 10 + 1 + userIdPadded.Length + 1 + machineCodePadded.Length + 1 + producIdPadded.Length + 1);
|
||||
|
||||
// 生成指定长度的随机字符串(字母和数字混合)
|
||||
string randomPadded = GenerateRandomString(randomStringLength);
|
||||
|
||||
// 使用 StringBuilder 拼接成最终字符串
|
||||
var sb = new StringBuilder(32);
|
||||
sb.Append(identifierPadded)
|
||||
.Append('T').Append(timestamp)
|
||||
.Append('U').Append(userIdPadded)
|
||||
.Append('P').Append(producIdPadded)
|
||||
.Append('M').Append(machineCodePadded)
|
||||
.Append('R').Append(randomPadded);
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private static string GenerateRandomString(int length)
|
||||
{
|
||||
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||
var random = new Random();
|
||||
var result = new char[length];
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
result[i] = chars[random.Next(chars.Length)];
|
||||
}
|
||||
return new string(result);
|
||||
}
|
||||
/// <summary>
|
||||
/// 解析订单号
|
||||
/// </summary>
|
||||
/// <param name="customString"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentException"></exception>
|
||||
public static (string Identifier, long Timestamp, int UserId, int ProductId, string MachineCode, string RandomString) ParseCustomString(string customString)
|
||||
{
|
||||
if (customString.Length != 32)
|
||||
{
|
||||
throw new ArgumentException("Custom string must be exactly 32 characters long.");
|
||||
}
|
||||
|
||||
// 通过索引位置缓存各个部分的起始位置
|
||||
int tIndex = customString.IndexOf('T');
|
||||
|
||||
int uIndex = customString.IndexOf('U');
|
||||
int pIndex = customString.IndexOf('P');
|
||||
int mIndex = customString.IndexOf('M');
|
||||
int rIndex = customString.IndexOf('R');
|
||||
|
||||
// 提取并去掉标识符的末尾零
|
||||
string identifier = customString.Substring(0, tIndex).TrimEnd('0');
|
||||
|
||||
// 提取时间戳
|
||||
long timestamp = long.Parse(customString.Substring(tIndex + 1, uIndex - tIndex - 1));
|
||||
|
||||
// 提取用户ID
|
||||
int userId = int.Parse(customString.Substring(uIndex + 1, pIndex - uIndex - 1));
|
||||
|
||||
// 提取产品ID
|
||||
int productId = int.Parse(customString.Substring(pIndex + 1, mIndex - pIndex - 1));
|
||||
|
||||
// 提取机器码
|
||||
string machineCode = customString.Substring(mIndex + 1, rIndex - mIndex - 1);
|
||||
|
||||
// 提取随机字符串
|
||||
string randomString = customString.Substring(rIndex + 1);
|
||||
|
||||
return (identifier, timestamp, userId, productId, machineCode, randomString);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
using CloudGaming.Code.Contract;
|
||||
using CloudGaming.Code.Payment;
|
||||
using Newtonsoft.Json;
|
||||
using SKIT.FlurlHttpClient.Wechat.TenpayV3.Models;
|
||||
using SKIT.FlurlHttpClient.Wechat.TenpayV3;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CloudGaming.Code.WeChat;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 微信支付
|
||||
/// </summary>
|
||||
public class WeChatPayment(WechatTenpayClient client, WeChatConfig weChatConfig, AppConfig appConfig, int userId) : IPayment
|
||||
{
|
||||
public async Task<(string orderId, string order)> CreateOrder(int productId, string productName, decimal price, params object[] args)
|
||||
{
|
||||
//var orderId = GenerateTimestampIdWithOffset();
|
||||
var orderId = PaymentExtend.GenerateCustomString("WX", userId, productId, "001");
|
||||
//var client = new WechatTenpayClient(wechatTenpayClientOptions);
|
||||
/* 以 JSAPI 统一下单接口为例 */
|
||||
string sign = $"{appConfig.Identifier}{orderId}{userId}";
|
||||
sign = MD5Encryption.ComputeMD5Hash(sign);
|
||||
var notifyUrl = weChatConfig.NotifyUrl.Replace("${pay}", "wx").Replace("${orderId}", orderId).Replace("${tenant}", appConfig.Identifier).Replace("${sign}", sign);
|
||||
|
||||
var request = new CreatePayTransactionAppRequest()
|
||||
{
|
||||
OutTradeNumber = orderId,
|
||||
AppId = weChatConfig.AppId,
|
||||
Description = productName,
|
||||
ExpireTime = DateTimeOffset.Now.AddMinutes(20),
|
||||
NotifyUrl = notifyUrl,
|
||||
Amount = new CreatePayTransactionJsapiRequest.Types.Amount()
|
||||
{
|
||||
Total = (int)(price * 100)
|
||||
},
|
||||
};
|
||||
|
||||
var response = await client.ExecuteCreatePayTransactionAppAsync(request);
|
||||
if (response.IsSuccessful())
|
||||
{
|
||||
var paramMap = client.GenerateParametersForAppPayRequest(request.AppId, response.PrepayId);
|
||||
//Console.WriteLine("PrepayId:" + response.PrepayId);
|
||||
return new(orderId, JsonConvert.SerializeObject(paramMap));
|
||||
}
|
||||
throw new Exception("微信下单失败");
|
||||
}
|
||||
}
|
||||
|
|
@ -44,6 +44,11 @@ namespace CloudGaming.DtoModel.Account.User
|
|||
/// </summary>
|
||||
public List<string> GameCollects { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否测试账号
|
||||
/// </summary>
|
||||
public bool IsTest { get; set; }
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CloudGaming.DtoModel.Mall
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class IntentOrderDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 订单编号
|
||||
/// </summary>
|
||||
public string OrderId { get; set; }
|
||||
/// <summary>
|
||||
/// 支付信息
|
||||
/// </summary>
|
||||
public object Payment { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CloudGaming.DtoModel.Mall;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class IntentOrderRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 产品编号
|
||||
/// </summary>
|
||||
public string ProductId { get; set; }
|
||||
/// <summary>
|
||||
/// 支付方式
|
||||
/// </summary>
|
||||
public string PaymentMethod { get; set; }
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CloudGaming.DtoModel.Payment;
|
||||
|
||||
/// <summary>
|
||||
/// 订单状态
|
||||
/// </summary>
|
||||
public enum OrderState
|
||||
{
|
||||
/// <summary>
|
||||
/// 已下单
|
||||
/// </summary>
|
||||
已下单 = 0,
|
||||
/// <summary>
|
||||
/// 正在发货
|
||||
/// </summary>
|
||||
正在发货 = 1,
|
||||
/// <summary>
|
||||
/// 已完成
|
||||
/// </summary>
|
||||
已完成 = 2,
|
||||
/// <summary>
|
||||
/// 发货失败
|
||||
/// </summary>
|
||||
发货失败 = 3
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user