前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >「完结」一万三千字带你从零玩转系列之微信支付实战Uni-App搭建我的订单页面和接入支付、取消、退款、超时接口

「完结」一万三千字带你从零玩转系列之微信支付实战Uni-App搭建我的订单页面和接入支付、取消、退款、超时接口

原创
作者头像
杨不易呀
修改2023-11-22 20:11:08
4K6
修改2023-11-22 20:11:08
举报
文章被收录于专栏:杨不易呀杨不易呀

一、前言

欢迎来到本期的博客!不好意思搁置太久了剩下的文章我的订单页面,是在想不到好看的页面了自己的奇思妙想哈哈哈虽然一点丑但是功能齐全!!! 如果有小伙伴有优化UI的思路可进行在仓库当中提PR谢谢大家!

本篇将学习我的订单页面的搭建和订单页面的接口搭建比如购买课程页面下单了但是没有进行支付那么可以在我的订单页面进行再次支付、也可进行取消订单退款订单订单超时系统主动取消订单等知识点.快来学习吧~

? 本次为前端知识点如果不懂前端可以去仓库直接copy出来使用,如果有什么问题可以在评论区留言,我会第一时间回复大家的.关注我不迷路,如果本篇文章对你有所帮助,或者你有什么疑问,欢迎在评论区留言,我一般看到都会回复的。大家点赞支持一下哟~ ?

作者: 杨不易呀 在此之前我已经更新了 13 章微信支付实战教程同学们感兴趣可前往我的腾讯云主页查看学习!

本次项目使用技术栈

后端: SpringBoot3.1.x、Mysql8.0、MybatisPlus

前端: Vue3、Vite、ElementPlus

小程序: Uniapp、UviewPlus、Vue3

桌面应用: Electron以慢著称,为什么桌面QQ却选择它做架构升级?跟着大厂玩(electron-egg)

一、我的订单页面需求分析

img
img

可以看到我们的页面分为上下两块区域,上面区域我们已经在之前的文章当中完美实现直接拿来复用就完事了,下部分为一行 tabBar 作用为展示不同的状态订单.(还是使用 uview 的组件库即可实现 so easy to happy 切菜一样~)

订单模块

img
img

可以看到我们有标志性的功能 订单倒计时 有标题、支付人、支付金额、下单时间、和下单的时候如果没有支付则在我的订单页面可以再次发起支付请求、还有用户取消订单业务.

好了我们已经分析的差不多了是不是很简单哈哈哈来我们直接开造!!!

在此之前请先把该启动启动好

  1. 启动后台服务应用
  2. 启动内网穿透工具(我的是花生壳)
  3. 打开 Hbuilder 工具启动小程序项目

二、装修我的订单页面

yby6-uniApp-wechatPay-blog/pages目录下创建 order 文件夹在创建 order.vue 页面

为了大家的方便我直接贴不重要的初始化页面代码,这些你们都看的懂咱们之前已经写过啦~

复制下面的代码到 order.vue 页面当中

代码语言:html
复制
<!-- yangbuyi Copyright (c) https://yby6.com 2023. -->
<script setup>
  import { onLoad, onReady } from '@dcloudio/uni-app'
  import { getCurrentInstance, ref } from "vue";
  import Tabbar from "../tabbar/tabbar.vue";

  // 获取当前实例
  const { proxy } = getCurrentInstance()
  // 加载层
  const loading = ref(false)


  // ==========================生命周期==========================
  onLoad(() => {
    console.log('onLoad');
  });

  onReady(() => {
    console.log('onReady');
  });
</script>

<template>
  <view class="app-container">
    <view class="container">
      <!--   上部分   -->
      <view>
        <u-notice-bar color="red" text="注意:小程序可查看有限只渲染近50条支付信息,完整请前往PC端!!!"></u-notice-bar>
        <view class="PaymentChannel_title">
          <u-tooltip text="PC端微信支付系统: https://lzys522.cn/wx" copyText="https://lzys522.cn/wx"
            overlay></u-tooltip>
        </view>
        <view class="PaymentChannel_title">
          <u-tooltip text="注意:0.4以上,支付成功后可在订单列表进行退款."
            copyText="注意:0.4以上,支付成功后可在订单列表进行退款."
            overlay></u-tooltip>
        </view>
        <view class="PaymentChannel_title"
          style="color: red;  margin-bottom: 10px;font-size: 14px;height: auto !important;">
          <u-tooltip text="开源仓库: https://gitee.com/yangbuyi/wxDemo" copyText="https://gitee.com/yangbuyi/wxDemo"
            overlay></u-tooltip>
        </view>
      </view>
      <!--   下部分   -->
      <view>

      </view>

      <!--    加载层    -->
      <u-loading-page :loading="loading"/>
      <!--    菜单    -->
      <tabbar selected="1"></tabbar>
    </view>
  </view>
