You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

221 lines
10 KiB
C#

9 months ago
using Aop.Api;
using Aop.Api.Request;
using Aop.Api.Response;
using NLog;
using POSV.ShoppingCart;
using POSV.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace POSV.PayApi
{
public class AlipayApi
{
private static Logger logger = NLog.LogManager.GetCurrentClassLogger();
private static Dictionary<AccountTypeEnum, DefaultAopClient> clientDic = new Dictionary<AccountTypeEnum, DefaultAopClient>();
private static Dictionary<AccountTypeEnum, string> appAuthTokenDic = new Dictionary<AccountTypeEnum, string>();
/// <summary>
/// 获取支付宝账户信息
/// </summary>
/// <param name="accountType"></param>
/// <returns></returns>
public static Tuple<string, DefaultAopClient> GetAlipayInfo(AccountTypeEnum accountType)
{
Tuple<string, DefaultAopClient> result = null;
switch (accountType)
{
case AccountTypeEnum.:
{
if (clientDic.ContainsKey(AccountTypeEnum.) && appAuthTokenDic.ContainsKey(AccountTypeEnum.))
{
return new Tuple<string, DefaultAopClient>(appAuthTokenDic[AccountTypeEnum.], clientDic[AccountTypeEnum.]);
}
else
{
var parameter = OrderUtils.GetPayMode("04").Body;
string appId = parameter.ContainsKey("appid") ? parameter["appid"].ToString() : "";
string privateKey = parameter.ContainsKey("privatekey") ? parameter["privatekey"].ToString() : "";
string appAuthToken = parameter.ContainsKey("appAuthToken") ? parameter["appAuthToken"].ToString() : "";
string storeNo = parameter.ContainsKey("storeNo") ? parameter["storeNo"].ToString() : "";
string signType = parameter.ContainsKey("signType") ? parameter["signType"].ToString() : "RSA";
DefaultAopClient client = null;
if ("RSA2".Equals(signType))
{
client = new DefaultAopClient(Global.Instance.AliPayServerUrl, appId, privateKey, "json", "utf-8", "RSA2");
}
else
{
client = new DefaultAopClient(Global.Instance.AliPayServerUrl, appId, privateKey, false);
}
clientDic.Add(AccountTypeEnum., client);
appAuthTokenDic.Add(AccountTypeEnum., appAuthToken);
return new Tuple<string, DefaultAopClient>(appAuthToken, client);
}
}
break;
}
return result;
}
/// <summary>
/// 支付宝退款申请
/// </summary>
/// <param name="accountType"></param>
/// <param name="tradeNo"></param>
/// <param name="totalAmount"></param>
/// <param name="refundNo"></param>
/// <param name="reason"></param>
/// <returns></returns>
public static Tuple<bool, string, AlipayTradeRefundResponse> RefundByAlipay(AccountTypeEnum accountType, string tradeNo, decimal totalAmount, string refundNo, string reason)
{
lock (Global.Instance.SyncLock)
{
try
{
logger.Info("订单[{0}]开始发起支付宝退款......", tradeNo);
AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
Dictionary<string, object> dic = new Dictionary<string, object>();
dic.Add("out_trade_no", tradeNo);
dic.Add("refund_amount", totalAmount);
dic.Add("refund_reason", reason?? "正常退款");
dic.Add("out_request_no", refundNo);
dic.Add("operator_id", Global.Instance.Worker.No);
dic.Add("store_id", Global.Instance.Worker.StoreInfo.No);
dic.Add("terminal_id", Global.Instance.Authc.PosNo);
request.BizContent = JsonUtils.Serialize(dic);
var info = GetAlipayInfo(accountType);
if (info != null)
{
var appAuthToken = info.Item1;
var client = info.Item2;
var result = client.Execute(request, null, appAuthToken);
logger.Info("订单[{0}]支付宝退款请求结果:{1}", tradeNo, JsonUtils.Serialize(result));
return new Tuple<bool, string, AlipayTradeRefundResponse>(true, null, result);
}
else
{
return new Tuple<bool, string, AlipayTradeRefundResponse>(false, "未配置支付宝支付参数", null);
}
}
catch (Exception ex)
{
logger.Error(ex, "订单[{0}]调用支付宝退款接口异常", tradeNo);
return new Tuple<bool, string, AlipayTradeRefundResponse>(false, "调用支付宝退款接口异常", null);
}
}
}
/// <summary>
/// 支付宝退款结果查询
/// </summary>
/// <param name="tradeNo"></param>
/// <returns></returns>
public static Tuple<bool, string, AlipayTradeFastpayRefundQueryResponse> QueryAlipayRefundResult(AccountTypeEnum accountType, string tradeNo, string refundNo)
{
lock (Global.Instance.SyncLock)
{
try
{
logger.Info("订单[{0}]开始发起支付宝退款查询请求......", tradeNo);
AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
Dictionary<string, object> dic = new Dictionary<string, object>();
dic.Add("out_request_no", refundNo);
dic.Add("out_trade_no", tradeNo);
request.BizContent = JsonUtils.Serialize(dic);
var info = GetAlipayInfo(accountType);
if (info != null)
{
var appAuthToken = info.Item1;
var client = info.Item2;
var result = client.Execute(request, null, appAuthToken);
logger.Info("订单[{0}]支付宝退款查询结果:{1}", tradeNo, JsonUtils.Serialize(result));
return new Tuple<bool, string, AlipayTradeFastpayRefundQueryResponse>(true, null, result);
}
else
{
return new Tuple<bool, string, AlipayTradeFastpayRefundQueryResponse>(false, "未配置支付宝支付参数", null);
}
}
catch (Exception ex)
{
logger.Error(ex, "订单[{0}]调用支付宝退款查询接口异常", tradeNo);
return new Tuple<bool, string, AlipayTradeFastpayRefundQueryResponse>(false, "调用支付宝退款查询接口异常", null);
}
}
}
/// <summary>
/// 支付宝退款+查询结果
/// </summary>
/// <param name="reMoney"></param>
/// <param name="tradeNo"></param>
/// <param name="reTradeNo"></param>
/// <returns></returns>
public static Tuple<bool, string> RefundAndQuery(AccountTypeEnum accountType, string tradeNo, decimal refundAmount, string reTradeNo, string reason, int timeout = 60)
{
try
{
var refundResponse = RefundByAlipay(accountType, tradeNo, refundAmount, reTradeNo, reason);
if (refundResponse.Item1)//请求成功
{
var refundResult = refundResponse.Item3;
if (refundResult.Code == "10000" || refundResult.Code == "10003")
{
int queryCount = 0;
int sleepTime = 3000;
if(timeout < 60)
{
timeout = 60;
}
queryCount = (60 * 1000 / sleepTime);
int i = 0; //60秒超时
while (i < queryCount)
{
var queryRefundResponse = QueryAlipayRefundResult(accountType, tradeNo, reTradeNo);
if (queryRefundResponse.Item1 && queryRefundResponse.Item3.Code == "10000")
{
return new Tuple<bool, string>(true, "退款成功!");
}
i++;
System.Threading.Thread.Sleep(3000);//睡眠3秒
}
if (i == queryCount)
{
return new Tuple<bool, string>(false, "查询退款结果超时,退单失败!");
}
}
else
{
return new Tuple<bool, string>(false, refundResult.Msg);
}
}
else
{
//请求失败
return new Tuple<bool, string>(false, refundResponse.Item2);
}
}
catch (Exception ex)
{
logger.Error(ex, "支付宝退款发生异常");
return new Tuple<bool, string>(false, "退款发生异常!");
}
return new Tuple<bool, string>(false, "退款失败!");
}
}
}