微信内置H5支付

news2024/12/24 10:25:03

🧑‍💻 写在开头
点赞 + 收藏 === 学会🤣🤣🤣

场景是用户通过微信扫app内的收款码,跳到一个h5页面。然后完成支付。

代码实现的整体流程:

使用微信扫码,码是app内生成的,码的内容是一个h5页面链接,扫码完成后跳转到自定义的h5支付界面。
扫码进入后,将页面展示所需要的参数进行缓存起来,存到本地。 然后需要微信静默授权。

  1. 微信静默授权的流程:
    配置appid、redirect_uri等参数,从项目页面跳转到微信授权页面:https://open.weixin.qq.com/connect/oauth2/authorize
    详细参考[ 微信官方文档]open.weixin.qq.com/connect/oau…

参数说明

在这里插入图片描述

// 示例
let ua = window.navigator.userAgent.toLowerCase();
if (ua.match(/MicroMessenger/i) == 'micromessenger') {
   // 回调地址:域名加页面路径
   let hdurl = encodeURIComponent('https://.../#/page_wallet');
   let appId = '申请项目的appid';
   window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${hdurl}&response_type=code&scope=snsapi_base#wechat_redirect`;
}

  1. 当授权后,会自动跳转到配置回调页面,也就是配置的‘redirect_uri’ 相当携带这code,重新打开了项目
  2. 然后解析url中的code,将code取出,支付的时候将code传给后端。

点击支付的时候,请求接口,使用微信浏览器内置对象WeixinJSBridge调起微信支付,使用方法如下所示,data就是由后端返回的数据。

function onBridgeReady(data) {
  WeixinJSBridge.invoke(
    "getBrandWCPayRequest",
    {
      // 公众号名称,由商户传入
      appId: data.appId,
      // 时间戳,自1970年以来的秒数
      timeStamp: data.timeStamp,
      // 随机串
      nonceStr: data.nonceStr,
      package: data.package,
      // 微信签名方式:
      signType: "MD5",
      // 微信签名
      paySign: data.paySign,
    },
    function (res) {
      if (res.err_msg == "get_brand_wcpay_request:ok") {
        // 使用以上方式判断前端返回,微信团队郑重提示:
        // res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
      }
    }
  )
 }

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 {
  onBridgeReady();
}

在使用uniapp开发中使用的代码如下:

<template>
   <view v-show="show">
      ...内容省略
       <view @click="confirmPay">付款</view>
   </view>
</template>

<script>
    // 支付接口
 import { payment_code } from '@/api/wallet';
 
 export default {
    data() {
      return {
        show: true, // 控制页面展示
        user: {}, // 页面信息
        form: { price: '', type: 0, code: null, receiver_id: null }, // 提交参数
        paydata: {} //返回的支付信息
      };
     },
     onLoad(e) {
       // 扫码后第一次进入该页面时
       if (e.id) {
          this.user = {
            name: e.name,
            id: e.id,
          };
          this.form.receiver_id = e.id;
          // 将信息存到本地
          uni.setStorageSync('userpay', this.user);
       }else{
          // 第二次进入(授权成功后,通过回调进入的页面)
          let data = uni.getStorageSync('userpay');
          this.user = {
            name: data.name,
            id: data.id,
          };
          this.form.price = data.price;
          this.form.receiver_id = data.id;
          let ua = window.navigator.userAgent.toLowerCase();
          //判断是不是微信
          if (ua.match(/MicroMessenger/i) == 'micromessenger') {
            // 第二次进来时,路径上已经携带了code,获取code。
            this.form.code = this.getUrlParam('code');
          }
       }
       // 去授权
       this.goAuthorization()
     }methods:{
       // 授权方法
       goAuthorization(){
         let ua = window.navigator.userAgent.toLowerCase();
         // //判断是不是微信
         if (ua.match(/MicroMessenger/i) == 'micromessenger') {
           // 判断是否已经获取了code
           if (this.form.code == null || this.form.code === '') {
               // 如果还没有code,就跳转授权页面
               let hdurl = encodeURIComponent('https://.../#/page_wallet');
               let appId = '申请项目的appid';
               window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${hdurl}&response_type=code&scope=snsapi_base#wechat_redirect`;   
           }else{
             // 有code的话,就将页面内容显示出来
             this.show = true;
           }
         }
       }
     }// 点击支付后,调用
     confirm(e) {
       uni.showLoading({});
        uni.$u.http.post('支付接口',this.form).then(res=>{
           uni.hideLoading();
           // 将返回的data赋值
           this.paydata = res.data.data;
           let that = this;
           // 绑定事件
           if (typeof WeixinJSBridge == 'undefined') {
              if (document.addEventListener) {
                document.addEventListener('WeixinJSBridgeReady', that.wxonBridgeReady, false);
              } else if (document.attachEvent) {
                document.attachEvent('WeixinJSBridgeReady', that.wxonBridgeReady);
                document.attachEvent('onWeixinJSBridgeReady', that.wxonBridgeReady);
              }
            } else {
              this.wxonBridgeReady();
            }
        }).catch((err) => {
          // 如果接口调用失败了,将信息存起来,再走一遍授权。
          this.user.price = this.form.price;
          uni.setStorageSync('userpay', this.user);
          this.form.code = null;
          this.goAuthorization();
        });
     },
     // 微信支付
     wxonBridgeReady(){
       let that = this;
       WeixinJSBridge.invoke(
        'getBrandWCPayRequest',
        {
          appId: that.paydata.appId,
          timeStamp: that.paydata.timeStamp,
          nonceStr: that.paydata.nonceStr,
          package: that.paydata.package,
          signType: that.paydata.signType,
          paySign: that.paydata.paySign
        },
        function (res) {
              // 如果取消了支付,就关闭当前h5页面,直接返回微信,也可以进行其他操作,通过res.err_msg来判断即可
          if (res.err_msg == 'get_brand_wcpay_request:cancel') {
            //关闭当前浏览器
            WeixinJSBridge.call('closeWindow');
          }
          // 这里是支付成功
          if (res.err_msg == 'get_brand_wcpay_request:ok') {
            // 使用以上方式判断前端返回,微信团队郑重提示:
            //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
          }
        }
      )
     },
     
     // 获取路径上参数的方法,用于获取code
     getUrlParam(name) {
      const url = window.location.href;
      const queryString = url.split('?')[1];
      if (!queryString) return null;
      const params = queryString.split('&');
      for (const param of params) {
        const [key, value] = param.split('=');
        if (key === name) {
          return decodeURIComponent(value);
        }
      }
      return null;
    },
     
  } 