</template>

<style lang="scss" scoped>
  ::v-deep .u-cell__body__content {
    width: 70%;
  }

  .btn {
    margin-left: 6px;
    display: inline-block;
  }

  .payView {
    /*float:right*/
    display: inline-block;
    text-align: right;
    vertical-align: baseline;
    float: right;
  }

  .time {
    @include flex;
    align-items: center;

    &__custom {
      margin-top: 4px;
      width: 22px;
      height: 22px;
      background-color: $u-primary;
      border-radius: 4px;
      /* #ifndef APP-NVUE */
      display: flex;
      /* #endif */
      justify-content: center;
      align-items: center;

      &__item {
        color: #fff;
        font-size: 12px;
        text-align: center;
      }
    }

    &__doc {
      color: $u-primary;
      padding: 0px 4px;
    }

    &__item {
      color: #606266;
      font-size: 15px;
      margin-right: 4px;
    }
  }
</style>

修改 ?pages.json

pages数组当中新增

代码语言:html
复制
    {
      "path": "pages/order/order",
      "style": {
        "navigationBarTitleText": ""
      }
    },

list数组当中新增

代码语言:json
复制
{
  "pagePath": "pages/order/order"
},

完整配置

img
img

查看初始化页面

img
img

完美、接下来我们进行编写 tabars 状态滑块按钮

编写 Tabs

打开组件库 UviewPlus 注意我们是 vue3 所以是 3.x 版本

地址: https://uiadmin.net/uview-plus/components/tabs.html

img
img

随便选择你自己喜欢的直接复制对应代码即可~

编写 Tabs 数据

代码语言:html
复制
// ==========================数据==========================
  const tabList = ref([
    { name: "全部" },
    { name: "未支付" },
    { name: "退款中" },
    { name: "已退款" },
    { name: "支付成功" },
    { name: "超时关闭" },
    { name: "用户取消" }
  ]);
img
img
代码语言:html
复制
<u-tabs
  :list="tabList"
  lineWidth="30"
  lineColor="#ffb9b9"
  :activeStyle="{
  color: '#FF8B8B',
  fontWeight: 'bold',
  transform: 'scale(1.06)',
  }"
  :inactiveStyle="{
  color: '#303133',
  transform: 'scale(1)'
  }"
  itemStyle="padding-left: 15px; padding-right: 15px; height: 34px;margin-bottom: 2px;"
  >
</u-tabs>

查看效果

img
img

我感觉还不错 hahah ~

编写 tabs 的点击事件

img
img
img
img

同学们自己手动敲一遍吧冲冲

效果测试

img
img

编写列表模块

逻辑: 当我们切换状态的时候要去后端请求不同状态的数据并且渲染到小程序当中

地址: https://uiadmin.net/uview-plus/components/list.html

img
img

是不是感觉到了和我们页面的不一样,因为我自定义的呀,要不然为什么这么丑~

img
img
代码语言:html
复制
方法代码

// 底部触发
const scrolltolower = (data) => {
  console.log(data);
};

// 模拟数据
const loadmore = () => {
  for (let i = 0; i < 10; i++) {
    indexList.value.push({
      url: urls[2],
    });
  }
};

生命周期加载模拟数据
  
onLoad(() => {
  loadmore();
  console.log('onLoad');
});
  


页面代码
 <u-list
    @scrolltolower="scrolltolower"
>
  <u-list-item
      v-for="(item, index) in indexList"
      :key="index"
  >
    <u-cell>
      <template #title>
        <view>
          我是标题
        </view>
        <template #label>
          <view>
            我是子标题
          </view>
        </template>
      </template>
    </u-cell>
  </u-list-item>
</u-list>

查看效果

img
img

好的目前我们就已经搭建好了一个雏形,我们继续完善给他把标题、支付人、下单时间等进行编写,搞定后我们将要去编写后端代码接口请求列表数据.

三、搭建我的订单接口

需要的接口为我的订单列表分页接口,还记得我上次编写前端 PC 我的订单的时候写了一个么,我们还需要编写一个小程序端的因为我这里就只是允许展示前五十条信息~ 其余的可以通过查询条件来查哦~

打开后端代码修改 OrderInfoController.java 页面

img
img

同学们手动写一下把,新增 orderUniAppPage 接口

重新启动项目测试

img
img
img
img

?可以正常调用成功

四、小程序对接接口

api 目录下创建 orderInfo.js 文件

