(精华)2020年10月28日 支付宝 ASP.NET Core 使用支付宝当面付之扫码支付

扫码支付简单介绍

扫码支付是支付宝当面付中的一种支付方式,当面付包含条码支付、扫码支付、声波支付。

扫码支付,指用户打开支付宝钱包中的“扫一扫”功能,扫描商家展示在某收银场景下的二维码并进行支付的模式。该模式适用于线下实体店支付、面对面支付等场景。

使用示例:

1.某直播平台充值在这里插入图片描述
2.某视频网站开通vip在这里插入图片描述
扫码支付比传统的跳转网页支付方便快捷。

业务流程:在这里插入图片描述
使用步骤:

  1. 收银员在商家收银系统操作生成支付宝订单,并生成二维码;
  2. 用户登录支付宝钱包,点击首页“付款-扫码付”或直接点击“扫一扫”,进入扫一扫界面;
  3. 用户扫收银员提供的二维码,核对金额,确认支付;
  4. 用户付款后商家收银系统会拿到支付成功或者失败的结果。

配置

新建一个ASP.NET Core 3.1 MVC项目在这里插入图片描述
1.配置SDK
新建一个Config类,在里面存储我们的配置。

public class Config
{
	// 应用ID,您的APPID
	public static string AppId = "";

	/// <summary>
	/// 合作商户uid
	/// </summary>
	public static string Uid = "";

	// 支付宝网关
	public static string Gatewayurl = "https://openapi.alipaydev.com/gateway.do";

	// 商户私钥,您的原始格式RSA私钥
	public static string PrivateKey = "";

	// 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
	public static string AlipayPublicKey = "";

	// 签名方式
	public static string SignType = "RSA2";

	// 编码格式
	public static string CharSet = "UTF-8";
}

实现扫码支付

新建控制器FTFPayController

1.生成二维码Action

/// <summary>
/// 生成支付二维码
/// </summary>
/// <param name="orderName">订单名称</param>
/// <param name="orderAmount">订单金额</param>
/// <param name="outTradeNo">订单号</param>
/// <returns></returns>
[HttpGet]
public IActionResult ScanCodeGen(string orderName, string orderAmount, string outTradeNo)
{

	AlipayTradePrecreateContentBuilder builder = BuildPrecreateContent(orderName,orderAmount,outTradeNo);

	//如果需要接收扫码支付异步通知,那么请把下面两行注释代替本行。
	//推荐使用轮询撤销机制,不推荐使用异步通知,避免单边账问题发生。
	AlipayF2FPrecreateResult precreateResult = _serviceClient.tradePrecreate(builder);
	//string notify_url = "http://10.5.21.14/Pay/Notify";  //商户接收异步通知的地址
	//AlipayF2FPrecreateResult precreateResult = serviceClient.tradePrecreate(builder, notify_url);

	//以下返回结果的处理供参考。
	//payResponse.QrCode即二维码对于的链接
	//将链接用二维码工具生成二维码打印出来,顾客可以用支付宝钱包扫码支付。
	var bitmap = new Bitmap(Path.Combine(_hostingEnvironment.WebRootPath, "images/error.png"));
	switch (precreateResult.Status)
	{
		case ResultEnum.SUCCESS:
			bitmap.Dispose();
			bitmap=RenderQrCode(precreateResult.response.QrCode);
			//轮询订单结果
			//根据业务需要,选择是否新起线程进行轮询
			ParameterizedThreadStart parStart = new ParameterizedThreadStart(LoopQuery);
			Thread myThread = new Thread(parStart);
			object o = precreateResult.response.OutTradeNo;
			myThread.Start(o);
			break;
		case ResultEnum.FAILED:
			Console.WriteLine("生成二维码失败:"+ precreateResult.response.Body);
			break;

		case ResultEnum.UNKNOWN:
			Console.WriteLine("生成二维码失败:" + (precreateResult.response == null ? "配置或网络异常,请检查后重试" : "系统异常,请更新外部订单后重新发起请求"));
			break;
	}
	MemoryStream ms = new MemoryStream();
	bitmap.Save(ms, ImageFormat.Png);
	byte[] bytes = ms.GetBuffer();
	return File(bytes, "image/png");
}

2.构造支付请求数据

