.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

相关文章

SpringBoot实现微信小程序支付功能

《SpringBoot实现微信小程序支付功能》小程序支付功能已成为众多应用的核心需求之一,本文主要介绍了SpringBoot实现微信小程序支付功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作... 目录一、引言二、准备工作(一)微信支付商户平台配置(二)Spring Boot项目搭建(三)配置文件

微信公众号脚本-获取热搜自动新建草稿并发布文章

《微信公众号脚本-获取热搜自动新建草稿并发布文章》本来想写一个自动化发布微信公众号的小绿书的脚本,但是微信公众号官网没有小绿书的接口,那就写一个获取热搜微信普通文章的脚本吧,:本文主要介绍微信公众... 目录介绍思路前期准备环境要求获取接口token获取热搜获取热搜数据下载热搜图片给图片加上标题文字上传图片

如何用java对接微信小程序下单后的发货接口

《如何用java对接微信小程序下单后的发货接口》:本文主要介绍在微信小程序后台实现发货通知的步骤,包括获取Access_token、使用RestTemplate调用发货接口、处理AccessTok... 目录配置参数 调用代码获取Access_token调用发货的接口类注意点总结配置参数 首先需要获取Ac

SpringBoot基于沙箱环境实现支付宝支付教程

《SpringBoot基于沙箱环境实现支付宝支付教程》本文介绍了如何使用支付宝沙箱环境进行开发测试,包括沙箱环境的介绍、准备步骤、在SpringBoot项目中结合支付宝沙箱进行支付接口的实现与测试... 目录一、支付宝沙箱环境介绍二、沙箱环境准备2.1 注册入驻支付宝开放平台2.2 配置沙箱环境2.3 沙箱

如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解

《如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解》:本文主要介绍如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别的相关资料,描述了如何使用海康威视设备网络SD... 目录前言开发流程问题和解决方案dll库加载不到的问题老旧版本sdk不兼容的问题关键实现流程总结前言作为

W外链微信推广短连接怎么做?

制作微信推广链接的难点分析 一、内容创作难度 制作微信推广链接时,首先需要创作有吸引力的内容。这不仅要求内容本身有趣、有价值,还要能够激起人们的分享欲望。对于许多企业和个人来说,尤其是那些缺乏创意和写作能力的人来说,这是制作微信推广链接的一大难点。 二、精准定位难度 微信用户群体庞大,不同用户的需求和兴趣各异。因此,制作推广链接时需要精准定位目标受众,以便更有效地吸引他们点击并分享链接

native和static native区别

本文基于Hello JNI  如有疑惑,请看之前几篇文章。 native 与 static native java中 public native String helloJni();public native static String helloJniStatic();1212 JNI中 JNIEXPORT jstring JNICALL Java_com_test_g

消除安卓SDK更新时的“https://dl-ssl.google.com refused”异常的方法

消除安卓SDK更新时的“https://dl-ssl.google.com refused”异常的方法   消除安卓SDK更新时的“https://dl-ssl.google.com refused”异常的方法 [转载]原地址:http://blog.csdn.net/x605940745/article/details/17911115 消除SDK更新时的“

如何更优雅地对接第三方API

如何更优雅地对接第三方API 本文所有示例完整代码地址:https://github.com/yu-linfeng/BlogRepositories/tree/master/repositories/third 我们在日常开发过程中,有不少场景会对接第三方的API,例如第三方账号登录,第三方服务等等。第三方服务会提供API或者SDK,我依稀记得早些年Maven还没那么广泛使用,通常要对接第三方

uniapp设置微信小程序的交互反馈

链接:uni.showToast(OBJECT) | uni-app官网 (dcloud.net.cn) 设置操作成功的弹窗: title是我们弹窗提示的文字 showToast是我们在加载的时候进入就会弹出的提示。 2.设置失败的提示窗口和标签 icon:'error'是设置我们失败的logo 设置的文字上限是7个文字,如果需要设置的提示文字过长就需要设置icon并给