代码语言:html
复制
// yangbuyi Copyright (c) https://yby6.com 2023.

import request from '@/utils/request'

export default {
    // 查询订单列表
    orderUniAppPage(data) {
        return request({
            url: '/api/orderInfo/orderUniAppPage',
            method: 'get',
            params: data
        })
    }
}

编写调用函数

img
img

编写页面

这部分很简单我就直接把代码贴上来啦(简单且麻烦)

代码语言:html
复制
<u-list-item
  v-for="(item, index) in orderList" :key="index">
     <u-cell>
       <template #title>
       <view>
       <view>
       <view style="display: inline-block">
       <u-tag :text="item.title"></u-tag>
       </view>

       <view class="payView">
       <view>
       <u-tag :text="item.orderStatus" v-if="item.orderStatus === '未支付'"></u-tag>
       <u-tag :text="item.orderStatus" v-if="item.orderStatus === '支付成功'" type="success"></u-tag>
       <u-tag :text="item.orderStatus" v-if="item.orderStatus === '超时已关闭'" type="warning"></u-tag>
       <u-tag :text="item.orderStatus" v-if="item.orderStatus === '用户已取消'" type="info"></u-tag>
       <u-tag :text="item.orderStatus" v-if="item.orderStatus === '退款中'" type="danger"></u-tag>
       <u-tag :text="item.orderStatus" v-if="item.orderStatus === '已退款'" type="info"></u-tag>
       </view>

       </view>
       <view style="margin-top: 5px;">
       订单支付人: {{ item.title.split('-')[1] ? item.title.split('-')[1] : 'PC用户' }}
  </view>
    </view>
    </view>


    <template #label>
    <view style="float:left;">
    <view style="text-align: left;">
    订单金额:{{ item.totalFee / 100 }} 元
    </view>
    <view style="text-align: left;">
    <view style="display: inline-block;">
    下单时间: {{ item.createTime }}
  </view>
    </view>
    </view>
    <view style="float:right;margin-top: 5px;">

    <view class="btn" v-if="item.orderStatus === '支付成功'">
    <u-button size="small" type="primary"
 
    text="退款"></u-button>
      </view>

      <view class="btn" v-if="item.orderStatus === '未支付'">
      <u-button size="small" type="primary" :disabled="payBtnDisabled"
   
    text="支付"></u-button>
      </view>

      <view class="btn" v-if="item.orderStatus === '未支付'">
      <u-button size="small" type="error"
   
    text="取消"></u-button>
      </view>
      </view>
      </template>
      </template>
      </u-cell>
      </u-list-item>

效果展示

img
img

接下来就是对订单的操作了,待完成的有 支付按钮、取消按钮、退款按钮、倒计时超时取消订单 写了我三个小时如果有帮助到您麻烦点个赞~谢谢?

五、未支付按钮、取消按钮、退款按钮、倒计时超时取消订单功能需求介绍

未支付按钮

用于在 '购买课程页面'进行了下单但是未支付的情况,这时候千万查看我的订单那么应该可以继续支付订单,降低了后端的成本和订单下单量重复的问题.

取消按钮

用于在用户还未支付,用户不想要了那么会主观的主动的进行去取消订单,不想买了.

退款按钮

顾名思义用于用户在支付订单后(还未发货等一些情况)可进行申请退款操作

倒计时超时取消订单功能

这个的话就是我们系统完全需要的功能,如果用户在某个时间下单,下单完毕后我们不可能一直存在这个订单我们需要有个时间效益来进行限制这个订单的过期,那么一般电商的时间都是设置了 15 分钟倒计时系统主动发起超时订单取消接口.

以上 支付接口、取消订单接口、退款接口 我们已经在往期从零玩转完毕! 有同学如果需要的可前往查看.

六、接入用户主动取消订单

还记得我们上面写了三个按钮方法吗

它对应三个功能: 支付、取消、退款 接下来我们进行完善它!!!!

img
img

我们进行编写三个函数方法来进行点击看看效果

代码语言:go
复制
// 用户主动取消订单
const cancelOrder = (obj) => {
  console.log(obj);
}
// 用户断点支付
const toPay = (obj) => {
  console.log(obj);
}
// 用户主动退款
const refund = (obj) => {
  console.log(obj);
}
img
img

点击任意按钮会输出当前点击的对象(也就是后台的一条记录)信息

未支付订单

创建一条未支付订单

img
img

前往我的订单点击未支付状态查询

img
img

修改 weChatPay.js 新增取消订单接口 注意自己的后端接口是否是这个哦~

