using System; using System.Collections.Generic; using System.Linq; using System.Text; using Antis.Pay.Core.Interface; using System.Web; using System.Security.Cryptography; using Antis.Pay.Core.Model; using System.Collections.Specialized; using Microsoft.AspNetCore.Http; using NCC.Common.Extensions; using NCC; namespace Antis.Pay.Core { public class AliPay : IAlipay { private readonly IHttpContextAccessor _httpContextAccessor; private static AlipayOptions AlipayConfig; public AliPay(IHttpContextAccessor httpContextAccessor) { _httpContextAccessor = httpContextAccessor; var setting = App.GetConfig("PaymentSettings", true); AlipayConfig = setting.AlipayConfig; } public string BuildAliPay(string orderNo, string subject, decimal payAmount, EnumAliPayTradeType tradeType) { return this.BuildRequest(orderNo, subject, payAmount, tradeType); } public bool VerifyReturnURL(HttpRequest request, out AliPayReturnModel model) { var requestVal = request.ReadFormAsync().GetAwaiter().GetResult(); return Verify(request, requestVal, out model); } public bool VerfyNotify(HttpRequest request, out AliPayReturnModel model) { var requestVal = request.ReadFormAsync().GetAwaiter().GetResult(); return Verify(request, requestVal, out model); } #region private method private bool Verify(HttpRequest request, IFormCollection requestVal, out AliPayReturnModel model) { bool result = false; SortedDictionary sortedDic = new SortedDictionary(); foreach (var item in requestVal.Keys) { if (item.ToLower() != "sign" && item.ToLower() != "sign_type" && !string.IsNullOrEmpty(item)) sortedDic.Add(item, requestVal[item]); } string requestSign = requestVal["sign"]; string requestSigntype = requestVal["sign_type"]; string param = CreateURLParamString(sortedDic); EnumSignType signType = requestSigntype == "MD5" ? EnumSignType.MD5 : requestSigntype == "RSA" ? EnumSignType.RSA : EnumSignType.MD5; if (signType == EnumSignType.MD5) { string sign = BuildRequestsign(param, signType); if (requestSign.Equals(sign)) result = true; } else result = RSAFromPkcs8.verify(param, requestSign, AlipayConfig.ALIPay_RSA_ALI_PUBLICKEY, "utf-8"); string responseText = GetResponseTxt(requestVal["notify_id"]); bool resultVal = result && responseText == "true"; if (resultVal) { model = new AliPayReturnModel() { OutTradeNo = request.Form["out_trade_no"], TradeNo = request.Form["trade_no"], TradeStatus = request.Form["trade_status"] }; decimal total_fee; decimal.TryParse(request.Form["total_fee"], out total_fee); model.TotalFee = total_fee; } else model = null; return resultVal; } private string BuildRequest(string orderNo, string subject, decimal totalAmt, EnumAliPayTradeType aliPayType) { var signType = aliPayType == EnumAliPayTradeType.APP ? EnumSignType.RSA : EnumSignType.MD5; SortedDictionary dicParam = CreateParam(orderNo, subject, totalAmt, aliPayType); string urlParam = CreateURLParamString(dicParam, aliPayType); string sign = BuildRequestsign(urlParam, signType); dicParam.Add("sign_type", signType.ToString()); if (aliPayType == EnumAliPayTradeType.APP) { //APP支付URL字段须进行URL编码,具体出处参看官方文档 sign = HttpUtility.UrlEncode(sign, Encoding.UTF8); return urlParam + "&sign=\"" + sign + "\"&sign_type=\"" + signType.ToString() + "\""; } else { dicParam.Add("sign", sign); return BuildForm(dicParam); } } private string BuildForm(SortedDictionary dicParam) { StringBuilder sbHtml = new StringBuilder(); sbHtml.Append("
"); foreach (KeyValuePair temp in dicParam) { sbHtml.Append(""); } sbHtml.Append(""); sbHtml.Append(""); return sbHtml.ToString(); } private SortedDictionary CreateParam(string orderNo, string subject, decimal totalAmt, EnumAliPayTradeType aliPayType) { SortedDictionary dic = new SortedDictionary(); #region BASEPARAM string service = aliPayType == EnumAliPayTradeType.Website ? AlipayConfig.ALIPay_WEB_SERVICE : aliPayType == EnumAliPayTradeType.Wap ? AlipayConfig.ALIPay_WAP_SERVICE : aliPayType == EnumAliPayTradeType.APP ? AlipayConfig.ALIPay_MOBILE_SERVICE : ""; dic.Add("service", service); dic.Add("partner", AlipayConfig.ALI_PARTER); dic.Add("_input_charset", AlipayConfig.CHARTSET); dic.Add("notify_url", AlipayConfig.ALIPay_NotifyURL); //dic.Add("sign_type", SIGNTYPE); #endregion #region BIZPARAM dic.Add("out_trade_no", orderNo); dic.Add("subject", subject); dic.Add("payment_type", AlipayConfig.PAYMENT_TYPE); dic.Add("total_fee", totalAmt.ToString("F2")); //dic.Add("seller_email", ALI_SELLEREMAIL); dic.Add("seller_id", AlipayConfig.ALI_SELLERID); //dic.Add("anti_phishing_key", anti_phishing_key);//防钓鱼时间戳,如果已申请开通防钓鱼证,则此字段必填。 //dic.Add("exter_invoke_ip", exter_invoke_ip);//客户端 IP ,如果商户申请后台开通防钓鱼 IP地址检查选项,此字段必填,校验用。 #endregion if (aliPayType == EnumAliPayTradeType.APP) dic.Add("body", subject + "购买"); return dic; } private string CreateURLParamString(SortedDictionary dicArray, EnumAliPayTradeType type = EnumAliPayTradeType.Website) { StringBuilder prestr = new StringBuilder(); foreach (KeyValuePair temp in dicArray.OrderBy(o => o.Key)) { if (type == EnumAliPayTradeType.APP) prestr.Append(temp.Key + "=\"" + temp.Value + "\"&"); else prestr.Append(temp.Key + "=" + temp.Value + "&"); } int nLen = prestr.Length; prestr.Remove(nLen - 1, 1); return prestr.ToString(); } private string BuildRequestsign(string urlParam, EnumSignType signType) { string mysign = ""; if (signType == EnumSignType.MD5) { string preString = urlParam + AlipayConfig.ALI_KEY; mysign = MD5Helper.Sign(preString, AlipayConfig.CHARTSET); } else if (signType == EnumSignType.RSA) mysign = RSASign(urlParam, AlipayConfig.ALIPay_RSA_PRIVATEKEY, AlipayConfig.CHARTSET); return mysign; } private string RSASign(string prestr, string privateKey, string input_charset) { try { return RSAFromPkcs8.sign(prestr, privateKey, input_charset); } catch (Exception e) { return e.Message; } } private string GetResponseTxt(string notify_id) { string veryfy_url = AlipayConfig.ALI_HTTPS_VERYFY_URL + "&partner=" + AlipayConfig.ALI_PARTER + "¬ify_id=" + notify_id; string response = HTTPHelper.Get(veryfy_url, 120000); return response; } #endregion } }