</script>

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1876760.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Qt WPS(有源码)

项目源码地址&#xff1a;WPS完整源码 一.项目详情 该项目仿照WPS&#xff0c;实现了部分的功能&#xff0c;能够很方便对文本和HTML进行修改&#xff0c;并且有打印功能&#xff0c;可以很方便的生成PDF。 应用界面 项目架构分析 这个项目主要可分为两个部分&#xff0c;一…

等保2.0安全计算环境解读

等保2.0&#xff0c;即网络安全等级保护2.0制度&#xff0c;是中国为了适应信息技术的快速发展和安全威胁的新变化而推出的网络安全保护标准。相较于等保1.0&#xff0c;等保2.0更加强调主动防御、动态防御和全面审计&#xff0c;旨在实现对各类信息系统的全面保护。 安全计算环…

鼠尾草(洋苏草)

鼠尾草&#xff08;Salvia japonica Thunb.&#xff09;&#xff0c;又名洋苏草、普通鼠尾草、庭院鼠尾草&#xff0c;属于唇形科鼠尾草属多年生草本植物。鼠尾草以其独特的蓝紫色花序和长而细密的叶片为特点&#xff0c;常用于花坛、庭院和药用植物栽培。 鼠尾草的名字源自于…

Java访问修饰符的区别

public&#xff1a;公开的&#xff0c;任何地方都可以访问。 protected&#xff1a;受保护的&#xff0c;同一个包中的类和所有子类(可跨包)可以访问。 private&#xff1a;私有的&#xff0c;只有在同一个类中可以访问。 默认&#xff08;无修饰符&#xff09;&#xff1a;包级…

[Go 微服务] go-micro + consul 的使用

文章目录 1.go-micro 介绍2.go-micro 的主要功能3.go-micro 安装4.go-micro 的使用4.1 创建服务端4.2 配置服务端 consul4.3 生成客户端 5.goodsinfo 服务5.1 服务端开发5.2 客户端开发 1.go-micro 介绍 Go Micro是一个简化分布式开发 的微服务生态系统&#xff0c;该系统为开…

stm32学习笔记---ADC模数转换器(理论部分)

目录 ADC简介 什么叫逐次逼近型&#xff1f; STM32 ADC框图 模数转换器外围线路 ADC基本结构图 输入通道 规则组的四种转换模式 第一种&#xff1a;单次转换非扫描模式 第二种&#xff1a;连续转换&#xff0c;非扫描模式 第三种&#xff1a;单次转换&#xff0c;扫描…

数据结构03 链表的基本操作【C++数组模拟实现】

前言&#xff1a;本节内容主要了解链表的基本概念及特点&#xff0c;以及能够通过数组模拟学会链表的几种基本操作&#xff0c;下一节我们将通过STL模板完成链表操作&#xff0c;可以通过专栏进入查看下一节哦~ 目录 单链表及其特点 完整链表构成 完整链表简述 创建单链表 …

MySQL自增主键踩坑记录

对于MySQL的自增主键&#xff0c;本文记录、整理下在工作中实际遇到的问题。 下面示例均基于MySQL 8.0 修改列的类型后&#xff0c;自增属性消失 CREATE TABLE users (id INT AUTO_INCREMENT PRIMARY KEY,username VARCHAR(50) NOT NULL,email VARCHAR(100) NOT NULL );上面的…

计算机监控软件有哪些?10款常年霸榜的计算机监控软件

