从0到1做H5支付(嵌入微信公众号)

1:需求下发
接到需求需要实现一个线下扫码支付的功能,流程是商户摆出来的那种二维码,用户扫码后授权,然后跳转到一个支付页面,页面可以输入金额,同时可以选择自己可用的券或者积分抵扣
2:前端项目生成
因为是运行在微信浏览器的H5页面项目,目前公司没有H5的项目,于是重新构建了一个基于vue3+vite的项目,步骤如下
1:

npm create vue@latest

2:选择配置项,第一行输入自己定义的项目名称,后面按需选择,我只保留了router。需要注意的是蓝色字体为当前的选中状态,如果认可当前状态,就直接回车;如果不认可当前的选中状态,可以输入1/2(1表示选择第一个选项)来进行选择。
在这里插入图片描述
3:上一步项目已经生成,可以直接cd到对应目录下,然后执行npm run dev运行项目,项目可正常运行。接下来就是第一新建页面,第二封装请求测试跟后端通信,

import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
const router = createRouter({
  // history: createWebHashHistory(), // 如果使用hash模式
  history: createWebHistory(import.meta.env.BASE_URL),
  // import.meta.env.BASE_URL这个如果是history模式必须得传,默认是'/',但是可以在vite.config.js里面进行配置
  routes: [
    {
      path: '/',
      name: 'home',
      component: HomeView,
      redirect: '/pay',
    },
    {
      path: '/pay',
      name: 'H5Pay',
      component: () => import('../views/H5Pay.vue')
    },
    {
      path: '/authorize',
      name: 'AuthorizeWeixin',
      component: () => import('../views/AuthorizeWeixin.vue')
    }
  ]
})

export default router
import axios from 'axios'
import { showToast } from 'vant'
const service = axios.create({
  // baseURL: 'https://xxxxxxx.com/sit',
  baseURL: import.meta.env.VITE_APP_BASE_API, // url = base url + request url
  // import.meta.env.VITE_APP_BASE_API 这个是自己配置的环境变量,根据不同的脚本加载不同的环境变量文件,后面也会记录一下
  timeout: 30000 // request timeout
})

// 请求头拦截器
service.interceptors.request.use(
  (config) => {
  	//   在这里可以打印出config,然后配置各种请求头或者判断url进行特殊处理
    //   config.headers["org-tenant-code"] = "123";
    return config;
  },
  (error) => {
    console.log(error); // for debug
    return Promise.reject(error);
  }
);

// 请求返回拦截器
service.interceptors.response.use(response => {
  const res = response.data
  if (res.code !== 200) {
    showToast(res.msg)
  } else {
    return res
  }
}, error => {
  console.log('err' + error) // for debug
  return Promise.reject(error)
})

export default service

4:请求二次封装以后需要全局注册使用,在vue3中需要按如下方法注入全局

// main.js
import service from '@/utils/request'
app.config.globalProperties.$axios = service
import { getCurrentInstance } from 'vue'
const { proxy } = getCurrentInstance()
proxy.$axios
  .get(`/app/h5/offline/getUserInfo?code=${code}&appid=${APPID}`)
  .then((res) => {
    if (res && res.code === 200) {
    }
  })

5:请求封装完,调用时有可能报错也有可能不报错,因为某些情况下会报跨域,这时候需要在vite.config.js里面配置一下,配置如下

server: {
  port: 80,
  host: '0.0.0.0',
  cors: true,
  proxy: {
  // 配置跨域
  '/api': {
  	target: 'https://xxxxxxx.com/sit', // 根据需求替换 请求后台接口,这个地址可以写本地固定的请求地址,只有请求匹配这个地址才会使用代理,因为线上一般不会跨域
  	changeOrigin: true, // 允许跨域
  	ws: true,
  	rewrite: (path) => path.replace(/^\/api/, ''), // 重写请求
  	},
  },
},

6:这时候应该可以正常新增页面,正常发起和接收请求了,但是为了应对项目部署的各种环境,还需要配置一下各种脚本,首先在package.json中新增两个脚本命令,同时对应新增两个环境变量文件,按照’.env.[mode]'的格式来命名,

"scripts": {
    "dev": "vite",
    "build": "vite build",
    "build:productionsit": "vite build --mode productionsit", // 新增sit环境
    "build:productionuat": "vite build --mode productionuat",// 新增uat环境
    "preview": "vite preview --mode productionuat"
  },

在这里插入图片描述
在这里插入图片描述

这样在执行不同的脚本时才会加载不同的环境配置文件,才可以在第三步axios的创建时直接使用import.meta.env.VITE_APP_BASE_API这个变量来设置baseurl
(需要注意的是环境配置文件中所有自定义的变量需要以VITE_开头,否则项目中是不能读取到的。)
同时还可以配置下执行不同的脚本时打包的dist名称,(一般不设置打包后都会生成dist,但是有些公司会要求不同的环境对应不同的包名,比如dist_sit、dist_uat)配置方法如下,注意在vite.config.js中不能使用import.meta.env来读取,因为vite.config.js文件是在构建过程中就执行的,import.meta.env只能在构建完成的项目文件中使用