代码语言:go
复制
// 取消订单
export function cancel(orderNo) {
    return request({
        url: '/api/wx-pay/native/cancel/' + orderNo,
        method: 'post'
    })
}
img
img

编写取消订单函数

toast("订单取消成功"); 是我们上次封装的提示框

img
img
img
img

建议同学们自己手动敲一遍~

代码语言:go
复制
// 用户主动取消订单
const cancelOrder = (obj) => {
  console.log(obj);
  loading.value = true;
  cancel(obj.orderNo).then((res) => {
    toast("订单取消成功");
    // 刷新列表
    loadmore();
  });
}

测试主动取消订单功能

可以看到我们发起取消订单接口成功并且提示了我们还刷新了列表

img
img

七、接入用户断点支付功能

用于在 '购买课程页面'进行了下单但是未支付的情况,这时候千万查看我的订单那么应该可以继续支付订单,降低了后端的成本和订单下单量重复的问题.

下单接口在前面我们已经编写过前后端都写过所以现在接入很简单

修改 weCharPay.js新增下单接口(如果已经存在则无视)

代码语言:go
复制
// 统一JSAPI下单
export function JSAPI(productId, openId) {
    return request({
        'url': `/api/wx-pay/js-api/${ productId }`,
        'method': 'post',
        'params': {
            "openId": openId
        }
    })
}

编写下单函数

创建一条未支付订单

img
img

修改 toPay函数 直接将购买界面的支付代码 copy 过来即可哈哈哈

逻辑: 为了安全怕绕过登录直接进行支付,那么这里进行判断一下是否登录

img
img

建议同学们手动敲打一下

代码语言:go
复制
// 用户断点支付
const toPay = (obj) => {
  console.log(obj);

  const storageSync = uni.getStorageSync('token');
  const nickName = uni.getStorageSync('nickName');
  payBtnDisabled.value = true;
  if (!storageSync || !nickName) {
    payBtnDisabled.value = false;
    toast("还未登录欸!");
    return;
  }

  JSAPI(obj.productId, storageSync + "|" + nickName)
      .then((res) => {
        const wx = res.data;
        toast("创建订单成功正在拉起支付请稍等....");
        uni.requestPayment({
          provide: 'wxpay',
          timeStamp: wx.timeStamp,
          nonceStr: wx.nonceStr,
          package: wx.package,
          signType: wx.signType,
          paySign: wx.paySign,
          success: (res) => {
            console.log(res);
            payBtnDisabled.value = false;
          },
          fail: (res) => {
            console.log(res);
            toast("取消支付可继续点击支付重新发起");
            payBtnDisabled.value = false;
          },
        });
      })
      .catch((err) => {
        console.log(err);
        payBtnDisabled.value = false;
      });
}

测试断点支付

img
img

查看后端检查看看是否重新创建了订单 显然没有重新创建我们是进行判断了的

img
img

八、接入退款订单功能

查看效果

img
img

前往 uviewplus 组件库找到我们的 modal 弹出层

地址: https://uiadmin.net/uview-plus/components/modal.html

img
img

新增变量

img
img
代码语言:go
复制
// 退款弹出
const refundDialogVisible = ref(false);
// 退款表单
const refundForm = ref({
  orderNo: '',
  refundNo: '',
  reason: '',
});
// 退款表单验证规则
const rules = ref({
  'refundNo': {
    type: 'number',
    required: true,
    max: 4,
    message: '请填写后四位交易订单号(数字)',
    trigger: [ 'blur', 'change' ]
  },
  'reason': {
    type: 'string',
    required: true,
    message: '请填写退款原因',
    trigger: [ 'blur', 'change' ]
  },
})

编写弹出层退款

思路在弹出层当中嵌入 form 表单

img
img
代码语言:go
复制
      <!--  弹出层退款   -->
      <u-modal
          :loading="loading"
          title="申请退款"
          :show="refundDialogVisible"
          showCancelButton
          @confirm="refundOrder"
          @cancel="closeDialog "
      >
        <view>
          <!-- 注意,如果需要兼容微信小程序,最好通过setRules方法设置rules规则 -->
          <u-form
              labelPosition="left"
              :model="refundForm"
              :rules="rules"
              ref="uForm"
          >
            <u-form-item
                labelWidth="100px"
                label="交易订单号"
                prop="refundNo"
                borderBottom
                ref="item1"
            >
              <u-input
                  v-model="refundForm.refundNo"
                  border="none"
              ></u-input>
            </u-form-item>
            <u-form-item
                labelWidth="100px"
                label="退款原因"
                prop="reason"
                borderBottom
                ref="item2"
            >
              <u-input
                  v-model="refundForm.reason"
                  border="none"
              ></u-input>
            </u-form-item>
          </u-form>
        </view>
      </u-modal>