计算机监控软件是企业管理和保护信息安全的重要工具&#xff0c;它们帮助企业管理者监督员工的计算机使用行为&#xff0c;确保工作效率、数据安全以及合规性。在众多监控软件中&#xff0c;有些产品因其卓越的功能、易用性、安全性以及持续获得的良好市场反馈而常年占据行业领…

什么是指令微调(LLM)

经过大规模数据预训练后的语言模型已经具备较强的模型能力&#xff0c;能够编码丰富的世界知识&#xff0c;但是由于预训练任务形式所限&#xff0c;这些模型更擅长于文本补全&#xff0c;并不适合直接解决具体的任务。 指令微调是相对“预训练”来讲的&#xff0c;预训练的时…

spring mvc实现一个自定义Formatter请求参数格式化

使用场景 在Spring Boot应用中&#xff0c;Formatter接口用于自定义数据的格式化&#xff0c;比如将日期对象格式化为字符串&#xff0c;或者将字符串解析回日期对象。这在处理HTTP请求和响应时特别有用&#xff0c;尤其是在展示给用户或从用户接收特定格式的数据时。下面通过…

集合,Collection接口

可动态保存任意多个对象&#xff0c;使用比较方便 提供了一系列方便操作对象的方法&#xff1a;add&#xff0c;remove&#xff0c;set&#xff0c;get等 使用集合添加删除新元素&#xff0c;代码简洁明了 单列集合 多列集合 Collection接口 常用方法 List list new Arra…

【原创图解 算法leetcode 146】实现一个LRU缓存淘汰策略策略的数据结构

1 概念 LRU是Least Recently Used的缩写&#xff0c;即最近最少使用&#xff0c;是一种常见的缓存淘汰算法。 其核心思想为&#xff1a;当内存达到上限时&#xff0c;淘汰最久未被访问的缓存。 2 LeetCode LeetCode: 146. LRU缓存 3 实现 通过上面LRU的淘汰策略可知&#…

北京市大兴区餐饮行业协会成立暨职业技能竞赛总结大会成功举办

2024年6月27日下午&#xff0c;北京市大兴区营商服务中心B1层报告厅迎来了北京市大兴区餐饮行业协会成立仪式暨2024年北京市大兴区餐饮行业职工职业技能竞赛总结大会。此次活动不仅标志着大兴区餐饮行业协会的正式成立&#xff0c;也对在2024年大兴区餐饮行业职工职业技能竞赛中…

Python自动化测试:web自动化测试——selenium API、unittest框架的使用

web自动化测试2 1. 设计用例的方法——selenium API1.1 基本元素定位1&#xff09;定位单个唯一元素2&#xff09;定位一组元素3&#xff09;定位多窗口/多框架4&#xff09;定位连续层级5&#xff09;定位下拉框6&#xff09;定位div框 1.2 基本操作1.3 等待1.4 浏览器操作1.5…

SpringBoot整合Quartz实现动态定时任务

目录 1、Quartz简介1.1 Quartz的三大核心组件1.2 CronTrigger配置格式 2、SpringBoot整合Quartz框架2.1 创建项目2.2 实现定时任务 1、Quartz简介 Quartz是一个开源的任务调度服务&#xff0c;它可以独立使用&#xff0c;也可与其它的Java EE&#xff0c;Java SE应用整合使用。…

Python数据分析案例48——二手房价格影响因素分析

案例背景 房价影响因素也是人们一直关注的问题&#xff0c;本次案例也适合各种学科的同学&#xff0c;无论你是经济管理类还是数学统计&#xff0c;还是电商物流类&#xff0c;都可以使用回归分析。通过数据分析回归分析分组聚合可视化等方法进行研究房价影响因素。 数据介绍 …

2024下半年必追国漫片单,谁将问鼎巅峰?

随着2024年上半年的落幕&#xff0c;国漫市场再度迎来了百花齐放的盛况。从经典续作到全新IP&#xff0c;从玄幻到科幻&#xff0c;每一部作品都以其独特的魅力吸引着观众的目光。本期为大家盘点下半年值得一看的国漫佳作&#xff0c;大胆预测&#xff0c;谁将成为这场神仙打架…

Grafana-11.0.0 在线部署教程

Grafana-11.0.0 在线部署教程 环境&#xff1a; 操作系统&#xff1a; ubuntugrafana版本&#xff1a; 11.0.0 &#xff08;建议不要按照最新版&#xff09;grafana要求的系统配置不高&#xff0c;建议直接部署在监控服务器上&#xff0c;比如zabbix服务器、prometheus服务器…

【Stable Diffusion】创意与科技的完美结合:AI绘画副业让美术老师月入2w+

前言 艺术与科技一直以来都是两个看似独立的领域&#xff0c;但如今&#xff0c;随着人工智能的发展&#xff0c;这两个领域正迎来一次前所未有的融合。在这个数字化时代&#xff0c;AI绘画成为了一项引人注目的副业&#xff0c;为美术老师们带来了新的机遇和收入。 儿童画 …