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
{
///
/// 回调管理
///
[ApiSignatureFilterForbid]
public class CallbackController : BaseController
{
private readonly IRedisManager _redisManager;
private readonly IOrderDomain _orderDomain;
private readonly PayCallbackConfig _payCallbackConfig;
///
///
///
///
///
///
public CallbackController(
IRedisManager redisManager,
IOrderDomain orderDomain,
IConfiguration configuration)
{
_redisManager = redisManager;
_orderDomain = orderDomain;
_payCallbackConfig = configuration.GetSection("PayCallbackConfig").Get();
}
///
/// 支付回调
///
///
///
[HttpPost("Pay")]
[ApiResultFilterForbid]
public async Task Pay(Dictionary 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($"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 { 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(dto);
var invalids = ValidationHelper.Validate2(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 dto)
{
var items = new List();
foreach (var p in dto.Keys)
{
items.Add(p);
}
items.Sort(new ASCIIComparer());
var dict = new Dictionary();
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(Dictionary 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
{
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;
}
}
}