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