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#
221 lines
10 KiB
C#
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, "退款失败!");
|
|
}
|
|
|
|
|
|
|
|
}
|
|
}
|