import { defineConfig, loadEnv } from 'vite'
export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd());
  const { VITE_APP_DIST, VITE_APP_BASE_DIR } = env;
  return {
    build: {
      outDir: VITE_APP_DIST
    }
  }
})

7:这时候应该画页面了,H5项目是主要运行在手机端的,所以在写样式的时候也需要制定适配的方案,适配可以用多种方式,我使用的是rem+vw布局的方法,实现方式就是在项目的index.html页面里设置根元素的字体大小,方法如下
在这里插入图片描述
设置完成后记得给body的字体设置正常16px或者14px,否则整个项目的字体都会大的虾仁,如果设计图某div的宽是75px,那我们只需要给他设置成0.75rem,就会自动适配各种手机
8:样式画完以后终于该上扫码支付的逻辑了,我按步骤记录一下
(1)申请一个测试号,测试号申请地址为https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index(因为扫码跳转到我们的H5项目然后支付相当于用户在微信客户端中访问第三方网页,所以第三方需要申请一个公众号,使用这个公众号来获取用户授权后的信息,但是本地调试期间我没有正式的公众号,只能用测试号)申请好以后可以看到测试号的appid和秘钥;往下翻还能找到一个网页授权获取用户基本信息,后面有一个修改;这三个东西是比较重要的
在这里插入图片描述

(2)画一个只有loading效果的中转页面,这个页面是扫码后跳转的第一个页面,在这个页面里面定义好三个参数,appid,scope,还有state(具体参考https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html#%E5%BE%AE%E4%BF%A1%E7%BD%91%E9%A1%B5%E6%8E%88%E6%9D%83%E8%83%BD%E5%8A%9B%E8%B0%83%E6%95%B4%E5%85%AC%E5%91%8A)然后设置好授权后的回跳地址(一般回跳地址就是支付页)引导用户打开授权页面

const APPID = "wx84438ca56d89890";
const MERCHANTID = "E240116572545436936";
const SCOPE = "snsapi_userinfo";
const STATE = "huhguhgudshkshksghdhgf";
// 授权回调地址,用户授权后先跳转到此页面,在此页面判断商户是否存在
const redirect_uri = encodeURIComponent(
  `https://${window.location.host}${import.meta.env.VITE_APP_BASE_DIR}transfer?appid=${APPID}&merchantId=${MERCHANTID}`
);
window.location.replace(`https://open.weixin.qq.com/connect/oauth2/authorize?appid=${APPID}&redirect_uri=${redirect_uri}&response_type=code&scope=${SCOPE}&state=${STATE}&time=${Date.now()}#wechat_redirect`)

(3)将项目运行起来,记录下运行的ip地址,(项目一定要运行在80端口,因为只有80端口可以不带端口号访问,因为微信开发者工具不支持带端口号访问)进入自己生成的测试号的管理地址,找到网页授权获取用户基本信息,后面有一个修改,点击修改,将自己项目运行的ip地址填进去(就是你项目里那个授权回调页面需要运行在这个你自己填写的授权回调域名下面)
在这里插入图片描述
在这里插入图片描述

(4)打开微信开发者工具,进入网页调试模式,在顶端地址栏输入你扫码后应该跳到的那个页面,测试是否可以正常跳转至微信授权页面
在这里插入图片描述

(5)在授权页面授权后,微信会跳转到第二步里面设置的授权回调地址,并且拼上一个授权后得到的code,这个code我传给后端,让后端用这个code去获取accessToken,再获取用户的unionId
在这里插入图片描述

(6)后端将unionId返回过来,前端再用这个unionId来跟后端进行交互

8:逻辑写完测完后就要部署了,这里也有几个坑要记录一下

第一个坑:

这个项目我给到部署人员后,他部署在了网站的一个子目录下面,而不是网站的根目录下面,这样就出现了部署以后进入页面会报错,比如这样,因为项目打包后默认还是去根目录找资源
在这里插入图片描述
解决方法(这是资料):
在这里插入图片描述
针对我的项目我做了如下配置
在这里插入图片描述

在这里插入图片描述

第二个坑

这个项目最初选用的方式是history模式,但是history模式需要服务端做对应的配置,所以改成了hash模式,但是部署以后问题来了,hash模式的路径是带#号的,微信授权回调地址又不能带#号(遇到#号微信就认为链接已经结束了导致会把参数拼接在路径的前面),否则就会出现很怪异的跳转链接参数和链接的顺序乱掉
所以hash模式也被pass掉了,最终改用了history模式,服务器端做了配置location,类似下面,
在这里插入图片描述
但是因为我们的项目不在根目录下,所以最终配置是这样的。
在这里插入图片描述

  • 10
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值