|  |  |  | 
|---|
|  |  |  | using Alipay.EasySDK.Payment.FaceToFace.Models; | 
|---|
|  |  |  | using LifePayment.Domain.Shared; | 
|---|
|  |  |  | using Microsoft.Extensions.Options; | 
|---|
|  |  |  | using Nest; | 
|---|
|  |  |  | using Spire.Pdf; | 
|---|
|  |  |  | using System; | 
|---|
|  |  |  | using System.Collections; | 
|---|
|  |  |  | using System.Collections.Generic; | 
|---|
|  |  |  | using System.Threading.Tasks; | 
|---|
|  |  |  | using Tea; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | namespace LifePayment.Domain | 
|---|
|  |  |  | { | 
|---|
|  |  |  | 
|---|
|  |  |  | { | 
|---|
|  |  |  | private readonly Config _options; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | public const string SDKVERSION = "alipay-easysdk-net-2.0.0"; | 
|---|
|  |  |  | protected Alipay.EasySDK.Kernel.Client _kernel; | 
|---|
|  |  |  | public AliPayApi( | 
|---|
|  |  |  | IOptionsMonitor<Config> optionsMonitor) | 
|---|
|  |  |  | IOptionsMonitor<Config> optionsMonitor, string optionsName = null) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | Alipay.EasySDK.Kernel.Context context = new Alipay.EasySDK.Kernel.Context(optionsName.IsNullOrEmpty() ? optionsMonitor.CurrentValue : optionsMonitor.Get(optionsName), SDKVERSION); | 
|---|
|  |  |  | _options = optionsMonitor.CurrentValue; | 
|---|
|  |  |  | this._kernel = new Client(context); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | public async Task<AlipayTradePrecreateResponse> GetAliPayQRCode(GetPayQrCodeInput input) | 
|---|
|  |  |  | 
|---|
|  |  |  | return response; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | public AlipayTradeQueryResponse OrderInQuiry(OrderInQuiryInput input) | 
|---|
|  |  |  | /// <summary> | 
|---|
|  |  |  | /// 查询支付宝支付订单信息 | 
|---|
|  |  |  | /// </summary> | 
|---|
|  |  |  | /// <param name="input"></param> | 
|---|
|  |  |  | /// <returns></returns> | 
|---|
|  |  |  | public async Task<AlipayTradeQueryResponse> OrderInQuiry(OrderInQuiryInput input) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | AlipayTradeQueryResponse response = Factory.Payment.Common().Query(input.OutTradeNo); | 
|---|
|  |  |  | return response; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /// <summary> | 
|---|
|  |  |  | /// 查询支付宝退款订单信息 | 
|---|
|  |  |  | /// </summary> | 
|---|
|  |  |  | /// <param name="input"></param> | 
|---|
|  |  |  | /// <returns></returns> | 
|---|
|  |  |  | public async Task<AlipayTradeFastpayRefundQueryResponse> QueryAlipayTradeRefund(OrderInQuiryInput input) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | AlipayTradeFastpayRefundQueryResponse response = await QueryTradeRefund(input.OutTradeNo, input.OutRefundNo); | 
|---|
|  |  |  | return response; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | public async Task<AlipayTradeRefundResponse> TradeRefund(AlipayTradeRefundRequest input) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | AlipayTradeRefundResponse response = await TradeRefund(input.OutTradeNo, input.OutRefundNo, input.RefundAmount); | 
|---|
|  |  |  | return response; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | private async Task<AlipayTradeRefundResponse> TradeRefund(string outTradeNo, string outRefundNo, string refundAmount) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | Dictionary<string, object> runtime_ = new Dictionary<string, object> | 
|---|
|  |  |  | { | 
|---|
|  |  |  | { | 
|---|
|  |  |  | "ignoreSSL", | 
|---|
|  |  |  | _kernel.GetConfig("ignoreSSL") | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | { | 
|---|
|  |  |  | "httpProxy", | 
|---|
|  |  |  | _kernel.GetConfig("httpProxy") | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | { "connectTimeout", 15000 }, | 
|---|
|  |  |  | { "readTimeout", 15000 }, | 
|---|
|  |  |  | { | 
|---|
|  |  |  | "retry", | 
|---|
|  |  |  | new Dictionary<string, int?> { { "maxAttempts", 0 } } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }; | 
|---|
|  |  |  | TeaRequest _lastRequest = null; | 
|---|
|  |  |  | Exception innerException = null; | 
|---|
|  |  |  | long _now = DateTime.Now.Millisecond; | 
|---|
|  |  |  | int _retryTimes = 0; | 
|---|
|  |  |  | while (TeaCore.AllowRetry((IDictionary)runtime_["retry"], _retryTimes, _now)) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | if (_retryTimes > 0) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | int backoffTime = TeaCore.GetBackoffTime((IDictionary)runtime_["backoff"], _retryTimes); | 
|---|
|  |  |  | if (backoffTime > 0) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | TeaCore.Sleep(backoffTime); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | _retryTimes++; | 
|---|
|  |  |  | try | 
|---|
|  |  |  | { | 
|---|
|  |  |  | TeaRequest teaRequest = new TeaRequest(); | 
|---|
|  |  |  | Dictionary<string, string> dictionary = new Dictionary<string, string> | 
|---|
|  |  |  | { | 
|---|
|  |  |  | { "method", "alipay.trade.refund" }, | 
|---|
|  |  |  | { | 
|---|
|  |  |  | "app_id", | 
|---|
|  |  |  | _kernel.GetConfig("appId") | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | { | 
|---|
|  |  |  | "timestamp", | 
|---|
|  |  |  | _kernel.GetTimestamp() | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | { "format", "json" }, | 
|---|
|  |  |  | { "version", "1.0" }, | 
|---|
|  |  |  | { | 
|---|
|  |  |  | "alipay_sdk", | 
|---|
|  |  |  | _kernel.GetSdkVersion() | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | { "charset", "UTF-8" }, | 
|---|
|  |  |  | { | 
|---|
|  |  |  | "sign_type", | 
|---|
|  |  |  | _kernel.GetConfig("signType") | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | { | 
|---|
|  |  |  | "app_cert_sn", | 
|---|
|  |  |  | _kernel.GetMerchantCertSN() | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | { | 
|---|
|  |  |  | "alipay_root_cert_sn", | 
|---|
|  |  |  | _kernel.GetAlipayRootCertSN() | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }; | 
|---|
|  |  |  | Dictionary<string, object> bizParams = new Dictionary<string, object> | 
|---|
|  |  |  | { | 
|---|
|  |  |  | { "out_trade_no", outTradeNo }, | 
|---|
|  |  |  | { "out_request_no", outRefundNo }, | 
|---|
|  |  |  | { "refund_amount", refundAmount } | 
|---|
|  |  |  | }; | 
|---|
|  |  |  | Dictionary<string, string> dictionary2 = new Dictionary<string, string>(); | 
|---|
|  |  |  | teaRequest.Protocol = _kernel.GetConfig("protocol"); | 
|---|
|  |  |  | teaRequest.Method = "POST"; | 
|---|
|  |  |  | teaRequest.Pathname = "/gateway.do"; | 
|---|
|  |  |  | teaRequest.Headers = new Dictionary<string, string> | 
|---|
|  |  |  | { | 
|---|
|  |  |  | { | 
|---|
|  |  |  | "host", | 
|---|
|  |  |  | _kernel.GetConfig("gatewayHost") | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | { "content-type", "application/x-www-form-urlencoded;charset=utf-8" } | 
|---|
|  |  |  | }; | 
|---|
|  |  |  | teaRequest.Query = _kernel.SortMap(TeaConverter.merge<string>(new object[3] | 
|---|
|  |  |  | { | 
|---|
|  |  |  | new Dictionary<string, string> { | 
|---|
|  |  |  | { | 
|---|
|  |  |  | "sign", | 
|---|
|  |  |  | _kernel.Sign(dictionary, bizParams, dictionary2, _kernel.GetConfig("merchantPrivateKey")) | 
|---|
|  |  |  | } }, | 
|---|
|  |  |  | dictionary, | 
|---|
|  |  |  | dictionary2 | 
|---|
|  |  |  | })); | 
|---|
|  |  |  | teaRequest.Body = TeaCore.BytesReadable(_kernel.ToUrlEncodedRequestBody(bizParams)); | 
|---|
|  |  |  | _lastRequest = teaRequest; | 
|---|
|  |  |  | TeaResponse response = await TeaCore.DoActionAsync(teaRequest, runtime_); | 
|---|
|  |  |  | Dictionary<string, object> respMap = await _kernel.ReadAsJsonAsync(response, "alipay.trade.refund"); | 
|---|
|  |  |  | if (_kernel.IsCertMode()) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | if (_kernel.Verify(respMap, _kernel.ExtractAlipayPublicKey(_kernel.GetAlipayCertSN(respMap)))) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | return TeaModel.ToObject<AlipayTradeRefundResponse>(_kernel.ToRespModel(respMap)); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | else if (_kernel.Verify(respMap, _kernel.GetConfig("alipayPublicKey"))) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | return TeaModel.ToObject<AlipayTradeRefundResponse>(_kernel.ToRespModel(respMap)); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | throw new TeaException(new Dictionary<string, string> { { "message", "验签失败,请检查支付宝公钥设置是否正确。" } }); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | catch (Exception ex) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | if (TeaCore.IsRetryable(ex)) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | innerException = ex; | 
|---|
|  |  |  | continue; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | throw ex; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | throw new TeaUnretryableException(_lastRequest, innerException); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | private async Task<AlipayTradeFastpayRefundQueryResponse> QueryTradeRefund(string outTradeNo, string outRequestNo) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | Dictionary<string, object> runtime_ = new Dictionary<string, object> | 
|---|
|  |  |  | { | 
|---|
|  |  |  | { | 
|---|
|  |  |  | "ignoreSSL", | 
|---|
|  |  |  | _kernel.GetConfig("ignoreSSL") | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | { | 
|---|
|  |  |  | "httpProxy", | 
|---|
|  |  |  | _kernel.GetConfig("httpProxy") | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | { "connectTimeout", 15000 }, | 
|---|
|  |  |  | { "readTimeout", 15000 }, | 
|---|
|  |  |  | { | 
|---|
|  |  |  | "retry", | 
|---|
|  |  |  | new Dictionary<string, int?> { { "maxAttempts", 0 } } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }; | 
|---|
|  |  |  | TeaRequest _lastRequest = null; | 
|---|
|  |  |  | Exception innerException = null; | 
|---|
|  |  |  | long _now = DateTime.Now.Millisecond; | 
|---|
|  |  |  | int _retryTimes = 0; | 
|---|
|  |  |  | while (TeaCore.AllowRetry((IDictionary)runtime_["retry"], _retryTimes, _now)) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | if (_retryTimes > 0) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | int backoffTime = TeaCore.GetBackoffTime((IDictionary)runtime_["backoff"], _retryTimes); | 
|---|
|  |  |  | if (backoffTime > 0) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | TeaCore.Sleep(backoffTime); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | _retryTimes++; | 
|---|
|  |  |  | try | 
|---|
|  |  |  | { | 
|---|
|  |  |  | TeaRequest teaRequest = new TeaRequest(); | 
|---|
|  |  |  | Dictionary<string, string> dictionary = new Dictionary<string, string> | 
|---|
|  |  |  | { | 
|---|
|  |  |  | { "method", "alipay.trade.fastpay.refund.query" }, | 
|---|
|  |  |  | { | 
|---|
|  |  |  | "app_id", | 
|---|
|  |  |  | _kernel.GetConfig("appId") | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | { | 
|---|
|  |  |  | "timestamp", | 
|---|
|  |  |  | _kernel.GetTimestamp() | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | { "format", "json" }, | 
|---|
|  |  |  | { "version", "1.0" }, | 
|---|
|  |  |  | { | 
|---|
|  |  |  | "alipay_sdk", | 
|---|
|  |  |  | _kernel.GetSdkVersion() | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | { "charset", "UTF-8" }, | 
|---|
|  |  |  | { | 
|---|
|  |  |  | "sign_type", | 
|---|
|  |  |  | _kernel.GetConfig("signType") | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | { | 
|---|
|  |  |  | "app_cert_sn", | 
|---|
|  |  |  | _kernel.GetMerchantCertSN() | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | { | 
|---|
|  |  |  | "alipay_root_cert_sn", | 
|---|
|  |  |  | _kernel.GetAlipayRootCertSN() | 
|---|
|  |  |  | } | 
|---|
|  |  |  | }; | 
|---|
|  |  |  | var queryOptions = new string[] { "gmt_refund_pay" }; | 
|---|
|  |  |  | Dictionary<string, object> bizParams = new Dictionary<string, object> | 
|---|
|  |  |  | { | 
|---|
|  |  |  | { "out_trade_no", outTradeNo }, | 
|---|
|  |  |  | { "out_request_no", outRequestNo }, | 
|---|
|  |  |  | { "query_options", queryOptions } | 
|---|
|  |  |  | }; | 
|---|
|  |  |  | Dictionary<string, string> dictionary2 = new Dictionary<string, string>(); | 
|---|
|  |  |  | teaRequest.Protocol = _kernel.GetConfig("protocol"); | 
|---|
|  |  |  | teaRequest.Method = "POST"; | 
|---|
|  |  |  | teaRequest.Pathname = "/gateway.do"; | 
|---|
|  |  |  | teaRequest.Headers = new Dictionary<string, string> | 
|---|
|  |  |  | { | 
|---|
|  |  |  | { | 
|---|
|  |  |  | "host", | 
|---|
|  |  |  | _kernel.GetConfig("gatewayHost") | 
|---|
|  |  |  | }, | 
|---|
|  |  |  | { "content-type", "application/x-www-form-urlencoded;charset=utf-8" } | 
|---|
|  |  |  | }; | 
|---|
|  |  |  | teaRequest.Query = _kernel.SortMap(TeaConverter.merge<string>(new object[3] | 
|---|
|  |  |  | { | 
|---|
|  |  |  | new Dictionary<string, string> { | 
|---|
|  |  |  | { | 
|---|
|  |  |  | "sign", | 
|---|
|  |  |  | _kernel.Sign(dictionary, bizParams, dictionary2, _kernel.GetConfig("merchantPrivateKey")) | 
|---|
|  |  |  | } }, | 
|---|
|  |  |  | dictionary, | 
|---|
|  |  |  | dictionary2 | 
|---|
|  |  |  | })); | 
|---|
|  |  |  | teaRequest.Body = TeaCore.BytesReadable(_kernel.ToUrlEncodedRequestBody(bizParams)); | 
|---|
|  |  |  | _lastRequest = teaRequest; | 
|---|
|  |  |  | TeaResponse response = await TeaCore.DoActionAsync(teaRequest, runtime_); | 
|---|
|  |  |  | Dictionary<string, object> respMap = await _kernel.ReadAsJsonAsync(response, "alipay.trade.fastpay.refund.query"); | 
|---|
|  |  |  | if (_kernel.IsCertMode()) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | if (_kernel.Verify(respMap, _kernel.ExtractAlipayPublicKey(_kernel.GetAlipayCertSN(respMap)))) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | return TeaModel.ToObject<AlipayTradeFastpayRefundQueryResponse>(_kernel.ToRespModel(respMap)); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | else if (_kernel.Verify(respMap, _kernel.GetConfig("alipayPublicKey"))) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | return TeaModel.ToObject<AlipayTradeFastpayRefundQueryResponse>(_kernel.ToRespModel(respMap)); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | throw new TeaException(new Dictionary<string, string> { { "message", "验签失败,请检查支付宝公钥设置是否正确。" } }); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | catch (Exception ex) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | if (TeaCore.IsRetryable(ex)) | 
|---|
|  |  |  | { | 
|---|
|  |  |  | innerException = ex; | 
|---|
|  |  |  | continue; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | throw ex; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | throw new TeaUnretryableException(_lastRequest, innerException); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|