170 lines
5.4 KiB
C#
170 lines
5.4 KiB
C#
using DG.Redis;
|
|
using Microsoft.EntityFrameworkCore.Query.Internal;
|
|
using Zxd.Core.Domain.Dto.Zxd.Callback;
|
|
using Zxd.Core.Shared.Helpers;
|
|
|
|
namespace Zxd.Core.WebApi.Controllers
|
|
{
|
|
/// <summary>
|
|
/// 回调管理
|
|
/// </summary>
|
|
[ApiSignatureFilterForbid]
|
|
public class CallbackController : BaseController
|
|
{
|
|
private readonly IRedisManager _redisManager;
|
|
|
|
private readonly IOrderDomain _orderDomain;
|
|
|
|
private readonly PayCallbackConfig _payCallbackConfig;
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="redisManager"></param>
|
|
/// <param name="orderDomain"></param>
|
|
/// <param name="configuration"></param>
|
|
public CallbackController(
|
|
IRedisManager redisManager,
|
|
IOrderDomain orderDomain,
|
|
IConfiguration configuration)
|
|
{
|
|
_redisManager = redisManager;
|
|
_orderDomain = orderDomain;
|
|
_payCallbackConfig = configuration.GetSection("PayCallbackConfig").Get<PayCallbackConfig>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 支付回调
|
|
/// </summary>
|
|
/// <param name="dto"></param>
|
|
/// <returns></returns>
|
|
[HttpPost("Pay")]
|
|
[ApiResultFilterForbid]
|
|
public async Task<string> Pay(Dictionary<string, object> dto)
|
|
{
|
|
var authorization = default(string);
|
|
var timestamps = default(string);
|
|
var json = default(string);
|
|
var success = false;
|
|
try
|
|
{
|
|
authorization = Request.Headers["authorization"].FirstOrDefault();
|
|
if (string.IsNullOrEmpty(authorization))
|
|
{
|
|
throw new ApiException("authorization必填", 1);
|
|
}
|
|
var parts = authorization.Split(':');
|
|
if (parts.Length != 2)
|
|
{
|
|
throw new ApiException("authorization无效", 1);
|
|
}
|
|
var user = parts[0];
|
|
var sign = parts[1];
|
|
//var secret = await _redisManager.GetAsync<string>($"ZxdCore:Secret:{user}");
|
|
var secret = _payCallbackConfig.Secret;
|
|
if (string.IsNullOrEmpty(secret))
|
|
{
|
|
throw new ApiException("还未配置secret", 999);
|
|
}
|
|
|
|
timestamps = Request.Headers["timestamps"].FirstOrDefault();
|
|
if (string.IsNullOrEmpty(timestamps))
|
|
{
|
|
throw new ApiException("timestamps必填", 1);
|
|
}
|
|
json = GetSortedJson(dto);
|
|
|
|
Log.Information($"Callback,{authorization},{timestamps},{json}");
|
|
|
|
var args = new List<string> { user, json, secret, timestamps };
|
|
args.Sort(new ASCIIComparer());
|
|
var input = string.Join("", args);
|
|
var signData = Shared.Helpers.SecurityHelper.GetMD5String(input);
|
|
if (signData != sign)
|
|
{
|
|
throw new ApiException("签名不正确", 2);
|
|
}
|
|
|
|
var req = Dict2Model<BindOrderDto>(dto);
|
|
var invalids = ValidationHelper.Validate2<BindOrderDto>(req);
|
|
if (!string.IsNullOrEmpty(invalids))
|
|
{
|
|
throw new ApiException(invalids, 1);
|
|
}
|
|
|
|
await _orderDomain.BindAsync(req);
|
|
success = true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Information($"CallbackError,{authorization},{timestamps},{json},{ex}");
|
|
}
|
|
return success ? "支付回调成功" : "支付回调失败";
|
|
}
|
|
|
|
private string GetSortedJson(Dictionary<string, object> dto)
|
|
{
|
|
var items = new List<string>();
|
|
foreach (var p in dto.Keys)
|
|
{
|
|
items.Add(p);
|
|
}
|
|
|
|
items.Sort(new ASCIIComparer());
|
|
var dict = new Dictionary<string, object>();
|
|
foreach (var item in items)
|
|
{
|
|
var val = dto[item];
|
|
if (val!=null && val.ToString().Length>0)
|
|
{
|
|
dict[item]=val;
|
|
}
|
|
}
|
|
|
|
return JsonSerializer.Serialize(dict);
|
|
}
|
|
|
|
private T Dict2Model<T>(Dictionary<string, object> dict) where T : class, new()
|
|
{
|
|
var one = new T();
|
|
var t = typeof(T);
|
|
var ps = t.GetProperties();
|
|
foreach (var p in ps)
|
|
{
|
|
if (dict.ContainsKey(p.Name))
|
|
{
|
|
var val = dict[p.Name];
|
|
if (val != null)
|
|
{
|
|
var val_real = ConvertHelper.GetVal(p.PropertyType, val.ToString());
|
|
p.SetValue(one, val_real, null);
|
|
}
|
|
}
|
|
}
|
|
return one;
|
|
}
|
|
}
|
|
|
|
public class ASCIIComparer : IComparer<string>
|
|
{
|
|
public int Compare(string x, string y)
|
|
{
|
|
var len = x.Length > y.Length ? y.Length : x.Length;
|
|
for (var i = 0; i < len; i++)
|
|
{
|
|
if (x[i] < y[i])
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
if (x[i] > y[i])
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
}
|