微信公众号、微信小程序使用JsApi支付方式,前端vue+后端c#,详细介绍

微信支付有多种方式,本文章主要介绍JsApi支付,前端调用使用的是vue,后端使用的是c# webapi,后端使用了插件Senparc.Weixin.TenPayV3。

开发工具:
前端:hbuilder
后端:Visual Studio 2022

注意:
小程序和公众号区别:
1、后端配置global.json的时候,Appid用对应平台上申请的
2、后端代码没有什么区别
3、vue在生成预付订单后,调起手机支付输入密码页面有区别,由于开发工具用的是Hbuilder,小程序支付可以直接用官方的wx.requestPayment,公众号不支持这种写法,所以稍微有一点点区别,公众号直接用微信公众号官方方法就可以了,下文中有贴出代码。

微信商户平台配置
微信商户平台开通JsApi接口
在这里插入图片描述

支付授权目录设置,注意路径要到你api的实际路径,不要只写到域名

在这里插入图片描述
API安全设置(后端配置需要TenPayV3_Key、TenPayV3_PrivateKey、TenPayV3_SerialNumber,都是在此页面设置的)
在这里插入图片描述

后端配置
我后端开发用的是Visual Studio 2022,要安装插件Senparc.Weixin.TenPayV3(盛派开发的
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/2f6b7c4f0952467887b21a62df9c58bf.png

配置global.json

//Senparc.Weixin SDK 设置
  "SenparcWeixinSetting": {
    //以下为 Senparc.Weixin 的 SenparcWeixinSetting 微信配置
    //微信全局
    "IsDebug": true,
    //微信支付V3(新版)
    "TenPayV3_AppId": "xxxxxxxxx", // 
    "TenPayV3_AppSecret": "xxxxxxxxx",
    "TenPayV3_MchId": "xxxxxx",//商户号
    "TenPayV3_TenpayNotify": "http://cd.xxxxxxxxx.com/PayNotifyUrl", //支付成功后的回调
    "TenPayV3_PrivateKey": "xxxx....", //(新)证书私钥(在证书文件夹中,很长一串,自己去复制)
    "TenPayV3_SerialNumber": "xxxx...", //证书序列号(在商户平台申请证后,复制过来)
    "TenPayV3_ApiV3Key": "xxxxxxxxx", //(新)APIv3 密钥 跟上面的TenPayV3_Key填同一个
  },

在program.cs要注册Senparc,代码如下
先添加引用

using Senparc.Weixin.AspNet;
using Senparc.Weixin.AspNet.RegisterServices;
using Senparc.Weixin.Entities;
using Senparc.Weixin.RegisterServices;
using Senparc.Weixin.TenPayV3;

继续在program.cs中添加注册代码

//Senparc.Weixin 注册(必须)
builder.Services.AddSenparcWeixinServices(builder.Configuration);
var app = builder.Build();
var senparcWeixinSetting = app.Services.GetService<IOptions<SenparcWeixinSetting>>()!.Value;
//启用微信配置(必须)
var registerService = app.UseSenparcWeixin(app.Environment,
    null /* 不为 null 则覆盖 appsettings  中的 SenpacSetting 配置*/,
    null /* 不为 null 则覆盖 appsettings  中的 SenpacWeixinSetting 配置*/,
    register => { },
    (register, weixinSetting) =>
    {
        //注册公众号信息(可以执行多次,注册多个小程序)
        register.RegisterTenpayApiV3(weixinSetting, "【xxx项目名称】微信支付(ApiV3)");//自定义一个名字
    });

支付流程
1、前端vue调用后端api,生成一条状态为待支付的数据
2、待支付订单生成结果返回到前端,前端发起支付,跳转输入密码界面
3、输入密码成功付款后,自动触发后端支付成功回调函数,修改支付状态

vue(公众号)


```html
			//生成订单预支付信息
			Recharge() {
				let that = this
				var recharge = {
					virtual_card_number: '123',
					phone: this.memberinfo.phone,
					recharge_money: this.renew_money,
					recharge_type: this.renew_type,
					openid: uni.getStorageSync('open_id')
				}//传输到后端api的参数,根据自己项目修改
					get_prepay_id(recharge).then(res => {
						this.prepay_result = res.data.data
						if (typeof WeixinJSBridge == "undefined") {
						    if (document.addEventListener) {
						        document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
						    } else if (document.attachEvent) {
						        document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
						        document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
						    }
						} else {
						    this.onBridgeReady();
						}
					})
		
			},
	onBridgeReady() {
	      let that=this
	      WeixinJSBridge.invoke(
	        'getBrandWCPayRequest', {
	                 "appId":that.prepay_result.appId ,   //公众号ID,由商户传入
	                 "timeStamp":that.prepay_result.timeStamp,   //时间戳,自1970年以来的秒数    
	                 "nonceStr": that.prepay_result.nonceStr,      //随机串    
	                 "package": that.prepay_result.package,
	                 "signType": that.prepay_result.signType,     //微信签名方式:    
	                 "paySign":  that.prepay_result.paySign//微信签名
	        },
	        function(res){
			  console.log('this.prepay_result',that.prepay_result)
	          if(res.err_msg == "get_brand_wcpay_request:ok" ){
	            // 使用者支付成功
	            alert('支付成功');
	          } else if(res.err_msg == "get_brand_wcpay_request:fail" ){
	            // 使用者支付失败
	            alert('支付失败');
	          }
	        }
	      );
	    }```

**
vue(小程序)

Recharge() {
				let that = this
				var recharge = {
					virtual_card_number: '123',
					phone: this.memberinfo.phone,
					recharge_money: this.renew_money,
					recharge_type: this.renew_type,
					openid: uni.getStorageSync('open_id')
				}//传输到后端api的参数,根据自己项目修改
					get_prepay_id(recharge).then(res => {
					    	var  result = res.data.data
							wx.requestPayment({
							timeStamp: result.timeStamp,
							nonceStr: result.nonceStr,
							package: result.package,
							signType: result.signType,
							paySign: result.paySign,
							success(res) {
								console.log('支付成功', res)
							},
							fail(res) {
								console.log('支付失败', res)
							}
						})
					})
		
			},

**后端 WebApi
生成预支付订单

 /// <summary>
 /// JsApi支付
 /// </summary>
 /// <param name="record">订单信息</param>
 /// <returns></returns>
 //发布到服务器iis时,选择应用池-鼠标右键–>高级设置–>进程模型–>加载用户配置文件–>设置为true
 public async Task<ApiReturnValue> GetPrepayid(c_recharge_record record)
 {
     ApiReturnValue<wx_pay_param> apiresult = new ApiReturnValue<wx_pay_param>();
     try
     {
        string HostIp = "xxxx.xx.xx.xxx";
         //生成订单10位序列号,此处用时间和随机数生成,商户根据自己调整,保证唯一
         record.sp_billno = "cz_"+SystemTime.Now.ToString("yyyyMMddHHmmss");
         record.recharge_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
         var body = "智慧停车充值";
         int price = record.recharge_money*100;//单位:分
         //int price =1;//单位:分
         var basePayApis = new Senparc.Weixin.TenPayV3.Apis.BasePayApis(Config.SenparcWeixinSetting);
         var requestData = new Senparc.Weixin.TenPayV3.Apis.BasePay.TransactionsRequestData(Config.SenparcWeixinSetting.TenPayV3_AppId, Config.SenparcWeixinSetting.TenPayV3_MchId, body, record.sp_billno, new Senparc.Weixin.TenPayV3.Entities.TenpayDateTime(SystemTime.Now.AddMinutes(120).DateTime, false), HostIp, Config.SenparcWeixinSetting.TenPayV3_TenpayNotify, null, new() { currency = "CNY", total = price }, new(record.openid), null, null, null);
         var result = await basePayApis.JsApiAsync(requestData);
         if (result.ResultCode.Success == true)
         {
             var packageStr = "prepay_id=" + result.prepay_id;
             var jsApiUiPackage = TenPaySignHelper.GetJsApiUiPackage(Config.SenparcWeixinSetting.TenPayV3_AppId, result.prepay_id);
             wx_pay_param param = new wx_pay_param
             {
                 prepay_id = result.prepay_id,//预付_id
                 appId = Config.SenparcWeixinSetting.TenPayV3_AppId,//appId
                 timeStamp = jsApiUiPackage.Timestamp,//时间戳
                 nonceStr = jsApiUiPackage.NonceStr,//随机字符串,长度为32个字符以下
                 package = packageStr,// 统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id = ***
                 signType = "RSA",// 签名算法,应与后台下单时的值一致
                 paySign = jsApiUiPackage.Signature//签名
             };
             //插入一条订单
             DB.Insertable(record).ExecuteCommand();
             apiresult.data = param;
         }
         else
         {
             apiresult.code = 500;
             apiresult.message = result.ResultCode.ErrorCode.ToString() + result.ResultCode.ErrorMessage + result.ResultCode.Solution;
         }
     }
     catch (Exception ex)
     {
         apiresult.code = 500;
         apiresult.message = ex.Message;
     }
     return apiresult;
 }

支付回调函数

  //支付成功后的回调
  [HttpPost("PayNotifyUrl")]
  public async Task<ApiReturnValue> PayNotifyUrl()
  {
      ApiReturnValue api_result = new ApiReturnValue();
      try
      {
          //获取微信服务器异步发送的支付通知信息
          var resHandler = new TenPayNotifyHandler(HttpContext);
          var orderReturnJson = await resHandler.AesGcmDecryptGetObjectAsync<OrderReturnJson>();

          //记录日志
          Senparc.Weixin.WeixinTrace.SendCustomLog("PayNotifyUrl 接收到消息", orderReturnJson.ToJson(true));

          //演示记录 transaction_id,实际开发中需要记录到数据库,以便退款和后续跟踪
          string out_trade_no = orderReturnJson.out_trade_no;
          //获取支付状态
          string trade_state = orderReturnJson.trade_state;

          //验证请求是否从微信发过来(安全)
          NotifyReturnData returnData = new();
        
          //验证可靠的支付状态
          if (orderReturnJson.VerifySignSuccess == true && trade_state == "SUCCESS")
          {
              returnData.code = "SUCCESS";//正确的订单处理
              /* 提示:
                  * 1、直到这里,才能认为交易真正成功了,可以进行数据库操作,但是别忘了返回规定格式的消息!
                  * 2、上述判断已经具有比较高的安全性以外,还可以对访问 IP 进行判断进一步加强安全性。
                  * 3、下面演示的是发送支付成功的模板消息提示,非必须。
                  */
              recharge_service.recharge_callback(out_trade_no);//这个方法自定义,我这里是直接去改变订单的状态为已支付
          }
          else
          {
              returnData.code = "FAILD";//错误的订单处理
              returnData.message = "验证失败";

              //此处可以给用户发送支付失败提示等
          }

          #region 记录日志(也可以记录到数据库审计日志中)

          var logDir = ServerUtility.ContentRootMapPath(string.Format("~/App_Data/TenPayNotify/{0}", SystemTime.Now.ToString("yyyyMMdd")));
          if (!Directory.Exists(logDir))
          {
              Directory.CreateDirectory(logDir);
          }

          var logPath = Path.Combine(logDir, string.Format("{0}-{1}-{2}.txt", SystemTime.Now.ToString("yyyyMMdd"), SystemTime.Now.ToString("HHmmss"), Guid.NewGuid().ToString("n").Substring(0, 8)));

          using (var fileStream = System.IO.File.OpenWrite(logPath))
          {
              var notifyJson = orderReturnJson.ToString();
              await fileStream.WriteAsync(Encoding.Default.GetBytes(notifyJson), 0, Encoding.Default.GetByteCount(notifyJson));
              fileStream.Close();

          }
          #endregion
      }
      catch (Exception ex)
      {
          WeixinTrace.WeixinExceptionLog(new WeixinException(ex.Message, ex));
          throw;
      }
      return api_result;
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值