目录
支付模块的一个大致过程主要分为
支付页面的一个基础布局、数据的渲染、支付流程、等待支付还有一个支付结果的展示
基础布局的话 就是配置路由和支付页面基础布局
新建文件 src/views/Member/Pay.vue
- <script name="XtxPayPage" setup lang="ts"></script>
- <template>
- <div class="xtx-pay-page">
- <div class="container">
- <XtxBread>
- <XtxBreadItem to="/">首页</XtxBreadItem>
- <XtxBreadItem to="/cart">购物车</XtxBreadItem>
- <XtxBreadItem>支付订单</XtxBreadItem>
- </XtxBread>
- <!-- 付款信息 -->
- <div class="pay-info">
- <span class="icon iconfont icon-queren2"></span>
- <div class="tip">
- <p>订单提交成功!请尽快完成支付。</p>
- <p>支付还剩 <span>24分59秒</span>, 超时后将取消订单</p>
- </div>
- <div class="amount">
- <span>应付总额:</span>
- <span>¥5673.00</span>
- </div>
- </div>
- <!-- 付款方式 -->
- <div class="pay-type">
- <p class="head">选择以下支付方式付款</p>
- <div class="item">
- <p>支付平台</p>
- <a class="btn wx" href="javascript:;"></a>
- <a class="btn alipay" href="javascript:;"></a>
- </div>
- <div class="item">
- <p>支付方式</p>
- <a class="btn" href="javascript:;">招商银行</a>
- <a class="btn" href="javascript:;">工商银行</a>
- <a class="btn" href="javascript:;">建设银行</a>
- <a class="btn" href="javascript:;">农业银行</a>
- <a class="btn" href="javascript:;">交通银行</a>
- </div>
- </div>
- </div>
- </div>
- </template>
-
- <style scoped lang="less">
- .pay-info {
- background: #fff;
- display: flex;
- align-items: center;
- height: 240px;
- padding: 0 80px;
- .icon {
- font-size: 80px;
- color: #1dc779;
- }
- .tip {
- padding-left: 10px;
- flex: 1;
- p {
- &:first-child {
- font-size: 20px;
- margin-bottom: 5px;
- }
- &:last-child {
- color: #999;
- font-size: 16px;
- }
- }
- }
- .amount {
- span {
- &:first-child {
- font-size: 16px;
- color: #999;
- }
- &:last-child {
- color: @priceColor;
- font-size: 20px;
- }
- }
- }
- }
- .pay-type {
- margin-top: 20px;
- background-color: #fff;
- padding-bottom: 70px;
- p {
- line-height: 70px;
- height: 70px;
- padding-left: 30px;
- font-size: 16px;
- &.head {
- border-bottom: 1px solid #f5f5f5;
- }
- }
- .btn {
- width: 150px;
- height: 50px;
- border: 1px solid #e4e4e4;
- text-align: center;
- line-height: 48px;
- margin-left: 30px;
- color: #666666;
- display: inline-block;
- &.active,
- &:hover {
- border-color: @xtxColor;
- }
- &.alipay {
- background: url(https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/7b6b02396368c9314528c0bbd85a2e06.png)
- no-repeat center / contain;
- }
- &.wx {
- background: url(https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/c66f98cff8649bd5ba722c2e8067c6ca.jpg)
- no-repeat center / contain;
- }
- }
- }
- </style>
src/router/index.ts 配置二级路由,不需要加 /
{
path: 'member/pay',
component: () => import('@/views/Member/Pay.vue')
}
订单跳转时要传递订单id参数
页面跳转需要思考的问题
router.push() 和 router.replace() 的区别是什么?
push 合适,还是用 replace 更合适呢,为什么? replace 更合适,下单后商品信息已经没有了,后退回去无意义。id- const submitCheckout = async () => {
- // 如果地址为空,不能提交订单
- if (!checkout.showAddress) {
- return Message.warning('请选择收货地址')
- }
- const res = await request.post('/member/order', {
- goods: checkout.checkoutInfo.goods.map((item) => {
- return {
- skuId: item.skuId,
- count: item.count,
- }
- }),
- addressId: checkout.showAddress.id,
- })
- // 成功提醒用户
- Message({ type: 'success', text: '下单成功~' })
- // 🔔重新获取购物车列表
- + cart.getCartList()
- // 跳转到支付页面
-
- + router.replace('/member/pay?id=' + res.data.result.id)
- }
就是渲染真实支付数据
(1)先提供数据类型
- export interface OrderPayInfo {
- id: string
- createTime: string
- payType: number
- orderState: number
- payLatestTime: string
- countdown: number
- postFee: number
- payMoney: number
- payChannel: number
- totalMoney: number
- totalNum: number
- deliveryTimeType: number
- receiverContact: string
- receiverMobile: string
- provinceCode: string
- cityCode: string
- countyCode: string
- receiverAddress: string
- payTime?: any
- consignTime?: any
- endTime?: any
- closeTime?: any
- evaluationTime?: any
- skus: {
- id: string
- spuId: string
- name: string
- quantity: number
- image: string
- realPay: number
- curPrice: number
- totalMoney?: any
- properties: {
- propertyMainName: string
- propertyValueName: string
- }[]
- attrsText: string
- }[]
- arrivalEstimatedTime?: any
- }
(2)发送请求获取支付数据
(3)渲染支付信息
- <div class="pay-info">
- <span class="icon iconfont icon-queren2">span>
- <div class="tip">
- <p>订单提交成功!请尽快完成支付。p>
- <p>
- 支付还剩 <span>{{ order?.countdown }}
- >, 超时后将取消订单
- p>
- div>
- <div class="amount">
- <span>应付总额:span>
- <span>¥{{ order?.totalMoney }}span>
- div>
- div>
支付页面 -倒计时渲染
(1)开始倒计时
- const showTime = ref(0)
-
- onMounted(async () => {
- const res = await request.get<ApiRes<OrderPayInfo>>(`/member/order/${id}`)
- console.log('GET', `/member/order/${id}`, res.data.result)
- order.value = res.data.result
- const { time, start } = useCountDown(order.value.countdown)
- start()
- watch(time, (value) => {
- showTime.value = value
- })
- })
(2)安装dayjs
yarn add dayjs
(3)提供方法(注意:vue3没有过滤器)
const formatTime = (time: number) => {
return dayjs.unix(time).format('mm分ss秒')
}
(4)渲染
支付还剩 {{ formatTime(showTime) }} , 超时后将取消订单
(5)倒计时为0,重新跳到购物车页面
- // 将初始值, 同步给showTime
- showTime.value = order.value.countdown
-
- watch(time, (value) => {
- showTime.value = value
-
- if (value <= 0) {
- // 跳转页面, 并提醒用户, 订单已超时
- router.replace('/cart')
- Message.warning('订单已超时, 请重新下单')
- }
- })
支付 - 支付流程
分析


