private static void AddSign(HttpClient client, String interfaceUrl, String requestBody) { String requestId = Guid.NewGuid().ToString("N"); String timestamp = DateTime.Now.ToString("yyyy-MM-ddTHH:mm:sszzzz"); String version = "yop-auth-v2"; String expireSeconds = "1800"; String appKey = GlobalConfig.YeePay_FundOut_AppKey; var signHeaders = new SortedDictionary <String, String>(); signHeaders["x-yop-appkey"] = appKey; signHeaders["x-yop-request-id"] = requestId; signHeaders["x-yop-date"] = timestamp; foreach (var key in signHeaders.Keys) { client.DefaultRequestHeaders.Remove(key); client.DefaultRequestHeaders.Add(key, signHeaders[key]); } //签名内容的请求头部分 String signHeaderSignContent = String.Join("\n", signHeaders.Select(x => $"{WebUtil.UrlEncode(x.Key)}:{UrlEncodeToUpper(WebUtil.UrlEncode(x.Value))}")); //签名内容 String signContent = $"{version}/{appKey}/{timestamp}/{expireSeconds}\nPOST\n{interfaceUrl}\n{requestBody}\n{signHeaderSignContent}"; var sign = SignUtil.MakeSign(signContent, KeyConfig.YeePay_FundOut_Hehua_PrivateKey, PrivateKeyFormat.PKCS1, "RSA2"); if (sign.Success) { String signHeaderNames = String.Join(";", signHeaders.Keys); String base64SignContent = EncodeBase64(sign.Value) + "$SHA256"; client.DefaultRequestHeaders.Remove("Authorization"); String auth = GetAuthorization(version, appKey, timestamp, expireSeconds, signHeaderNames, base64SignContent); _logger.Debug($"Authorization={auth}"); client.DefaultRequestHeaders.Add("Authorization", auth); } }
public static XResult <TResult> Execute <TRequest, TResult>(String interfaceUrl, TRequest request) { if (request == null) { return(new XResult <TResult>(default(TResult), new ArgumentNullException(nameof(request)))); } String service = $"{typeof(YeePayFundOutUtil).FullName}.Execute(...)"; var client = GetClient(); var requestDic = CommonUtil.ToDictionary(request); if (requestDic == null || requestDic.Count == 0) { return(new XResult <TResult>(default(TResult), ErrorCode.INVALID_CAST, new InvalidCastException("将请求对象转换成字典失败"))); } //签名内容的请求内容部分 requestDic["method"] = interfaceUrl; requestDic["appKey"] = GlobalConfig.YeePay_FundOut_AppKey; requestDic["locale"] = "zh_CN"; requestDic["ts"] = GetTimeStamp(); requestDic["v"] = "1.0"; var orderedDic = new SortedDictionary <String, String>(requestDic); foreach (var key in orderedDic.Keys.ToList()) { orderedDic[key] = UrlEncodeToUpper(WebUtil.UrlEncode(orderedDic[key])); } String requestBody = String.Join("&", from t0 in orderedDic select $"{t0.Key}={t0.Value}"); AddSign(client, interfaceUrl, requestBody); String requestUrl = $"{ApiConfig.YeePay_FundOut_RequestUrl}{interfaceUrl}"; String traceMethod = $"{nameof(client)}.PostForm(...)"; _logger.Trace(TraceType.UTIL.ToString(), CallResultStatus.OK.ToString(), service, traceMethod, LogPhase.BEGIN, "开始请求易宝代付接口", new Object[] { requestUrl, requestDic }); var result = client.PostForm(requestUrl, orderedDic); _logger.Trace(TraceType.UTIL.ToString(), (result.Success ? CallResultStatus.OK : CallResultStatus.ERROR).ToString(), service, traceMethod, LogPhase.ACTION, "结束请求易宝代付接口"); if (!result.Success) { _logger.Error(TraceType.UTIL.ToString(), CallResultStatus.ERROR.ToString(), service, traceMethod, $"调用易宝代付接口失败:{result.ErrorMessage}", result.FirstException); return(new XResult <TResult>(default(TResult), result.FirstException)); } if (result.Value == null) { _logger.Error(TraceType.UTIL.ToString(), CallResultStatus.ERROR.ToString(), service, traceMethod, $"调用易宝代付接口超时"); return(new XResult <TResult>(default(TResult), ErrorCode.REQUEST_TIMEOUT)); } try { String respString = result.Value.Content.ReadAsStringAsync().GetAwaiter().GetResult(); String compressedRespString = CompressJsonString(respString); _logger.Trace(TraceType.UTIL.ToString(), CallResultStatus.OK.ToString(), service, traceMethod, LogPhase.END, "易宝代付返回结果", compressedRespString); if (respString.IsNullOrWhiteSpace()) { return(new XResult <TResult>(default(TResult), ErrorCode.REMOTE_RETURN_NOTHING, new RemoteException("支付机构未返回任何数据"))); } var respDic = JsonUtil.GetJToken(compressedRespString); var state = respDic.GetValue <String>("state"); if (state == "FAILURE") { var errorDecodeResult = JsonUtil.DeserializeObject <IDictionary <String, String> >(respDic["error"].ToString()); if (!errorDecodeResult.Success) { _logger.Error(TraceType.UTIL.ToString(), CallResultStatus.ERROR.ToString(), service, "errorDecodeResult", "易宝返回的数据无法反序列化", errorDecodeResult.FirstException, respDic["error"]); return(new XResult <TResult>(default(TResult), ErrorCode.DESERIALIZE_FAILED, errorDecodeResult.FirstException)); } return(new XResult <TResult>(default(TResult), ErrorCode.FAILURE, new RemoteException(respDic["message"].ToString()))); } //验签返回的结果 String signContent = GetResultJsonValue(compressedRespString); if (!VerifySign(signContent, respDic.GetValue <String>("sign"), out String signError)) { return(new XResult <TResult>(default(TResult), ErrorCode.SIGN_VERIFY_FAILED, new SignException(signError))); } var payResult = JsonUtil.DeserializeObject <TResult>(signContent); if (!payResult.Success) { _logger.Error(TraceType.UTIL.ToString(), CallResultStatus.ERROR.ToString(), service, "payResult", "易宝返回的数据无法反序列化", payResult.FirstException, respDic["error"]); return(new XResult <TResult>(default(TResult), ErrorCode.DESERIALIZE_FAILED, new ArgumentException($"参数payResult无法转换成{nameof(TResult)}类型"))); } return(new XResult <TResult>(payResult.Value)); } catch (Exception ex) { return(new XResult <TResult>(default(TResult), ex)); } }