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.

241 lines
11 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.IO;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
namespace POSV.PayApi
{
public class WeixinApi
{
private static Logger logger = NLog.LogManager.GetCurrentClassLogger();
private static Dictionary<AccountTypeEnum, Tuple<string, string, string, string, string>> clientDic = new Dictionary<AccountTypeEnum, Tuple<string, string, string, string, string>>();
/// <summary>
/// 获取微信账户信息
/// </summary>
/// <param name="accountType"></param>
/// <returns></returns>
public static Tuple<string, string, string, string, string> GetWeixinInfo(AccountTypeEnum accountType)
{
Tuple<string, string, string, string, string> result = null;
switch (accountType)
{
case AccountTypeEnum.:
{
if (!clientDic.ContainsKey(AccountTypeEnum.))
{
var payMode = OrderUtils.GetPayMode("05");
var parameter = payMode.Body;
string appId = parameter.ContainsKey("appid") ? parameter["appid"].ToString() : "";
string mchId = parameter.ContainsKey("mchid") ? parameter["mchid"].ToString() : "";
string subMchId = parameter.ContainsKey("submchid") ? parameter["submchid"].ToString() : "";
string key = parameter.ContainsKey("appsecret") ? parameter["appsecret"].ToString() : "";
string certText = payMode.CertText;
clientDic.Add(AccountTypeEnum., new Tuple<string, string, string, string, string>(appId, mchId, subMchId, key, certText));
}
return clientDic[AccountTypeEnum.];
}
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, OrderRefundResult> RefundByWeixin(AccountTypeEnum accountType, string tradeNo, decimal totalAmount, decimal refundAmount, string refundNo, string reason)
{
lock (Global.Instance.SyncLock)
{
try
{
logger.Info("订单[{0}]开始发起微信退款......", tradeNo);
string nonceStr = "x86" + ObjectId.GenerateNewStringId();
string totalAmountStr = Convert.ToInt32(totalAmount * 100) + "";
string RefundAmountStr = Convert.ToInt32(refundAmount * 100) + "";
var accountInfo = GetWeixinInfo(accountType);
if(accountInfo != null)
{
if (!string.IsNullOrEmpty(accountInfo.Item5))
{
string appId = accountInfo.Item1;
string mchId = accountInfo.Item2;
string subMchId = accountInfo.Item3;
string appSecret = accountInfo.Item4;
string certText = accountInfo.Item5;
WxPayV3OrderRefundRequestData request = new WxPayV3OrderRefundRequestData(appId, mchId, subMchId, appSecret, nonceStr, null, tradeNo, refundNo, totalAmountStr, RefundAmountStr, "SNY", reason);
byte[] certDataArray = Convert.FromBase64String(certText);
X509Certificate2 cert = new X509Certificate2(certDataArray, mchId);
var refundResult = WxPayV3.OrderRefund(request, cert);
logger.Info("订单[{0}]微信退款请求结果:{1}", tradeNo, JsonUtils.Serialize(refundResult));
if ("SUCCESS".Equals(refundResult.return_code))
{
if ("SUCCESS".Equals(refundResult.result_code))
{
return new Tuple<bool, string, OrderRefundResult>(true, null, refundResult);
}
else
{
return new Tuple<bool, string, OrderRefundResult>(false, refundResult.err_code + refundResult.err_code_des, null);
}
}
else
{
return new Tuple<bool, string, OrderRefundResult>(false, refundResult.return_msg, null);
}
}
else
{
return new Tuple<bool, string, OrderRefundResult>(false, "未配置微信支付证书(退款必须)", null);
}
}
else
{
return new Tuple<bool, string, OrderRefundResult>(false, "未配置微信支付参数", null);
}
}
catch (Exception ex)
{
logger.Error(ex, "订单[{0}]调用微信退款接口异常", tradeNo);
return new Tuple<bool, string, OrderRefundResult>(false, "调用微信退款接口异常", null);
}
}
}
/// <summary>
/// 微信退款结果查询
/// </summary>
/// <param name="tradeNo"></param>
/// <returns></returns>
public static Tuple<bool, string, RefundQueryResult> QueryWeixinRefundResult(AccountTypeEnum accountType, string tradeNo, string refundNo)
{
lock (Global.Instance.SyncLock)
{
try
{
logger.Info("订单[{0}]开始发起微信退款查询请求......", tradeNo);
string nonceStr = "x86" + ObjectId.GenerateNewStringId();
var accountInfo = GetWeixinInfo(accountType);
if (accountInfo != null)
{
string appId = accountInfo.Item1;
string mchId = accountInfo.Item2;
string subMchId = accountInfo.Item3;
string appSecret = accountInfo.Item4;
WxPayV3RefundQueryRequestData request = new WxPayV3RefundQueryRequestData(appId, mchId, subMchId, appSecret, nonceStr, null, tradeNo, refundNo, null);
var queryResult = WxPayV3.RefundQuery(request);
logger.Info("订单[{0}]微信退款查询结果:{1}", tradeNo, JsonUtils.Serialize(queryResult));
if ("SUCCESS".Equals(queryResult.return_code))
{
if ("SUCCESS".Equals(queryResult.result_code))
{
return new Tuple<bool, string, RefundQueryResult>(true, null, queryResult);
}
else
{
return new Tuple<bool, string, RefundQueryResult>(false, queryResult.err_code + queryResult.err_code_des, null);
}
}
else
{
return new Tuple<bool, string, RefundQueryResult>(false, queryResult.return_msg, null);
}
}
else
{
return new Tuple<bool, string, RefundQueryResult>(false, "未配置微信支付参数", null);
}
}
catch (Exception ex)
{
logger.Error(ex, "订单[{0}]调用微信退款查询接口异常", tradeNo);
return new Tuple<bool, string, RefundQueryResult>(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 totalAmount, decimal refundAmount, string reTradeNo, string reason, int timeout = 60)
{
try
{
var refundResponse = RefundByWeixin(accountType, tradeNo, totalAmount, refundAmount, reTradeNo, reason);
if (refundResponse.Item1)//请求成功
{
//int queryCount = 0;
//int sleepTime = 3000;
//if(timeout < 60)
//{//微信退款较慢显示最小60秒查询
// timeout = 60;
//}
//queryCount = (timeout * 1000 / sleepTime);
//int i = 0; //60秒超时
//while (i < queryCount)
//{
// var queryRefundResponse = QueryWeixinRefundResult(accountType, tradeNo, reTradeNo);
// if (queryRefundResponse.Item1 && queryRefundResponse.Item3.refund_status_list.Count > 0 && queryRefundResponse.Item3.refund_status_list[0] == "SUCCESS")
// {
// return new Tuple<bool, string>(true, "退款成功!");
// }
// i++;
// System.Threading.Thread.Sleep(3000);//睡眠3秒
//}
//if (i == queryCount)
//{
// return new Tuple<bool, string>(false, "查询退款结果超时,退单失败!");
//}
return new Tuple<bool, string>(true, "退款成功!");
}
else if ("ERROR订单已全额退款".Equals(refundResponse.Item2))
{
return new Tuple<bool, string>(true, "退款成功!");
}
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, "退款失败!");
}
}
}