修改创建订单回调地址
This commit is contained in:
parent
9047e3915c
commit
8dc9ee123c
43
src/0-core/HuanMeng.DotNetCore/Utility/MD5Encryption.cs
Normal file
43
src/0-core/HuanMeng.DotNetCore/Utility/MD5Encryption.cs
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HuanMeng.DotNetCore.Utility
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static class MD5Encryption
|
||||
{
|
||||
/// <summary>
|
||||
/// md5加密
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public static string ComputeMD5Hash(string input)
|
||||
{
|
||||
// 创建一个 MD5 哈希算法的实例
|
||||
using (MD5 md5 = MD5.Create())
|
||||
{
|
||||
// 将输入字符串转换为字节数组
|
||||
byte[] inputBytes = Encoding.UTF8.GetBytes(input);
|
||||
|
||||
// 计算 MD5 哈希值
|
||||
byte[] hashBytes = md5.ComputeHash(inputBytes);
|
||||
|
||||
// 将字节数组转换为十六进制字符串
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < hashBytes.Length; i++)
|
||||
{
|
||||
sb.Append(hashBytes[i].ToString("x2"));
|
||||
}
|
||||
|
||||
// 返回哈希值字符串
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -55,7 +55,7 @@ namespace HuanMeng.MiaoYu.Code.Order
|
|||
{
|
||||
price = (decimal)0.01;
|
||||
}
|
||||
(var orderId, var order) = await payment.CreateOrder(product.ProductName, price, product, ip);
|
||||
(var orderId, var order) = await payment.CreateOrder(product.Id,product.ProductName, price, product, ip);
|
||||
var t = product.ToIntentOrder(paymentMethod, orderId);
|
||||
t.UserId = _UserId;
|
||||
Dao.daoDbMiaoYu.context.Add(t);
|
||||
|
|
|
|||
|
|
@ -11,15 +11,16 @@ using Alipay.EasySDK.Kernel.Util;
|
|||
using Alipay.EasySDK.Payment.FaceToFace.Models;
|
||||
using StackExchange.Redis;
|
||||
using HuanMeng.DotNetCore.MultiTenant.Contract;
|
||||
using HuanMeng.MiaoYu.Code.Payment.WeChat;
|
||||
|
||||
namespace HuanMeng.MiaoYu.Code.Payment.Alipay
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class AlipayPayment(Config config, ITenantInfo tenantInfo) : IPayment
|
||||
public class AlipayPayment(Config config, ITenantInfo tenantInfo, int userId) : IPayment
|
||||
{
|
||||
public Task<(string orderId, string order)> CreateOrder(string productName, decimal price, params object[] args)
|
||||
public Task<(string orderId, string order)> CreateOrder(int productId, string productName, decimal price, params object[] args)
|
||||
{
|
||||
if (string.IsNullOrEmpty(productName))
|
||||
{
|
||||
|
|
@ -30,11 +31,13 @@ namespace HuanMeng.MiaoYu.Code.Payment.Alipay
|
|||
{
|
||||
throw new ArgumentNullException($"价格不能为空!");
|
||||
}
|
||||
var orderId = GenerateTimestampIdWithOffset();
|
||||
var orderId = PaymentExtend.GenerateCustomString("ZFB", userId, productId, "001");
|
||||
//.SetOptions(GetConfig());
|
||||
//AsyncNotify
|
||||
//https://pay.shhuanmeng.com/api/${tenant}/zfb/${orderId}
|
||||
var notifyUrl = config.NotifyUrl.Replace("${pay}", "zfb").Replace("${orderId}", orderId).Replace("${tenant}", tenantInfo.Identifier); ;
|
||||
string sign = $"{tenantInfo.Identifier}{orderId}{userId}";
|
||||
sign = MD5Encryption.ComputeMD5Hash(sign);
|
||||
var notifyUrl = config.NotifyUrl.Replace("${pay}", "zfb").Replace("${orderId}", orderId).Replace("${tenant}", tenantInfo.Identifier).Replace("${sign}", sign);
|
||||
var response = Factory.Payment.App().AsyncNotify(notifyUrl).Optional("passback_params", "PaymentType%3Dzfb").Pay(productName, orderId, priceStr);
|
||||
if (!ResponseChecker.Success(response))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -14,11 +14,15 @@ namespace HuanMeng.MiaoYu.Code.Payment.Contract
|
|||
/// <summary>
|
||||
/// 创建订单
|
||||
/// </summary>
|
||||
/// <param name="productId">产品id</param>
|
||||
/// <param name="orderId">订单id</param>
|
||||
/// <param name="productName">产品名称</param>
|
||||
/// <param name="price">价格</param>
|
||||
/// <param name="args">其它参数</param>
|
||||
/// <returns></returns>
|
||||
Task<(string orderId, string order)> CreateOrder(string productName, decimal price, params object[] args);
|
||||
Task<(string orderId, string order)> CreateOrder(int productId, string productName, decimal price, params object[] args);
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,9 +111,9 @@ namespace HuanMeng.MiaoYu.Code.Payment
|
|||
|
||||
if (payment == "zfb")
|
||||
{
|
||||
return new AlipayPayment(AlipayConfig, miaoYuBase.TenantInfo);
|
||||
return new AlipayPayment(AlipayConfig, miaoYuBase.TenantInfo, miaoYuBase._UserId);
|
||||
}
|
||||
return new WeChatPayment(wxClient, weChatConfig, miaoYuBase.TenantInfo);
|
||||
return new WeChatPayment(wxClient, weChatConfig, miaoYuBase.TenantInfo, miaoYuBase._UserId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -140,5 +140,98 @@ namespace HuanMeng.MiaoYu.Code.Payment
|
|||
};
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,20 +4,25 @@ using SKIT.FlurlHttpClient.Wechat.TenpayV3.Models;
|
|||
using SKIT.FlurlHttpClient.Wechat.TenpayV3;
|
||||
using Newtonsoft.Json;
|
||||
using HuanMeng.DotNetCore.MultiTenant.Contract;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace HuanMeng.MiaoYu.Code.Payment.WeChat
|
||||
{
|
||||
/// <summary>
|
||||
/// 微信支付
|
||||
/// </summary>
|
||||
public class WeChatPayment(WechatTenpayClient client, WeChatConfig weChatConfig, ITenantInfo tenantInfo) : IPayment
|
||||
public class WeChatPayment(WechatTenpayClient client, WeChatConfig weChatConfig, ITenantInfo tenantInfo, int userId) : IPayment
|
||||
{
|
||||
public async Task<(string orderId, string order)> CreateOrder(string productName, decimal price, params object[] args)
|
||||
public async Task<(string orderId, string order)> CreateOrder(int productId, string productName, decimal price, params object[] args)
|
||||
{
|
||||
var orderId = GenerateTimestampIdWithOffset();
|
||||
//var orderId = GenerateTimestampIdWithOffset();
|
||||
var orderId = PaymentExtend.GenerateCustomString("WX", userId, productId, "001");
|
||||
//var client = new WechatTenpayClient(wechatTenpayClientOptions);
|
||||
/* 以 JSAPI 统一下单接口为例 */
|
||||
var notifyUrl = weChatConfig.NotifyUrl.Replace("${pay}", "wx").Replace("${orderId}", orderId).Replace("${tenant}", tenantInfo.Identifier);
|
||||
string sign = $"{tenantInfo.Identifier}{orderId}{userId}";
|
||||
sign = MD5Encryption.ComputeMD5Hash(sign);
|
||||
var notifyUrl = weChatConfig.NotifyUrl.Replace("${pay}", "wx").Replace("${orderId}", orderId).Replace("${tenant}", tenantInfo.Identifier).Replace("${sign}", sign);
|
||||
|
||||
var request = new CreatePayTransactionAppRequest()
|
||||
{
|
||||
OutTradeNumber = orderId,
|
||||
|
|
@ -34,16 +39,10 @@ namespace HuanMeng.MiaoYu.Code.Payment.WeChat
|
|||
if (response.IsSuccessful())
|
||||
{
|
||||
var paramMap = client.GenerateParametersForAppPayRequest(request.AppId, response.PrepayId);
|
||||
Console.WriteLine("PrepayId:" + response.PrepayId);
|
||||
//Console.WriteLine("PrepayId:" + response.PrepayId);
|
||||
return new(orderId, JsonConvert.SerializeObject(paramMap));
|
||||
}
|
||||
throw new Exception("微信下单失败");
|
||||
}
|
||||
private string GenerateTimestampIdWithOffset()
|
||||
{
|
||||
var timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds(); // 获取Unix时间戳(毫秒)
|
||||
var random = new Random().Next(1000, 9999); // 生成四位随机数
|
||||
return $"WX0{timestamp}J001C{random}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,8 +31,8 @@ namespace HuanMeng.MiaoYu.WebPayApi.Controllers
|
|||
/// ${tenant}/zfb/${orderId}
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpPost("{tenant?}/{pay?}/{orderId?}")]
|
||||
public async Task<string> Post(string? tenant, string? pay, string? orderId)
|
||||
[HttpPost("{tenant?}/{pay?}/{orderId?}/{sign?}")]
|
||||
public async Task<string> Post(string? tenant, string? pay, string? orderId,string? sign)
|
||||
{
|
||||
var context = httpContextAccessor.HttpContext;
|
||||
context.Request.EnableBuffering(); // Enable buffering to allow the body to be read multiple times
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user