.NET6+furion+Senparc盛派SDK对接微信支付V3-扫码Native支付

2023-10-07 12:59

本文主要是介绍.NET6+furion+Senparc盛派SDK对接微信支付V3-扫码Native支付,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

参考文档

盛派微信支付V3帮助文档(第一种对接方式)

furion官方文档

微信支付文档

OSS.Clients.Pay参考文档(第二种对接方式)

一、Native支付简单介绍

1.简介与应用场景

简介:Native支付是指商户系统按微信支付协议生成支付二维码,用户再用微信“扫一扫”完成支付的模式。

应用场景:Native支付适用于PC网站、实体店单品或订单、媒体广告支付等场景

2.支付流程

简单流程:用户在登录PC网站进入商品列表点击商品选择支付,生成支付二维码,用户使用手机微信app”扫一扫“功能,扫描支付二维码唤起微信支付

 

 二、实战案例

备注:(我这里是引用的furion框架,具体的不详细介绍了可以看看官方文档),我提供两种的对接微信支付方法,第一个是用盛派的sdk,第二个是不用盛派的sdk

1.盛派sdk对接方式

管理Nuget包安装(Senparc.Weixin、Senparc.Weixin.TenPayV3)

Startup里注册微信缓存与盛派微信服务

services.AddMemoryCache();
services.AddSenparcWeixinServices(config);

Configure里配置

//启用微信配置var senparcSetting = App.GetOptions<SenparcSetting>();var senparcWeixinSetting = App.GetOptions<SenparcWeixinSetting>();var registerService = app.UseSenparcGlobal(env,senparcSetting,globalRegister => { }).UseSenparcWeixin(senparcWeixinSetting, (weixinRegister, weixinSetting) =>{//weixinRegister.RegisterMpAccount(senparcWeixinSetting, "测试公众号");//公众号配置!可以不用管weixinRegister.RegisterTenpayApiV3(weixinSetting, "微信支付V3");});

以上是furion框架写法,如果不用furion可以参考盛派帮助文档,如下:

在appsettings.json中添加:(这里面的appid、密钥、商户id等都在微信支付后台获取,我这里就不做演示了,网上教程很多)

 "SenparcWeixinSetting": {"IsDebug": true,//公众号"Token": "#{Token}#", "EncodingAESKey": "#{EncodingAESKey}#","WeixinAppId": "#{WeixinAppId}#","WeixinAppSecret": "#{WeixinAppSecret}#",//微信支付V3"TenPayV3_AppId": "#{TenPayV3_AppId}#",//appid"TenPayV3_AppSecret": "#{TenPayV3_AppSecret}#",//app密钥"TenPayV3_SubAppId": "#{TenPayV3_SubAppId}#","TenPayV3_SubAppSecret": "#{TenPayV3_SubAppSecret}#","TenPayV3_MchId": "#{TenPayV3_MchId}#",//商户id"TenPayV3_SubMchId": "#{TenPayV3_SubMchId}#", //子商户,没有可留空"TenPayV3_Key": "#{TenPayV3_Key}#","TenPayV3_TenpayNotify": "#{TenPayV3_TenpayNotify}#", //http://YourDomainName/TenpayApiV3/PayNotifyUrl/* 支付证书私钥* 1、支持明文私钥(无换行字符)* 2、私钥文件路径(如:~/App_Data/cert/apiclient_key.pem),注意:必须放在 App_Data 等受保护的目录下,避免泄露*/    "TenPayV3_PrivateKey": "#{TenPayV3_PrivateKey}#", //(新)证书私钥"TenPayV3_SerialNumber": "#{TenPayV3_SerialNumber}#", //(新)证书序列号"TenPayV3_ApiV3Key": "#{TenPayV3_APIv3Key}#", //(新)APIv3 密钥}

新增一个控制器WXAppService添加如下代码

上面初始化添加

/// <summary>
/// 用于初始化BasePayApis
/// </summary>
private readonly BasePayApis _basePayApis;
private readonly ISenparcWeixinSettingForTenpayV3 _tenpayV3Setting;

 构造函数WXAppService()里添加

_tenpayV3Setting = Senparc.Weixin.Config.SenparcWeixinSetting.TenpayV3Setting;
_basePayApis = new BasePayApis(_tenpayV3Setting);

然后就是主接口NativePayCode()

        /// <summary>/// (盛派sdk)使用 Native 支付下单/// </summary>/// <param name="productId"></param>/// <param name="hc"></param>/// <returns></returns>public async Task<string> NativePayCode()//可以根据自己的业务传商品id等{string MchId = App.Configuration["SenparcWeixinSetting:TenPayV3_MchId"];//获取appsettings.json中的TenPayV3_MchId的商户idstring AppId = App.Configuration["SenparcWeixinSetting:TenPayV3_AppId"];//获取appsettings.json中的TenPayV3_AppId的APPidvar price = 100;//这里是1:100,一块钱等于一百var name = "测试微信支付V3Native支付";var sp_billno = string.Format("{0}{1}{2}", MchId/*10位*/, SystemTime.Now.ToString("yyyyMMddHHmmss"),TenPayV3Util.BuildRandomStr(6));//自生成的订单号传入微信支付接口,方便后续回调处理var notifyUrl = "这里填的是你的支付回调地址(比如你的控制器是WXpayController,回调接口是PayNotifyUrl(),那回调地址就是你服务器的IP或域名加上WXpay/PayNotifyUrl),注意!Native支付的回调还需要在微信支付后台配置,微信支付-首页-产品中心-开发配置";TransactionsRequestData requestData = new(AppId, MchId, name, sp_billno, new TenpayDateTime(DateTime.Now.AddHours(1)), null,notifyUrl, null, new() { currency = "CNY", total = price }, null, null, null, null);BasePayApis basePayApis = new();var result = await basePayApis.NativeAsync(requestData);//调用微信Native支付//进行安全签名验证if (result.VerifySignSuccess == true){//成功的业务,我是把链接直接返回给前端让前端生成二维码return result.code_url;}else{//如果二维码链接生成失败的业务}return result.code_url;}

上面接口里只是最简单的支付案例,里面可以根据自己的业务添加逻辑代码

接下来测试一下效果,重新生成一下运行

复制一下data里面的链接,打开浏览器在线二维码图片生成器_二维码扫描软件下载_联图二维码

把链接放入框内生成二维码(当然.net也有很多二维码生成程序包,只不过我懒,不想写)

如下图:

 打开手机微信app扫一扫

 很好,很成功,接下来就是回调方法了

备注:我翻了微信V3支付的文档,没有找到测试环境,所以我没办法测试回调,以下回调方法仅供参考!!

/// <summary>/// (盛派sdk)weixin支付回调地址(在下单接口中设置的 notify_url)/// </summary>/// <returns></returns>public async Task PayNotifyUrl(){try{//获取微信服务器异步发送的支付通知信息var resHandler = new TenPayNotifyHandler(_httpContextAccessor.HttpContext);var orderReturnJson = await resHandler.AesGcmDecryptGetObjectAsync<OrderReturnJson>();//获取支付状态string trade_state = orderReturnJson.trade_state;//验证请求是否从微信发过来(安全)NotifyReturnData returnData = new();//验证可靠的支付状态if (orderReturnJson.VerifySignSuccess == true && trade_state == "SUCCESS"){returnData.code = "SUCCESS";//正确的订单处理Console.WriteLine(orderReturnJson.out_trade_no);//打印订单号//orderReturnJson里还有很多返回的参数,可根据需求自己拿取/* 提示:* 1、直到这里,才能认为交易真正成功了,可以进行数据库操作,但是别忘了返回规定格式的消息!* 2、上述判断已经具有比较高的安全性以外,还可以对访问 IP 进行判断进一步加强安全性。* 3、下面演示的是发送支付成功的模板消息提示,非必须。*/}else{returnData.code = "FAILD";//错误的订单处理returnData.message = "验证失败";//此处可以给用户发送支付失败提示等}}catch (Exception ex){WeixinTrace.WeixinExceptionLog(new WeixinException(ex.Message, ex));throw;}}

2.OSSClientsPay对接方式

参考文档:OSS.Clients.Pay

这个也是我偶然发现的

nuget下安装命令:

Install-Package OSS.Clients.Pay.Wechat

V3版接口采用fluent方式简化了调用流程,方便扩展,只需要继承基础类BasePostReq<TReq, TResp>,和 BaseGetReq<TReq, TResp> ,使用时调用SendAsync 扩展方法,内部已经完成了需要的加密验签等处理操作

我继续延用我上面盛派写的appsettings.json里的值了

新增接口OSSWXNativePayment()

        /// <summary>/// (OSS.PayCenter)使用Native支付下单/// </summary>/// <returns></returns>public async Task<string> OSSWXNativePayment(){string MchId = App.Configuration["SenparcWeixinSetting:TenPayV3_MchId"];//商户idstring AppId = App.Configuration["SenparcWeixinSetting:TenPayV3_AppId"];//APPidstring TenPayV3_Key = App.Configuration["SenparcWeixinSetting:TenPayV3_Key"];//V3keystring out_trade_no = SystemTime.Now.ToString("yyyyMMddHHmmss") + "123456";//订单号WechatPayHelper.pay_config = new WechatPayConfig(){app_id = AppId,mch_id = MchId,api_v3_key = TenPayV3_Key,cert_path = "D:\\publish\\TutorGPT\\1649499980_20230727_cert\\apiclient_cert.p12",//这个地方是微信支付后台配置的商户证书下载下来存在你本地的地址cert_password = MchId};var nResp = await new WechatNativePayReq(){amount = new WechatPayAmount(){total = 1//同样为1:100},description = "OSS.PayCenter测试商品",out_trade_no = out_trade_no,notify_url = "回调地址"}// .SetContextConfig(new WechatPayConfig(){})   // 可以设置当前上下文的配置信息,设置后本次请求将使用此配置,方便多应用的用户//.AddOptionalBodyPara("attach","附加数据")  // 添加可选参数.SendAsync();if (nResp.code!="0"&&nResp.code_url==null)//失败{//失败逻辑}return nResp.code_url;//成功返回链接}

上面cert_path参数商户证书是在微信支付后台配置,证书密码如果没在后台配置的话默认为商户id,具体的可以看微信支付文档教程,如下图

测试效果,重新生成一下运行:

  复制一下data里面的链接,打开浏览器在线二维码图片生成器_二维码扫描软件下载_联图二维码

扫码如下图:

 也成功了,然后就是回调了,这部分的回调是我自己捣鼓的,也是目前公司项目正在使用的

        /// <summary>/// (OSS.PayCenter)微信支付回调接口/// </summary>/// <returns></returns>[AllowAnonymous][UnitOfWork(true)]public async Task PostWxPayNotify(){try{string message = string.Empty;_httpContextAccessor.Request.EnableBuffering();_httpContextAccessor.Request.Body.Seek(0, SeekOrigin.Begin);Log.Information(_httpContextAccessor.Request.Method);//日志using (var reader = new StreamReader(_httpContextAccessor.Request.Body, Encoding.UTF8)){message = reader.ReadToEndAsync().Result;}//序列化为WeiXinResultDto实体类var weiXinResult = JsonConvert.DeserializeObject<WeiXinResultDto>(message);Log.Information($"微信支付回调通知信息为: {JsonConvert.SerializeObject(weiXinResult)}");//按照微信的规则密文解密返回数据var resourcestr = Dtos.AesGcm.AesGcmDecrypt(weiXinResult.resource.associated_data, weiXinResult.resource.nonce, weiXinResult.resource.ciphertext);Log.Information($"解密后信息为: {resourcestr}");var resourceResult = JsonConvert.DeserializeObject<resourceClass>(resourcestr);Log.Information($"微信支付回调订单信息为: {JsonConvert.SerializeObject(resourceResult)}");if (resourceResult.trade_state.Contains("SUCCESS")){//支付成功的逻辑...//微信支付可能返回的状态类型//SUCCESS:支付成功//REFUND:转入退款//NOTPAY:未支付//CLOSED:已关闭//REVOKED:已撤销(付款码支付) //USERPAYING:用户支付中(付款码支付) //PAYERROR:支付失败(其他原因,如银行返回失败)}if (resourceResult.trade_state.Contains("PAYERROR")){//支付失败的逻辑...}}catch (Exception ex){//报错记录日志Log.Error($"回调报错信息为:{ex.Message}");}}

 其中有<WeiXinResultDto>实体类、AesGcm解密方法类、<resourceClass>实体类,我在下方贴出代码

<WeiXinResultDto>实体类、<resourceClass>实体类、还有一些在此回调方法需要用到的实体类都在下面

    /// <summary>/// 微信支付后返回通知参数/// </summary>public class WeiXinResultDto{/// <summary>/// 通知id(由微信生成)/// </summary>public string id { get; set; }/// <summary>/// 通知创建时间/// </summary>public string create_time { get; set; }/// <summary>/// 通知类型/// </summary>public string resource_type { get; set; }/// <summary>/// 通知数据类型/// </summary>public string event_type { get; set; }/// <summary>/// 回调摘要(示例值:支付成功)/// </summary>public string summary { get; set; }/// <summary>/// 通知数据/// </summary>public resource resource { get; set; }}/// <summary>/// 通知数据/// </summary>public class resource{/// <summary>/// 原始类型/// </summary>public string original_type { get; set; }/// <summary>/// 加密算法类型/// </summary>public string algorithm { get; set; }/// <summary>/// 数据密文(需要解密才能获得下方的resourceClass数据)/// </summary>public string ciphertext { get; set; }/// <summary>/// 附加数据/// </summary>public string associated_data { get; set; }/// <summary>/// 随机串/// </summary>public string nonce { get; set; }}/// <summary>/// 测试解密串Dto/// </summary>public class resourcenew{public string ciphertext { get; set; }public string associated_data { get; set; }public string nonce { get; set; }}/// <summary>/// ciphertext解密后的Dto/// </summary>public class resourceClass{/// <summary>/// 商户id/// </summary>public string mchid { get; set; }/// <summary>/// appid/// </summary>public string appid { get; set; }/// <summary>/// 订单号/// </summary>public string out_trade_no { get; set; }/// <summary>/// 微信订单号(微信生成)/// </summary>public string transaction_id { get; set; }/// <summary>/// 支付方式类型/// </summary>public string trade_type { get; set; }/// <summary>/// 支付结果状态/// </summary>public string trade_state { get; set; }/// <summary>/// 支付结果摘要/// </summary>public string trade_state_desc { get; set; }/// <summary>/// /// </summary>public string bank_type { get; set; }/// <summary>/// /// </summary>public string attach { get; set; }/// <summary>/// 支付时间/// </summary>public string success_time { get; set; }/// <summary>/// payer(openid)/// </summary>public payer payer { get; set; }/// <summary>/// 订单信息/// </summary>public amount amount { get; set; }}/// <summary>/// 支付人员信息/// </summary>public class payer{/// <summary>/// openid/// </summary>public string openid { get; set; }}/// <summary>/// 订单信息/// </summary>public class amount{/// <summary>/// 金额/// </summary>public int total { get; set; }public int payer_tota { get; set; }/// <summary>/// 货币种(CNY)/// </summary>public string currency { get; set; }public string payer_currency { get; set; }}

AesGcm解密方法类:

这个之前在NuGet安装Portable.BouncyCastle包

    public class AesGcm{private static string ALGORITHM = "AES/GCM/NoPadding";private static int TAG_LENGTH_BIT = 128;private static int NONCE_LENGTH_BYTE = 12;private static string AES_KEY =App.Configuration["SenparcWeixinSetting:TenPayV3_Key"];//APIv3密钥public static string AesGcmDecrypt(string associatedData, string nonce, string ciphertext){GcmBlockCipher gcmBlockCipher = new GcmBlockCipher(new AesEngine());AeadParameters aeadParameters = new AeadParameters(new KeyParameter(Encoding.UTF8.GetBytes(AES_KEY)),128,Encoding.UTF8.GetBytes(nonce),Encoding.UTF8.GetBytes(associatedData));gcmBlockCipher.Init(false, aeadParameters);byte[] data = Convert.FromBase64String(ciphertext);byte[] plaintext = new byte[gcmBlockCipher.GetOutputSize(data.Length)];int length = gcmBlockCipher.ProcessBytes(data, 0, data.Length, plaintext, 0);gcmBlockCipher.DoFinal(plaintext, length);return Encoding.UTF8.GetString(plaintext);}}

第一次写博客如有不足请见谅,希望多多指导

如有问题可以在下方留言

这篇关于.NET6+furion+Senparc盛派SDK对接微信支付V3-扫码Native支付的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/157920

相关文章

java向微信服务号发送消息的完整步骤实例

《java向微信服务号发送消息的完整步骤实例》:本文主要介绍java向微信服务号发送消息的相关资料,包括申请测试号获取appID/appsecret、关注公众号获取openID、配置消息模板及代码... 目录步骤1. 申请测试系统2. 公众号账号信息3. 关注测试号二维码4. 消息模板接口5. Java测试

Python基于微信OCR引擎实现高效图片文字识别

《Python基于微信OCR引擎实现高效图片文字识别》这篇文章主要为大家详细介绍了一款基于微信OCR引擎的图片文字识别桌面应用开发全过程,可以实现从图片拖拽识别到文字提取,感兴趣的小伙伴可以跟随小编一... 目录一、项目概述1.1 开发背景1.2 技术选型1.3 核心优势二、功能详解2.1 核心功能模块2.

java对接海康摄像头的完整步骤记录

《java对接海康摄像头的完整步骤记录》在Java中调用海康威视摄像头通常需要使用海康威视提供的SDK,下面这篇文章主要给大家介绍了关于java对接海康摄像头的完整步骤,文中通过代码介绍的非常详细,需... 目录一、开发环境准备二、实现Java调用设备接口(一)加载动态链接库(二)结构体、接口重定义1.类型

VSCode设置python SDK路径的实现步骤

《VSCode设置pythonSDK路径的实现步骤》本文主要介绍了VSCode设置pythonSDK路径的实现步骤,包括命令面板切换、settings.json配置、环境变量及虚拟环境处理,具有一定... 目录一、通过命令面板快速切换(推荐方法)二、通过 settings.json 配置(项目级/全局)三、

如何基于Python开发一个微信自动化工具

《如何基于Python开发一个微信自动化工具》在当今数字化办公场景中,自动化工具已成为提升工作效率的利器,本文将深入剖析一个基于Python的微信自动化工具开发全过程,有需要的小伙伴可以了解下... 目录概述功能全景1. 核心功能模块2. 特色功能效果展示1. 主界面概览2. 定时任务配置3. 操作日志演示

Redis迷你版微信抢红包实战

《Redis迷你版微信抢红包实战》本文主要介绍了Redis迷你版微信抢红包实战... 目录1 思路分析1.1hCckRX 流程1.2 注意点①拆红包:二倍均值算法②发红包:list③抢红包&记录:hset2 代码实现2.1 拆红包splitRedPacket2.2 发红包sendRedPacket2.3 抢

java对接第三方接口的三种实现方式

《java对接第三方接口的三种实现方式》:本文主要介绍java对接第三方接口的三种实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录HttpURLConnection调用方法CloseableHttpClient调用RestTemplate调用总结在日常工作

SpringBoot后端实现小程序微信登录功能实现

《SpringBoot后端实现小程序微信登录功能实现》微信小程序登录是开发者通过微信提供的身份验证机制,获取用户唯一标识(openid)和会话密钥(session_key)的过程,这篇文章给大家介绍S... 目录SpringBoot实现微信小程序登录简介SpringBoot后端实现微信登录SpringBoo

Java对接Dify API接口的完整流程

《Java对接DifyAPI接口的完整流程》Dify是一款AI应用开发平台,提供多种自然语言处理能力,通过调用Dify开放API,开发者可以快速集成智能对话、文本生成等功能到自己的Java应用中,本... 目录Java对接Dify API接口完整指南一、Dify API简介二、准备工作三、基础对接实现1.

Python实现微信自动锁定工具

《Python实现微信自动锁定工具》在数字化办公时代,微信已成为职场沟通的重要工具,但临时离开时忘记锁屏可能导致敏感信息泄露,下面我们就来看看如何使用Python打造一个微信自动锁定工具吧... 目录引言:当微信隐私遇到自动化守护效果展示核心功能全景图技术亮点深度解析1. 无操作检测引擎2. 微信路径智能获