编写关闭退款弹出层

img
img
代码语言:go
复制
//关闭退款对话框
const closeDialog = () => {
  console.log('close.................');
  refundDialogVisible.value = false;
  refundForm.value = {
    orderNo: '',
    refundNo: '',
    reason: '',
  };
  refundSubmitBtnDisabled.value = false;
};

用于用户不行进行退款了的情况

编写确定退款按钮请求

后端接口我们在之前的 PC 系列 文章已经编写和讲解过我们看看需要传递什么

  • @param orderNo 订单号
  • @param refundsNo 退款单号
  • @param reason 退款原因
img
img

修改 weChatPay.js新增退款接口

img
img
代码语言:go
复制
// 申请退款
export function refunds(orderNo, reason, refundNo) {
    return request({
        url: '/api/wx-pay/native/refunds/' + orderNo + '/' + refundNo + "/" + reason,
        method: 'post'
    })
}

编写发起退款请求函数

先进行看看退款请求按钮是否是禁用状态 禁用则不允许提交请求

开启我们的组件库表单的非空校验并且限制最大输入的订单号为 4 位因为后端我们进行了单独的处理

img
img

测试退款功能

创建一个订单进行支付成功

img
img
img
img

记住我们这次的交易订单号后四位 我这里是 3070

直接找到我们刚刚支付的订单

img
img

填写对应订单信息进行提交退款信息

img
img

提交成功需要等待一两分钟

img
img

退款入账提醒

img
img

后端回调日志

img
img

输入图片说明
输入图片说明

最后

本章节文章相当于已经完结 《从零玩转系列之微信支付》在我准备开启这篇教程我当时是感受支付的乐趣并且感觉官方文档有些麻烦自此萌生出写一篇从零玩转的微信支付可能会有同学觉得简单,调用API嘛但是努力写文章可以帮助到需要的人那么这件事情就不简单啦~ 完结 ?

接下来就剩下倒计时超时取消订单功能了由于此功能有些长那么将分开发布衍生新的一篇文章构建思路、测试程序、等一系列耗时的事情写了我差不多六个小时如果有帮助到您麻烦点个赞~谢谢?

本期结束咱们下次再见?~

? 关注我不迷路,如果本篇文章对你有所帮助,或者你有什么疑问,欢迎在评论区留言,我一般看到都会回复的。大家点赞支持一下哟~ ?

我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、前言
  • 一、我的订单页面需求分析
    • 订单模块
    • 二、装修我的订单页面
      • 完整配置
        • 查看初始化页面
          • 编写 Tabs
            • 编写 Tabs 数据
              • 查看效果
                • 编写 tabs 的点击事件
                  • 效果测试
                    • 编写列表模块
                      • 查看效果
                      • 三、搭建我的订单接口
                        • 重新启动项目测试
                        • 四、小程序对接接口
                          • 编写调用函数
                            • 编写页面
                              • 效果展示
                              • 五、未支付按钮、取消按钮、退款按钮、倒计时超时取消订单功能需求介绍
                                • 未支付按钮
                                  • 取消按钮
                                    • 退款按钮
                                      • 倒计时超时取消订单功能
                                      • 六、接入用户主动取消订单
                                        • 未支付订单
                                          • 编写取消订单函数
                                            • 测试主动取消订单功能
                                            • 七、接入用户断点支付功能
                                              • 编写下单函数
                                                • 测试断点支付
                                                • 八、接入退款订单功能
                                                  • 编写弹出层退款
                                                    • 编写关闭退款弹出层
                                                      • 编写确定退款按钮请求
                                                        • 测试退款功能
                                                          • 填写对应订单信息进行提交退款信息
                                                          • 提交成功需要等待一两分钟
                                                          • 退款入账提醒
                                                          • 后端回调日志
                                                      • 最后
                                                        • 接下来就剩下倒计时超时取消订单功能了由于此功能有些长那么将分开发布衍生新的一篇文章构建思路、测试程序、等一系列耗时的事情写了我差不多六个小时如果有帮助到您麻烦点个赞~谢谢?
                                                        相关产品与服务
                                                        云开发 CloudBase
                                                        云开发(Tencent CloudBase,TCB)是腾讯云提供的云原生一体化开发环境和工具平台,为200万+企业和开发者提供高可用、自动弹性扩缩的后端云服务,可用于云端一体化开发多种端应用(小程序、公众号、Web 应用等),避免了应用开发过程中繁琐的服务器搭建及运维,开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。
                                                        领券
                                                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
                                                        http://www.vxiaotou.com