步骤
●PC前台点击支付按钮,新开标签页打开后台提供的支付链接带上订单ID还有回跳地址
●后台服务发起支付,等待支付结果,修改订单状态,回跳PC前台结果页
●PC前台在结果页获取回跳URL参数订单ID查询支付状态,展示支付结果
# 支付地址回调地址(可变)
http://www.corho.com:8080/#/pay/callback
买家账号jfjbwb4477@sandbox.com
登录密码111111
支付密码111111
支付 - 等待支付
目的:支付打开新页,当前页打开提示框
- 在
utils/request.ts中导出基础路径
export const baseURL = 'https://apipc-xiaotuxian-front.itheima.net/'
const request = axios.create({
baseURL,
// baseURL: 'http://pcapi-xiaotuxian-front.itheima.net/',
timeout: 5000
})
2.拼接支付链接
const redirectUrl = encodeURIComponent('http://www.corho.com:8080/#/pay/callback')
const payUrl = `${baseURL}pay/aliPay?orderId=${route.query.id}&redirect=${redirectUrl}`
3.增加跳转链接
支付结果展示
实现步骤
- 准备一个基础页面
- 根据地址订单ID查询订单状态进行展示,或者是地址栏支付结果
具体代码
(1)准备结果页面 src/views/Member/Pay/Callback.vue
-
- <template>
- <div class="xtx-pay-page">
- <div class="container">
- <XtxBread>
- <XtxBreadItem to="/">首页XtxBreadItem>
- <XtxBreadItem to="/cart">购物车XtxBreadItem>
- <XtxBreadItem>支付结果XtxBreadItem>
- XtxBread>
-
- <div class="pay-result">
- <span class="iconfont icon-queren2 green">span>
-
- <p class="tit">订单支付成功p>
- <p class="tip">我们将尽快为您发货,收货期间请保持手机畅通p>
- <p>支付方式:<span>微信支付span>p>
- <p>支付金额:<span>¥1899.00span>p>
- <div class="btn">
- <XtxButton type="primary" style="margin-right:20px">查看订单XtxButton>
- <XtxButton type="gray">进入首页XtxButton>
- div>
- <p class="alert">
- <span class="iconfont icon-tip">span>
- 温馨提示:小兔鲜儿不会以订单异常、系统升级为由要求您点击任何网址链接进行退款操作,保护资产、谨慎操作。
- p>
- div>
- div>
- div>
- template>
-
- <style scoped lang="less">
- .pay-result {
- padding: 100px 0;
- background: #fff;
- text-align: center;
- > .iconfont {
- font-size: 100px;
- }
- .green {
- color: #1dc779;
- }
- .red {
- color: @priceColor;
- }
- .tit {
- font-size: 24px;
- }
- .tip {
- color: #999;
- }
- p {
- line-height: 40px;
- font-size: 16px;
- }
- .btn {
- margin-top: 50px;
- }
- .alert {
- font-size: 12px;
- color: #999;
- margin-top: 50px;
- }
- }
- style>
(2)配置路由
- {
- path: '/',
- component: Layout,
- children: [
- ...,
- {
- path: '/pay/callback',
- component: () => import('@/views/member/pay/callback.vue')
- }
- ]
- },
(3)根据地址订单id查询订单状态进行展示
-
- <template>
- <div class="xtx-pay-page">
- <div class="container">
- <XtxBread>
- <XtxBreadItem to="/">首页XtxBreadItem>
- <XtxBreadItem to="/cart">购物车XtxBreadItem>
- <XtxBreadItem>支付结果XtxBreadItem>
- XtxBread>
-
- <div class="pay-result">
- <span v-if="payResult" class="iconfont icon-queren2 green">span>
- <span v-else class="iconfont icon-shanchu red">span>
- <p class="tit">{{ payResult ? '订单支付成功' : '订单支付失败' }}p>
- <p class="tip">我们将尽快为您发货,收货期间请保持手机畅通p>
- <p>支付方式:<span>支付宝支付span>p>
- <p>
- 支付金额:<span>{{ order.payMoney }}span>
- p>
- <div class="btn">
- <XtxButton type="primary" style="margin-right: 20px">
- 查看订单
- XtxButton>
- <XtxButton type="gray">进入首页XtxButton>
- div>
- <p class="alert">
- <span class="iconfont icon-tip">span>
- 温馨提示:小兔鲜儿不会以订单异常、系统升级为由要求您点击任何网址链接进行退款操作,保护资产、谨慎操作。
- p>
- div>
- div>
- div>
- template>