2025-04-21 14:10:27 +08:00

499 lines
19 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using MyCode.Project.Infrastructure.Common;
using MyCode.Project.Infrastructure.Utils;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Xml;
using Wolf.ExternalService.CMBPay.Common;
using Wolf.ExternalService.CMBPay.Core;
using Wolf.ExternalService.CMBPay.Core.Events;
using Wolf.ExternalService.CMBPay.Core.Utils;
using static MyCode.Project.Infrastructure.Constant.LxmConst;
namespace MyCode.Project.Infrastructure.PayModels
{
/// <summary>
/// 招行支付的底层类扩展,
/// 方法1 增加查询订单实际支付情况的接口
/// </summary>
public class ExtendedGateway : Gateway
{
#region
/// <summary>
/// 统一下单 接口类型
/// </summary>
private const string UnifiedOrderApiType = "unified.trade.micropay";
/// <summary>
/// 查询订单 接口类型
/// </summary>
private const string QueryApiType = "unified.trade.query";
/// <summary>
/// 关闭订单 接口类型
/// </summary>
private const string CloseOrderApiType = "unified.micropay.reverse";
#endregion
#region
/// <summary>
/// 通知
/// </summary>
public new Notify Notify => (Notify)base.Notify;
#endregion
#region
/// <summary>
/// 初始化一个<see cref="ExtendedGateway"/>类型的实例
/// </summary>
public ExtendedGateway() : this(new Merchant())
{
}
/// <summary>
/// 初始化一个<see cref="ExtendedGateway"/>类型的实例
/// </summary>
/// <param name="merchant">商家数据</param>
public ExtendedGateway(Merchant merchant) : base(merchant)
{
}
#endregion
#region
/// <summary>
/// 每隔5秒轮询判断用户各种支付的真实支付情况总共轮询5次
/// </summary>
/// <param name="auxiliary">辅助接口</param>
private void PollQueryTradeState(IAuxiliary auxiliary)
{
for (int i = 0; i < 5; i++)
{
Thread.Sleep(5000);
BuildQuery(auxiliary);
string dsds = Notify.TradeState.ToLower();
if (IsSuccessPay && Notify.TradeState.ToLower() == SUCCESS)
{
OnPaymentSucceed(new PaymentSucceedEventArgs(this));
return;
}
}
}
/// <summary>
/// 异步每隔5秒轮询判断用户是否支付总共轮询5次
/// </summary>
/// <param name="auxiliary">辅助接口</param>
/// <returns></returns>
private async Task PollQueryTradeStateAsync(IAuxiliary auxiliary)
{
await Task.Run(() => PollQueryTradeState(auxiliary));
}
/// <summary>
/// 查询订单的相关平台参数
/// </summary>
/// <param name="query"></param>
public void QueryOrderPay(Auxiliary query)
{
Task.Run(async () =>
{
await PollQueryTradeStateAsync(new Auxiliary()
{
TransactionId = query.TransactionId,
OutTradeNo = query.OutTradeNo
});
})
.GetAwaiter()
.GetResult();
}
/// <summary>
/// 生成查询订单参数
/// </summary>
/// <param name="auxiliary">辅助参数</param>
/// <returns></returns>
private INotify BuildQuery(IAuxiliary auxiliary)
{
InitQuery(auxiliary);
Commit();
return Notify;
}
/// <summary>
/// 初始化查询订单参数
/// </summary>
/// <param name="auxiliary">辅助参数</param>
private void InitQuery(IAuxiliary auxiliary)
{
Merchant.Service = QueryApiType;
InitAuxiliaryParameter(GatewayAuxiliaryType.Query, auxiliary);
}
#endregion
/// <summary>
/// 初始化订单参数
/// </summary>
/// <param name="action">操作</param>
private void InitOrderParameter(Action action = null)
{
GatewayData.Clear();
Merchant.NonceStr = Util.GenerateNonceStr();
Merchant.DeviceInfo = Wolf.ExternalService.CMBPay.Common.Constant.WEB;
action?.Invoke();
GatewayData.Add(Merchant, StringCase.Snake);
GatewayData.Add(Order, StringCase.Snake);
AddSign();
}
/// <summary>
/// 初始化辅助参数
/// </summary>
/// <param name="gatewayAuxiliaryType">辅助类型</param>
/// <param name="auxiliary">辅助参数</param>
private void InitAuxiliaryParameter(GatewayAuxiliaryType gatewayAuxiliaryType, IAuxiliary auxiliary)
{
auxiliary.Validate(gatewayAuxiliaryType);
Merchant.NonceStr = Util.GenerateNonceStr();
//Merchant.NotifyUrl = "";
GatewayData.Add(Merchant, StringCase.Snake);
GatewayData.Add(auxiliary, StringCase.Snake);
AddSign();
}
/// <summary>
/// 转换通知对象
/// </summary>
/// <returns></returns>
protected override INotify ToObject()
{
return GatewayData.ToObject<Notify>(StringCase.Snake);
}
/// <summary>
/// 转换通知对象
/// </summary>
/// <returns></returns>
protected override async Task<INotify> ToObjectAsync()
{
return await GatewayData.ToObjectAsync<Notify>(StringCase.Snake);
}
#region testfuyoupay()
/// <summary>
/// 富友扫客户支付码支付
/// </summary>
/// <param name="order"></param>
/// <param name="order_type">支付类型 ALIPAY , WECHAT, QQ(QQ 钱包), UNIONPAY(银联二维码) , BESTPAY(翼支付)</param>
/// <returns></returns>
public string FuiouScanpPay(Wolf.ExternalService.CMBPay.Barcodepay.Order order, string order_type)
{
Dictionary<string, string> map = new Dictionary<string, string>();
map.Add("version", "1.0");
map.Add("ins_cd", FuiouPayConst.ins_cd);
map.Add("mchnt_cd", order.OpUserId);
map.Add("term_id", FuiouPayConst.term_id);
map.Add("random_str", Guid.NewGuid().ToString("N"));
map.Add("sign", "");
map.Add("order_type", order_type);
map.Add("goods_des", order.Body);
map.Add("goods_detail", "");
map.Add("reserved_expire_minute", "1440");
map.Add("addn_inf", order.Attach);
map.Add("auth_code", order.AuthCode);
map.Add("mchnt_order_no", order.OutTradeNo);
map.Add("curr_type", "");
map.Add("order_amt", order.Amount.ToString());
map.Add("term_ip", FuiouPayConst.term_ip);
map.Add("txn_begin_ts", DateTime.Now.ToString("yyyyMMddhhmmss"));
map.Add("goods_tag", "");
map.Add("sence", "1");
map.Add("reserved_sub_appid", "");
map.Add("reserved_limit_pay", "");
string result = run(map, FuiouPayConst.fuiouScanpPayUrl);
return result;
}
#endregion
private static string run(Dictionary<string, string> map, string url)
{
Dictionary<string, string> reqs = new Dictionary<string, string>();
Dictionary<string, string> nvs = new Dictionary<string, string>();
foreach (KeyValuePair<string, string> kvp in map)
{
reqs.Add(kvp.Key, kvp.Value);
}
string sign = FuYouPayUtils.getSign(reqs);
reqs.Remove("sign");
reqs.Add("sign", sign);
XmlDocument doc = new XmlDocument();
XmlElement elem = doc.CreateElement("xml");
doc.AppendChild(elem);
foreach (KeyValuePair<string, string> kvp in reqs)
{
XmlElement elem2 = doc.CreateElement(kvp.Key);
elem2.InnerText = kvp.Value;
elem.AppendChild(elem2);
}
string reqBody = "<?xml version=\"1.0\" encoding=\"GBK\" standalone=\"yes\"?>" + doc.OuterXml;
LogHelper.Info("请求报文:" + reqBody);
reqBody = FuYouPayUtils.UrlEncode(reqBody, Encoding.GetEncoding(FuiouPayConst.charset));
nvs.Add("req", reqBody);
StringBuilder result = new StringBuilder("");
Infrastructure.Utils.HttpUtils httpUtils = new HttpUtils();
httpUtils.post(url, nvs, result);
string data = HttpUtility.UrlDecode(result.ToString(), Encoding.GetEncoding(FuiouPayConst.charset));
LogHelper.Info("在线支付返回报文:" + data);
return data;
}
#region FuyouOnlinePay()
/// <summary>
/// 富友客户扫商家的二维码支付
/// </summary>
/// <param name="order"></param>
/// <param name="order_type">支付类型 ALIPAY , WECHAT, QQ(QQ 钱包), UNIONPAY(银联二维码) , BESTPAY(翼支付)</param>
/// <returns></returns>
public string FuiouOnlinePay(FuiouOrder order, string order_type)
{
Dictionary<string, string> map = new Dictionary<string, string>();
map.Add("order_type", order_type);
map.Add("goods_des", order.Body);
map.Add("reserved_expire_minute", "1440");
map.Add("addn_inf", order.Attach);
map.Add("mchnt_order_no", order.OutTradeNo);
map.Add("order_amt", order.Amount.ToString());
map.Add("version", "1.0");
map.Add("ins_cd", FuiouPayConst.ins_cd);
map.Add("mchnt_cd", order.OpUserId);
//map.Add("mchnt_cd", FuiouPayConst.mchnt_cd);
map.Add("term_id", FuiouPayConst.term_id);
map.Add("random_str", Guid.NewGuid().ToString("N"));
map.Add("sign", "");
map.Add("goods_detail", "");
map.Add("curr_type", "");
map.Add("term_ip", order.SpbillCreateIp);//FuiouPayConst.term_ip);
map.Add("txn_begin_ts", DateTime.Now.ToString("yyyyMMddhhmmss"));
map.Add("goods_tag", "");
map.Add("notify_url", FuiouPayConst.notify_url);
map.Add("reserved_sub_appid", "");
map.Add("reserved_limit_pay", "");
map.Add("reserved_terminal_info", order.DeviceInfo);
string result = run(map, FuiouPayConst.fuiouOnlinePayUrl);
XmlDocument doc = new XmlDocument();
doc.LoadXml(result);
string ifok = doc.SelectSingleNode("/xml/result_code").InnerText;
if (ifok == "000000")
result = doc.SelectSingleNode("/xml/qr_code").InnerText;
else
result = doc.SelectSingleNode("/xml/result_msg").InnerText;
return result;
}
#endregion
/// <summary>
/// 解析富友的XML字符串为可读文本
/// </summary>
/// <param name="res"></param>
/// <returns></returns>
public string GetXMLString(string res)
{
res = HttpUtility.UrlDecode(res, Encoding.GetEncoding(FuiouPayConst.charset));
return res;
}
#region FuyouWXOnlinePay( /)
/// <summary>
/// 富友 公众号/服务窗统一下单
/// </summary>
/// <param name="order"></param>
/// <param name="order_type">支付类型 ALIPAY , JSAPI, QQ(QQ 钱包), UNIONPAY(银联二维码) , BESTPAY(翼支付) LETPAY-小程序</param>
/// <param name="openid"></param>
/// <param name="appid"></param>
/// <returns></returns>
public string FuyouWXOnlinePay(Wolf.ExternalService.CMBPay.Barcodepay.Order order, string order_type, string openid, string appid)
{
Dictionary<string, string> map = new Dictionary<string, string>();
map.Add("version", "1.0");
map.Add("ins_cd", FuiouPayConst.ins_cd);
map.Add("mchnt_cd", order.OpUserId);
map.Add("term_id", FuiouPayConst.term_id);
map.Add("random_str", Guid.NewGuid().ToString("N"));
map.Add("sign", "");
map.Add("goods_des", order.Body);
map.Add("goods_detail", "");
map.Add("goods_tag", "");
map.Add("txn_begin_ts", DateTime.Now.ToString("yyyyMMddhhmmss"));
map.Add("notify_url", FuiouPayConst.notify_url);
map.Add("limit_pay", "");
if (order_type == "WECHAT")
order_type = "JSAPI";
else if (order_type == "ALIPAY")
order_type = "FWC";
else if (order_type == "LETPAY")
order_type = "LETPAY";
map.Add("trade_type", order_type);
map.Add("addn_inf", order.Attach);
map.Add("openid", "");
map.Add("product_id", "");
map.Add("sub_openid", openid);
map.Add("sub_appid", appid);
map.Add("reserved_expire_minute", "1440");
map.Add("mchnt_order_no", order.OutTradeNo);
map.Add("curr_type", "CNY");
map.Add("order_amt", order.Amount.ToString());
map.Add("term_ip", FuiouPayConst.term_ip);
string result = run(map, FuiouPayConst.fuiouOnlineWxPayUrl);
LogHelper.Info(result);
XmlDocument doc = new XmlDocument();
doc.LoadXml(result);
string ifok = doc.SelectSingleNode("/xml/result_code").InnerText;
if (ifok == "000000")
result = doc.SelectSingleNode("/xml/reserved_pay_info").InnerText;
else
result = doc.SelectSingleNode("/xml/result_msg").InnerText;
return result;
}
#endregion
#region FuyouOnlinePay()
/// <summary>
/// 富友主动查询订单支付状态
/// </summary>
/// <param name="mchnt_order_no">商户订单交易号</param>
/// <param name="order_type">支付类型 ALIPAY , WECHAT, QQ(QQ 钱包), UNIONPAY(银联二维码) , BESTPAY(翼支付)</param>
/// <returns></returns>
public string FuyouQueryPay(string mchnt_order_no, string order_type, string mchnt_cd = "0002900F0370588")
{
Dictionary<string, string> map = new Dictionary<string, string>();
map.Add("order_type", order_type);
map.Add("mchnt_order_no", mchnt_order_no);
map.Add("version", "1.0");
map.Add("ins_cd", FuiouPayConst.ins_cd);
map.Add("mchnt_cd", mchnt_cd);
map.Add("term_id", FuiouPayConst.term_id);
map.Add("random_str", Guid.NewGuid().ToString("N"));
map.Add("sign", "");
string result = run(map, FuiouPayConst.fuiou_23_url);
//XmlDocument doc = new XmlDocument();
//doc.LoadXml(result);
//string ifok = doc.SelectSingleNode("/xml/result_code").InnerText;
//if (ifok == "000000")
// result = doc.SelectSingleNode("/xml/trans_stat").InnerText;
//else
// result = doc.SelectSingleNode("/xml/result_msg").InnerText;
return result;
}
#endregion
#region FuYouReturnMoney(退)
/// <summary>
/// 富友退款申请
/// </summary>
public string FuYouReturnMoney(string OutTradeNo, string order_type, string refund_order_no
, decimal total_amt, decimal refund_amt, string mchnt_cd = "")
{
string total = (total_amt * 100).ToString("0");
string refund = (refund_amt * 100).ToString("0");
Dictionary<string, string> map = new Dictionary<string, string>();
map.Add("version", "1.0");
map.Add("ins_cd", FuiouPayConst.ins_cd);
map.Add("mchnt_cd", mchnt_cd);
map.Add("term_id", FuiouPayConst.term_id);
map.Add("random_str", Guid.NewGuid().ToString("N"));
map.Add("sign", "");
map.Add("order_type", order_type);
map.Add("mchnt_order_no", OutTradeNo);
map.Add("total_amt", total);
map.Add("operator_id", "");
map.Add("reserved_fy_term_id", "");
map.Add("refund_amt", refund);
map.Add("refund_order_no", refund_order_no);
string result = run(map, FuiouPayConst.fuiou_24_url);
result = GetXMLString(result);
//XmlDocument doc = new XmlDocument();
//doc.LoadXml(result);
//string ifok = doc.SelectSingleNode("/xml/result_code").InnerText;
//if (ifok == "000000")
// result = doc.SelectSingleNode("/xml/reserved_refund_amt").InnerText;
//else
// result = doc.SelectSingleNode("/xml/result_msg").InnerText;
return result;
}
#endregion
#region FuYouRefundQuery(退)
/// <summary>
/// 富友退款申请进度查询
/// </summary>
/// <param name="refund_order_no">商户退款单号</param>
/// <param name="mchnt_cd">商户号, 富友分配的商户号</param>
/// <returns></returns>
public string FuYouRefundQuery(string refund_order_no
, string mchnt_cd = "")
{
Dictionary<string, string> map = new Dictionary<string, string>();
map.Add("version", "1.0");
map.Add("ins_cd", FuiouPayConst.ins_cd);
map.Add("mchnt_cd", mchnt_cd);
map.Add("term_id", FuiouPayConst.term_id);
map.Add("refund_order_no", refund_order_no);
map.Add("random_str", Guid.NewGuid().ToString("N"));
map.Add("sign", "");
string result = run(map, FuiouPayConst.fuiou_30_url);
result = GetXMLString(result);
//XmlDocument doc = new XmlDocument();
//doc.LoadXml(result);
//string ifok = doc.SelectSingleNode("/xml/result_code").InnerText;
//if (ifok == "000000")
// result = doc.SelectSingleNode("/xml/reserved_refund_amt").InnerText;
//else
// result = doc.SelectSingleNode("/xml/result_msg").InnerText;
return result;
}
#endregion
}
}