支付功能

组件准备

  • src/router/index.js

    1. const router = [
    2. // 支付页
    3. {
    4. path: '/pay/:courseId/',
    5. name: 'pay',
    6. component: () => import(/* webpackChunkName: 'pay' */'@/views/pay/index'),
    7. meta: { requiresAuth: true },
    8. props: true
    9. },
    10. ]
  • src/views/course-info/index.vue

    1. // 支付
    2. handlePay () {
    3. // 检测是否登陆
    4. if (this.$store.state.user) {
    5. // 如果已登陆。跳转支付页
    6. this.$router.push({
    7. name: 'pay',
    8. params: {
    9. courseId: this.courseId
    10. }
    11. })
    12. } else {
    13. // 如果未登陆,跳转登陆,并记录本页面信息,登陆成功后跳回当前页
    14. this.$router.push({
    15. name: 'login',
    16. query: {
    17. redirect: this.$route.fullPath
    18. }
    19. })
    20. }
    21. },

布局处理与数据绑定

  • src/views/pay/index.vue ```vue
``` ### 支付结构处理 - src/views/pay/index.vue ```vue
  1. <a name="DNP0W"></a>
  2. ### 接口封装
  3. - src/servires/pay.js
  4. ```javascript
  5. import request from '@/utils/request'
  6. // 创建商品订单接口
  7. // - goodsId 商品 ID 必传
  8. export const createOrder = data => {
  9. return request({
  10. method: 'POST',
  11. url: '/front/order/saveOrder',
  12. data
  13. })
  14. }
  15. // 获取支付方式接口
  16. // - shopOrderNo 订单号必传
  17. export const getPayInfo = params => {
  18. return request({
  19. method: 'GET',
  20. url: '/front/pay/getPayInfo',
  21. params
  22. })
  23. }
  24. // 创建订单(发起支付)
  25. // - goodsOrderNo, channel, returnUrl 必传
  26. export const initPayment = data => {
  27. return request({
  28. method: 'POST',
  29. url: '/front/pay/saveOrder',
  30. data
  31. })
  32. }
  33. // 查询订单(查询支付结果)
  34. // - orderNo 订单号必传
  35. export const getPayResult = params => {
  36. return request({
  37. method: 'GET',
  38. url: '/front/pay/getPayResult',
  39. headers: { 'content-type': 'application/json' },
  40. params
  41. })
  42. }
  • src/views/pay/index.vue

    1. <script>
    2. import { createOrder, getPayInfo } from '@/services/pay'
    3. export default {
    4. name: 'Pay',
    5. props: {
    6. courseId: {
    7. type: [String, Number],
    8. required: true
    9. }
    10. },
    11. data () {
    12. return {
    13. // 课程信息
    14. course: {},
    15. // 支付方式
    16. radio: 1,
    17. // 订单号
    18. orderNo: null,
    19. // 支付方式信息
    20. payInfo: {}
    21. }
    22. },
    23. methods: {
    24. // 支付
    25. // 加载支付信息
    26. async loadOrder () {
    27. // 创建订单,获取订单号
    28. const { data } = await createOrder({
    29. goodsId: this.courseId
    30. })
    31. this.orderNo = data.content.orderNo
    32. // 获取支付方式
    33. const { data: payInfo } = await getPayInfo({
    34. shopOrderNo: this.orderNo
    35. })
    36. this.payInfo = payInfo.content.supportChannels
    37. },
    38. // 获取课程信息
    39. async loadCourse () {
    40. const { data } = await getCourseById({
    41. courseId: this.courseId
    42. })
    43. this.course = data.content
    44. }
    45. },
    46. created () {
    47. this.loadCourse()
    48. this.loadOrder()
    49. }
    50. }
    51. </script>

    支付请求

    1. <script>
    2. import { initPayment, getPayResult } from '@/services/pay'
    3. export default {
    4. methods: {
    5. // 支付
    6. async handlePay () {
    7. // 发起支付请求,获取地址与支付订单号
    8. const { data } = await initPayment({
    9. goodsOrderNo: this.orderNo,
    10. channel: this.radio === 1 ? 'weChat' : 'aliPay',
    11. returnUrl: 'http://edufront.lagou.com/'
    12. })
    13. console.log(data)
    14. // 接收响应地址,并进行跳转
    15. window.location.href = data.content.payUrl
    16. const timer = setInterval(async () => {
    17. // 发起查询支付结果请求
    18. const { data: payResult } = await getPayResult({
    19. orderNo: data.content.orderNo
    20. })
    21. // 如果支付结果成功,清除定时器,并提示购买成功,跳回学习页
    22. if (payResult.content && payResult.content.status === 2) {
    23. clearInterval(timer)
    24. this.$toast.success('购买成功')
    25. this.$router.push({
    26. name: 'learn'
    27. })
    28. }
    29. }, 1000)
    30. },
    31. }
    32. }
    33. </script>

    打包优化

    配置文件

  • vue.config.js ```javascript module.exports = { // 生产环境不生成 .map productionSourceMap: false, // 不单独打包 css css: { extract: false },

}

  1. <a name="fU4wn"></a>
  2. ### 图片压缩
  3. 安装插件:
  4. ```powershell
  5. npm install image-webpack-loader
  • vue.config.js

    1. module.exports = {
    2. chainWebpack: config => {
    3. // 图片压缩 loader 配置
    4. config.module
    5. .rule('images')
    6. .use('image-webpack-loader')
    7. .loader('image-webpack-loader')
    8. .options({
    9. bypassOnDebug: true
    10. })
    11. .end()
    12. }
    13. }

Vant 按需引入

安装插件:

  1. npm install babel-plugin-import -D

配置文件:babel.config.js

  1. module.exports = {
  2. presets: [
  3. '@vue/cli-plugin-babel/preset'
  4. ],
  5. plugins: [
  6. ['import', {
  7. libraryName: 'vant',
  8. libraryDirectory: 'es',
  9. style: true
  10. }]
  11. ]
  12. }

CDN 引入

  • public/index.html ```html <!DOCTYPE html>

  1. - vue.config.js
  2. ```javascript
  3. module.exports = {
  4. configureWebpack: {
  5. // 通过 CDN 引入
  6. externals: {
  7. vue: 'Vue',
  8. vant: 'vant'
  9. }
  10. }
  11. }