Yoyo.Abp.Alipay
DefatultAlipayHelper.cs
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Threading.Tasks;
using Abp.Extensions;
using Alipay.AopSdk.AspnetCore;
using Alipay.AopSdk.Core.Domain;
using Alipay.AopSdk.Core.Request;
using Alipay.AopSdk.Core.Response;
using Alipay.AopSdk.F2FPay.Business;
using Alipay.AopSdk.F2FPay.Domain;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using QRCoder;
using Yoyo.Abp.FTF;
using Yoyo.Abp.Other;
using Yoyo.Abp.WapPay;
using Yoyo.Abp.WebPay;
using F2FResultEnum = Alipay.AopSdk.F2FPay.Model.ResultEnum;
namespace Yoyo.Abp
{
///
/// 支付宝支付默认实现
///
public clast DefatultAlipayHelper : IAlipayHelper
{
private readonly AlipayF2FService _alipayF2FService;
private readonly AlipayService _alipayService;
private readonly FTFConfig _fTFConfig;
public DefatultAlipayHelper(
AlipayF2FService alipayF2FService,
AlipayService alipayService,
IOptions fTFConfigOptions
)
{
_alipayF2FService = alipayF2FService;
_alipayService = alipayService;
_fTFConfig = fTFConfigOptions.Value;
}
#region 面对面支付
///
/// 面对面支付(异步消息通知),返回生成的图片二维码byte数组
///
/// 支付信息
/// 异步消息通知地址
/// 面对面支付配置信息(不填则使用全局配置的)
/// 二维码图片字节数组
public async Task FTFPay(AlipayTradePrecreateContentBuilder input, string asyncNotifyUrl, FTFConfig fTFConfig = null)
{
return await this.FTFGenQRCode(input, asyncNotifyUrl, null, fTFConfig);
}
///
/// 面对面支付(轮询),返回生成的图片二维码byte数组
///
/// 支付信息
///
/// 面对面支付配置信息(不填则使用全局配置的)
///
public async Task FTFPay(AlipayTradePrecreateContentBuilder input, Action loopQueryAction, FTFConfig fTFConfig = null)
{
return await this.FTFGenQRCode(input, null, loopQueryAction, fTFConfig);
}
///
/// 面对面支付结果查询
///
///
///
public async Task FTFQuery(string outTradeNo)
{
return await _alipayF2FService.TradeQueryAsync(outTradeNo);
}
#endregion
#region PC Web 支付
///
/// PC Web 支付,返回支付宝支付链接
///
/// 支付信息和回调通知信息
/// 支付选项,如果为空则使用添加时内置的
/// 返回支付宝支付链接
public async Task WebPay(WebPayInput input, AlipayOptions options = null)
{
await Task.Yield();
if (input.Data.ProductCode.IsNullOrWhiteSpace())
{
input.Data.ProductCode = YoYoAlipayConsts.ProductCode_FAST_INSTANT_TRADE_PAY;
}
var request = new AlipayTradePagePayRequest();
// 设置同步回调地址
request.SetReturnUrl(input.SynchronizationCallbackUrl);
// 设置异步通知接收地址
request.SetNotifyUrl(input.AsyncNotifyUrl);
// 将业务model载入到request
request.SetBizModel(input.Data);
// 发起支付
var response = this._alipayService.SdkExecute(request);
// 返回回调地址
var tmpOptions = options ?? _alipayService.Options;
return new WebPayOutput()
{
Response = response,
RedirectUrl = $"{tmpOptions.Gatewayurl}?{response.Body}"
};
}
#endregion
#region Mobile WAP 支付
public async Task WapPay(WapPayInput input, AlipayOptions options = null)
{
await Task.Yield();
// 设置产品代码
if (input.Data.ProductCode.IsNullOrWhiteSpace())
{
input.Data.ProductCode = YoYoAlipayConsts.ProductCode_QUICK_WAP_WAY;
}
// 设置支付中途退出返回商户网站地址
if (input.Data.QuitUrl.IsNullOrWhiteSpace())
{
input.Data.QuitUrl = input.QuitUrl;
}
var request = new AlipayTradeWapPayRequest();
// 设置同步回调地址
request.SetReturnUrl(input.SynchronizationCallbackUrl);
// 设置异步通知接收地址
request.SetNotifyUrl(input.AsyncNotifyUrl);
// 将业务model载入到request
request.SetBizModel(input.Data);
// 发起支付
var response = await this._alipayService.PageExecuteAsync(request);
return new WapPayOutput()
{
Response = response,
Body = response.Body
};
}
#endregion
#region 订单查询
///
/// 订单查询
///
/// 查询数据
///
public async Task Query(OrderQueryInput input)
{
return await this.Query(input.Data);
}
///
/// 订单查询
///
/// 查询数据
///
public async Task Query(AlipayTradeQueryModel input)
{
var request = new AlipayTradeQueryRequest();
request.SetBizModel(input);
var response = await _alipayService.ExecuteAsync(request);
return response;
}
///
/// 订单查询
///
/// 商户系统订单编码
/// 支付宝订单编码
///
public async Task Query(string tradeNo, string alipayTradeNo)
{
AlipayTradeQueryModel model = new AlipayTradeQueryModel
{
OutTradeNo = tradeNo,
TradeNo = alipayTradeNo
};
return await this.Query(model);
}
#endregion
#region 订单退款
///
/// 订单退款
///
/// 退款数据
///
public async Task Refund(RefundInput input)
{
return await this.Refund(input.Data);
}
///
/// 订单退款
///
/// 退款数据
///
public async Task Refund(AlipayTradeRefundModel input)
{
AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
request.SetBizModel(input);
var response = await _alipayService.ExecuteAsync(request);
return response;
}
///
/// 订单退款
///
/// 商户订单号
/// 支付宝交易号
/// 退款金额
/// 退款原因
/// 退款单号
///
public async Task Refund(string tradeno, string alipayTradeNo, string refundAmount, string refundReason, string refundNo)
{
var model = new AlipayTradeRefundModel();
model.OutTradeNo = tradeno;
model.TradeNo = alipayTradeNo;
model.RefundAmount = refundAmount;
model.RefundReason = refundReason;
model.OutRequestNo = refundNo;
return await this.Refund(model);
}
#endregion
#region 订单退款查询
///
/// 订单退款查询
///
/// 查询信息
///
public async Task RefundQuery(RefundQueryInput input)
{
return await this.RefundQuery(input.Data);
}
///
/// 订单退款查询
///
/// 查询信息
///
public async Task RefundQuery(AlipayTradeFastpayRefundQueryModel input)
{
if (string.IsNullOrEmpty(input.OutRequestNo))
{
input.OutRequestNo = input.OutTradeNo;
}
var request = new AlipayTradeFastpayRefundQueryRequest();
request.SetBizModel(input);
AlipayTradeFastpayRefundQueryResponse response = await _alipayService.ExecuteAsync(request);
return response;
}
///
/// 订单退款查询
///
/// 商户订单号
/// 支付宝交易号
/// 退款单号
///
public async Task RefundQuery(string tradeno, string alipayTradeNo, string refundNo)
{
var model = new AlipayTradeFastpayRefundQueryModel();
model.OutTradeNo = tradeno;
model.TradeNo = alipayTradeNo;
model.OutRequestNo = refundNo;
return await this.RefundQuery(model);
}
#endregion
#region 关闭订单
///
/// 关闭订单
///
/// 关闭订单数据
///
public async Task OrderClose(OrderCloseInput input)
{
return await this.OrderClose(input.Data);
}
///
/// 关闭订单
///
/// 关闭订单数据
///
public async Task OrderClose(AlipayTradeCloseModel input)
{
var request = new AlipayTradeCloseRequest();
request.SetBizModel(input);
var response = await _alipayService.ExecuteAsync(request);
return response;
}
///
/// 关闭订单
///
/// 商户订单号
/// 支付宝交易号
///
public async Task OrderClose(string tradeno, string alipayTradeNo)
{
var model = new AlipayTradeCloseModel()
{
OutTradeNo = tradeno,
TradeNo = alipayTradeNo,
};
return await this.OrderClose(model);
}
#endregion
#region 回调获取请求数据
public async Task PayRequestCheck(HttpRequest request)
{
await Task.Yield();
var result = new PayRequestCheckOutput();
if (request.Method.ToLower() == "post")
{
result.SArray = GetRequestPost(request);
}
else
{
result.SArray = GetRequestGet(request);
}
if (result.SArray.Count != 0)
{
result.IsSuccess = _alipayService.RSACheckV1(result.SArray);
}
return result;
}
#endregion
#region FTF Pay 私有函数
///
/// 面对面支付生成支付二维码
///
/// 支付数据
/// 异步通知地址,为空则表示为同步轮询模式
/// 同步轮询回调函数
/// 面对面支付其它配置
///
private async Task FTFGenQRCode(AlipayTradePrecreateContentBuilder input, string asyncNotifyUrl, Action loopQueryAction, FTFConfig fTFConfig)
{
// 参数检测
var isAsyncNotify = !asyncNotifyUrl.IsNullOrWhiteSpace();
if (!isAsyncNotify && loopQueryAction == null)
{
throw new NullReferenceException("轮询模式下 loopQueryAction 不能为空!");
}
// 收款账号检测,如果为空则默认填入全局配置的Uid
if (input.seller_id.IsNullOrWhiteSpace())
{
input.seller_id = this._alipayService.Options.Uid;
}
Bitmap bitmap = null;
MemoryStream memoryStream = null;
var message = string.Empty;
//推荐使用轮询撤销机制,不推荐使用异步通知,避免单边账问题发生。
AlipayF2FPrecreateResult precreateResult = null;
// 异步通知
if (isAsyncNotify)
{
precreateResult = await _alipayF2FService.TradePrecreateAsync(input, asyncNotifyUrl);
}// 同步轮询
else
{
precreateResult = await _alipayF2FService.TradePrecreateAsync(input);
}
switch (precreateResult.Status)
{
case F2FResultEnum.SUCCESS:
// 将链接用二维码工具生成二维码打印出来,顾客可以用支付宝钱包扫码支付。
bitmap = RenderQrCode(precreateResult.response.QrCode);
// 同步轮询模式,触发轮询回调函数
if (!isAsyncNotify)
{
loopQueryAction.Invoke(precreateResult);
}
break;
case F2FResultEnum.FAILED:
message = $"生成二维码失败: {precreateResult.response.Body}";
break;
case F2FResultEnum.UNKNOWN:
message = "生成二维码失败:" + (precreateResult.response == null ? "配置或网络异常,请检查后重试" : "系统异常,请更新外部订单后重新发起请求");
break;
}
// 如果位图为空,则生成错误提示二维码
if (bitmap == null)
{
bitmap = new Bitmap(fTFConfig == null ? this._fTFConfig?.QRCodeGenErrorImageFullPath : fTFConfig.QRCodeGenErrorImageFullPath);
}
// 转换成字节数组
memoryStream = new MemoryStream();
bitmap.Save(memoryStream, ImageFormat.Png);
var imgBuffer = memoryStream.GetBuffer();
// 释放资源
memoryStream.Dispose();
bitmap.Dispose();
return new FTFOutput()
{
QRCodeImageBuffer = imgBuffer,
IsSuccess = precreateResult.Status == F2FResultEnum.SUCCESS,
Message = message
};
}
///
/// FTF渲染二维码
///
///
///
private Bitmap RenderQrCode(string str, FTFConfig fTFConfig = null)
{
var eccLevel = QRCodeGenerator.ECCLevel.L;
using (var qrGenerator = new QRCodeGenerator())
{
using (var qrCodeData = qrGenerator.CreateQrCode(str, eccLevel))
{
using (var qrCode = new QRCode(qrCodeData))
{
var bp = qrCode.GetGraphic(20, Color.Black, Color.White,
new Bitmap(fTFConfig == null ? this._fTFConfig?.QRCodeIconFullPath : fTFConfig.QRCodeIconFullPath),
15);
return bp;
}
}
}
}
#endregion
#region 解析请求参数
private Dictionary GetRequestGet(HttpRequest request)
{
Dictionary sArray = new Dictionary();
ICollection requessatem = request.Query.Keys;
foreach (var item in requessatem)
{
sArray.Add(item, request.Query[item]);
}
return sArray;
}
private Dictionary GetRequestPost(HttpRequest request)
{
Dictionary sArray = new Dictionary();
ICollection requessatem = request.Form.Keys;
foreach (var item in requessatem)
{
sArray.Add(item, request.Form[item]);
}
return sArray;
}
#endregion
}
}