/// <summary>
/// 构造支付请求数据
/// </summary>
/// <param name="orderName">订单名称</param>
/// <param name="orderAmount">订单金额</param>
/// <param name="outTradeNo">订单编号</param>
/// <returns>请求结果集</returns>
private AlipayTradePrecreateContentBuilder BuildPrecreateContent(string orderName,string orderAmount,string outTradeNo)
{
	//线上联调时,请输入真实的外部订单号。
	if (string.IsNullOrEmpty(outTradeNo))
	{
		outTradeNo = System.DateTime.Now.ToString("yyyyMMddHHmmss") + "0000" + (new Random()).Next(1, 10000).ToString();
	}

	AlipayTradePrecreateContentBuilder builder = new AlipayTradePrecreateContentBuilder();
	//收款账号
	builder.seller_id = Config.Uid;
	//订单编号
	builder.out_trade_no = outTradeNo;
	//订单总金额
	builder.total_amount = orderAmount;
	//参与优惠计算的金额
	//builder.discountable_amount = "";
	//不参与优惠计算的金额
	//builder.undiscountable_amount = "";
	//订单名称
	builder.subject = orderName;
	//自定义超时时间
	builder.timeout_express = "5m";
	//订单描述
	builder.body = "";
	//门店编号,很重要的参数,可以用作之后的营销
	builder.store_id = "test store id";
	//操作员编号,很重要的参数,可以用作之后的营销
	builder.operator_id = "test";

	//传入商品信息详情
	List<GoodsInfo> gList = new List<GoodsInfo>();
	GoodsInfo goods = new GoodsInfo();
	goods.goods_id = "goods id";
	goods.goods_name = "goods name";
	goods.price = "0.01";
	goods.quantity = "1";
	gList.Add(goods);
	builder.goods_detail = gList;

	//系统商接入可以填此参数用作返佣
	//ExtendParams exParam = new ExtendParams();
	//exParam.sysServiceProviderId = "20880000000000";
	//builder.extendParams = exParam;

	return builder;

}

3.渲染二维码

/// <summary>
/// 渲染二维码
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
private Bitmap RenderQrCode(string str)
{
	QRCodeGenerator.ECCLevel eccLevel = QRCodeGenerator.ECCLevel.L;
	using (QRCodeGenerator qrGenerator = new QRCodeGenerator())
	{
		using (QRCodeData qrCodeData = qrGenerator.CreateQrCode(str, eccLevel))
		{
			using (QRCode qrCode = new QRCode(qrCodeData))
			{

				Bitmap bp= qrCode.GetGraphic(20, Color.Black, Color.White,
					new Bitmap(Path.Combine(_hostingEnvironment.WebRootPath, "images/alipay.png")), 15);
				return bp;
			}
		}
	}

}

4.轮询支付结果

/// <summary>
/// 轮询支付结果
/// </summary>
/// <param name="o">订单号</param>
public void LoopQuery(object o)
{
	AlipayF2FQueryResult queryResult = new AlipayF2FQueryResult();
	int count = 100;
	int interval = 10000;
	string outTradeNo = o.ToString();

	for (int i = 1; i <= count; i++)
	{
		Thread.Sleep(interval);
		queryResult = _serviceClient.tradeQuery(outTradeNo);
		if (queryResult?.Status == ResultEnum.SUCCESS)
		{
			DoSuccessProcess(queryResult);
			return;
		}
	}
	DoFailedProcess(queryResult);
}

/// <summary>
/// 请添加支付成功后的处理
/// </summary>
private void DoSuccessProcess(AlipayF2FQueryResult queryResult)
{
	//支付成功,请更新相应单据
	Console.WriteLine("扫码支付成功:商户订单号 " + queryResult.response.OutTradeNo);

}

/// <summary>
/// 请添加支付失败后的处理
/// </summary>
private void DoFailedProcess(AlipayF2FQueryResult queryResult)
{
	//支付失败,请更新相应单据
	Console.WriteLine("扫码支付失败:商户订单号 " + queryResult.response.OutTradeNo);
}

关于支付结果,可以使用轮询或者异步通知来获取,异步通知我这里没条件就没有演示,但是代码已经实现了的

具体使用步骤

1.生成二维码

生成二维码必须提供商户订单号、订单金额、订单名称三个参数,不然会出现错误。
2.扫描支付

打开手机支付宝,点开扫一扫,扫描二维码完成付款。

如果使用的是沙箱环境,那么必须下载沙箱版支付宝,使用正式版支付宝扫描沙箱环境api生成的二维码,会出现二维码失效,沙箱环境后台可以下载。沙箱环境必须使用沙箱环境账号。
3.支付结果

通过轮询获得的结果:在这里插入图片描述

©️2020 CSDN 皮肤主题: 猿与汪的秘密 设计师:上身试试 返回首页