提交代码,增加创建微信、支付接口

This commit is contained in:
zpc 2024-11-18 19:24:06 +08:00
parent a6768ca942
commit 5ae53b3cde
21 changed files with 811 additions and 8 deletions

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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)

View File

@ -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));
}
}

View File

@ -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阿里云配置

View File

@ -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;
}

View File

@ -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>

View File

@ -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;
}
}
}

View File

@ -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>
/// 用户默认配置

View File

@ -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; }
}

View File

@ -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>

View 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);
}

View 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
{
}
}

View File

@ -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;

View 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);
}
}

View 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);
}
}

View File

@ -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("微信下单失败");
}
}

View File

@ -44,6 +44,11 @@ namespace CloudGaming.DtoModel.Account.User
/// </summary>
public List<string> GameCollects { get; set; }
/// <summary>
/// 是否测试账号
/// </summary>
public bool IsTest { get; set; }
}
}

View File

@ -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; }
}
}

View File

@ -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; }
}

View File

@ -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
}