refactor(daxpay): 重构收银台界面和支付流程- 更新了 AlipayAuth、WechatAuth、AlipayCashierCode、WechatCashierCode、AliAggregate、WechatAggregate 和 CheckoutPay 组件的结构和样式

- 优化了支付流程,增加了加载状态和错误处理
-调整了订单信息的展示方式,使其更加清晰和详细
- 统一了支付按钮的样式和行为
- 重构了部分 API 接口,增加了主键字段
This commit is contained in:
DaxPay
2024-12-04 19:22:55 +08:00
parent db4a87d3ae
commit 7f95a9bec3
10 changed files with 117 additions and 110 deletions

9
components.d.ts vendored
View File

@@ -11,8 +11,17 @@ declare module 'vue' {
Logo: typeof import('./src/components/Logo.vue')['default'] Logo: typeof import('./src/components/Logo.vue')['default']
SvgIcon: typeof import('./src/components/SvgIcon.vue')['default'] SvgIcon: typeof import('./src/components/SvgIcon.vue')['default']
VanButton: typeof import('vant/es')['Button'] VanButton: typeof import('vant/es')['Button']
VanCell: typeof import('vant/es')['Cell']
VanCellGroup: typeof import('vant/es')['CellGroup']
VanCol: typeof import('vant/es')['Col']
VanConfigProvider: typeof import('vant/es')['ConfigProvider'] VanConfigProvider: typeof import('vant/es')['ConfigProvider']
VanField: typeof import('vant/es')['Field']
VanGrid: typeof import('vant/es')['Grid']
VanGridItem: typeof import('vant/es')['GridItem']
VanLoading: typeof import('vant/es')['Loading'] VanLoading: typeof import('vant/es')['Loading']
VanOverlay: typeof import('vant/es')['Overlay']
VanRow: typeof import('vant/es')['Row']
VanSpace: typeof import('vant/es')['Space']
VanSubmitBar: typeof import('vant/es')['SubmitBar'] VanSubmitBar: typeof import('vant/es')['SubmitBar']
} }
} }

View File

@@ -9,3 +9,10 @@ body {
.van-action-sheet__cancel { .van-action-sheet__cancel {
color: var(--van-primary-color) !important; color: var(--van-primary-color) !important;
} }
.loading-wrapper {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}

View File

@@ -1,6 +1,6 @@
<template> <template>
<van-overlay v-show="show" :show="true"> <van-overlay v-show="show" :show="true">
<div class="wrapper" @click.stop> <div class="loading-wrapper" @click.stop>
<van-loading size="24px"> <van-loading size="24px">
获取中... 获取中...
</van-loading> </van-loading>
@@ -60,12 +60,6 @@ async function init() {
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
.wrapper {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
.block { .block {
width: 120px; width: 120px;

View File

@@ -1,6 +1,6 @@
<template> <template>
<van-overlay v-show="show" :show="true"> <van-overlay v-show="show" :show="true">
<div class="wrapper" @click.stop> <div class="loading-wrapper" @click.stop>
<van-loading size="24px"> <van-loading size="24px">
获取中... 获取中...
</van-loading> </van-loading>
@@ -47,12 +47,6 @@ async function init() {
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
.wrapper {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
.block { .block {
width: 120px; width: 120px;

View File

@@ -98,7 +98,7 @@ function initData() {
getCashierTypeConfig(CashierTypeEnum.ALIPAY, code as string).then(({ data }) => { getCashierTypeConfig(CashierTypeEnum.ALIPAY, code as string).then(({ data }) => {
cashierTypeConfig.value = data cashierTypeConfig.value = data
}).catch((res) => { }).catch((res) => {
router.push({ name: 'ErrorResult', query: { msg: res.message } }) router.push({ name: 'ErrorResult', query: { msg: res.message }, replace: true })
}) })
} }

View File

@@ -2,7 +2,7 @@
<div v-if="show"> <div v-if="show">
<div class="container"> <div class="container">
<div style="font-size: 28px;margin-top: 10px;"> <div style="font-size: 28px;margin-top: 10px;">
{{ cashierTypeConfig.cashierName || '微信收银台' }} {{ cashierTypeConfig.name || '微信收银台' }}
</div> </div>
<div class="amount-display"> <div class="amount-display">
<p style="font-size: 20px"> <p style="font-size: 20px">
@@ -114,7 +114,7 @@ function init() {
const url = res.data const url = res.data
location.replace(url) location.replace(url)
}).catch((res) => { }).catch((res) => {
router.push({ name: 'ErrorResult', query: { msg: res.message } }) router.push({ name: 'ErrorResult', query: { msg: res.message }, replace: true })
}) })
} }
else { else {
@@ -133,14 +133,14 @@ function initData() {
getCashierTypeConfig(CashierTypeEnum.WECHAT_PAY, code as string).then(({ data }) => { getCashierTypeConfig(CashierTypeEnum.WECHAT_PAY, code as string).then(({ data }) => {
cashierTypeConfig.value = data cashierTypeConfig.value = data
}).catch((res) => { }).catch((res) => {
router.push({ name: 'ErrorResult', query: { msg: res.message } }) router.push({ name: 'ErrorResult', query: { msg: res.message }, replace: true })
}) })
// 认证获取OpenId // 认证获取OpenId
auth(authParam.value).then(({ data }) => { auth(authParam.value).then(({ data }) => {
openId.value = data.openId as string openId.value = data.openId as string
}).catch((res) => { }).catch((res) => {
router.push({ name: 'ErrorResult', query: { msg: res.message } }) router.push({ name: 'ErrorResult', query: { msg: res.message }, replace: true })
}) })
} }

View File

@@ -174,8 +174,8 @@ export interface CheckoutConfigResult {
* 收银台分类配置 * 收银台分类配置
*/ */
export interface CheckoutGroupConfigResult { export interface CheckoutGroupConfigResult {
/** 类型 */ /** 主键 */
type?: string id?: string
/** 名称 */ /** 名称 */
name?: string name?: string
/** 配置项列表 */ /** 配置项列表 */
@@ -186,6 +186,8 @@ export interface CheckoutGroupConfigResult {
* 收银台配置项 * 收银台配置项
*/ */
export interface CheckoutItemConfigResult { export interface CheckoutItemConfigResult {
/** 主键 */
id?: string
/** 发起调用的类型 */ /** 发起调用的类型 */
callType?: string callType?: string
/** 名称 */ /** 名称 */

View File

@@ -1,13 +1,41 @@
<template> <template>
<div v-if="show"> <div v-if="show">
123 <van-overlay :show="loading">
<div class="loading-wrapper" @click.stop>
<van-loading size="24px">
支付中...
</van-loading>
</div>
</van-overlay>
<van-cell-group inset title="订单信息">
<van-cell title="金额" title-style="font-size: 22px;color: red">
<template #default>
<span style="font-size: 22px;color: red">{{ orderAndConfig.order.amount }}</span>
</template>
</van-cell>
<van-field label="标题" :model-value="orderAndConfig.order.title" readonly />
<van-field label="订单号" :model-value="orderAndConfig.order.bizOrderNo" readonly />
<van-field label="支付号" :model-value="orderAndConfig.order.orderNo" readonly />
<van-field label="描述" rows="2" type="textarea" :model-value="orderAndConfig.order.description" readonly />
</van-cell-group>
<van-cell-group inset :title="group.name" v-for="group in orderAndConfig.groupConfigs" :key="group.id">
<van-space direction="vertical" fill>
<van-button @click="pay(config)" type="primary" v-for="config in group.items" :key="config.id" block>{{ config.name }}</van-button>
</van-space>
</van-cell-group>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import { onMounted, ref } from 'vue' import { onMounted, ref } from 'vue'
import type { CheckoutOrderAndConfigResult } from './CheckoutPay.api' import {
CheckoutItemConfigResult,
CheckoutOrderAndConfigResult,
checkoutPay,
CheckoutPayParam
} from './CheckoutPay.api'
import { getOrderAndConfig } from './CheckoutPay.api' import { getOrderAndConfig } from './CheckoutPay.api'
import { CheckoutTypeEnum } from '@/enums/daxpay/DaxPayEnum' import { CheckoutTypeEnum } from '@/enums/daxpay/DaxPayEnum'
import router from '@/router' import router from '@/router'
@@ -17,12 +45,14 @@ const route = useRoute()
const { orderNo } = route.params const { orderNo } = route.params
const ua = navigator.userAgent const ua = navigator.userAgent
const show = ref(false) const show = ref(false)
const loading = ref(false)
const orderAndConfig = ref<CheckoutOrderAndConfigResult>({ const orderAndConfig = ref<CheckoutOrderAndConfigResult>({
order: {}, order: {},
config: {}, config: {},
groupConfigs: [], groupConfigs: [],
}) })
/** /**
* 初始化 * 初始化
*/ */
@@ -37,10 +67,13 @@ async function initData() {
// 获取收银台配置 // 获取收银台配置
await getOrderAndConfig(orderNo, CheckoutTypeEnum.H5).then(({ data }) => { await getOrderAndConfig(orderNo, CheckoutTypeEnum.H5).then(({ data }) => {
orderAndConfig.value = data orderAndConfig.value = data
}).catch((res) => {
router.push({ name: 'ErrorResult', query: { msg: res.message }, replace: true })
}) })
// 判断是否自动升级为聚合控制台 // 判断是否自动升级为聚合控制台
if (orderAndConfig.value.config.h5AutoUpgrade) { if (orderAndConfig.value.config.h5AutoUpgrade) {
await goAggregate() goAggregate()
return
} }
show.value = true show.value = true
} }
@@ -54,14 +87,25 @@ function goAggregate() {
} }
else if (ua.includes('Alipay')) { else if (ua.includes('Alipay')) {
router.push({ path: `/aggregate/alipay/${orderNo}`, replace: true }) router.push({ path: `/aggregate/alipay/${orderNo}`, replace: true })
} else {
show.value = true
} }
} }
/** /**
* 发起支付 * 发起支付
*/ */
function pay(){ function pay(config: CheckoutItemConfigResult){
loading.value = true
const from = {
orderNo: orderNo,
itemId: config.id
} as CheckoutPayParam
checkoutPay(from).then(({data}) => {
loading.value = false
// 跳转到支付页面
location.replace(data.payBody)
})
} }
</script> </script>

View File

@@ -1,19 +1,24 @@
<template> <template>
<div> <div>
<div class="container"> <van-overlay :show="loading">
<div style="font-size: 28px;margin-top: 10px;"> <div class="loading-wrapper" @click.stop>
{{ aggregateInfo.config.name || '支付宝收银台' }} <van-loading size="24px">
支付中...
</van-loading>
</div> </div>
<div class="amount-display"> </van-overlay>
<p style="font-size: 20px"> <van-cell-group inset title="订单信息">
订单 <van-cell title="金额" title-style="font-size: 22px;color: red">
</p> <template #default>
<p style="font-size: 32px;"> <span style="font-size: 22px;color: red">{{ aggregateInfo.order.amount }}</span>
¥ {{ aggregateInfo.order.amount || 0.00 }} </template>
</p> </van-cell>
</div> <van-field label="标题" :model-value="aggregateInfo.order.title" readonly />
</div> <van-field label="订单号" :model-value="aggregateInfo.order.bizOrderNo" readonly />
<van-submit-bar :price="(aggregateInfo.order.amount || 0)*100" button-text="支付" @submit="pay" /> <van-field label="支付号" :model-value="aggregateInfo.order.orderNo" readonly />
<van-field label="描述" rows="2" type="textarea" :model-value="aggregateInfo.order.description" readonly />
</van-cell-group>
<van-submit-bar safe-area-inset-bottom :price="(aggregateInfo.order.amount || 0)*100" button-text="支付" @submit="pay" />
</div> </div>
</template> </template>
@@ -54,7 +59,7 @@ async function initData() {
await getAggregateConfig(orderNo, CheckoutAggregateEnum.ALI).then(({ data }) => { await getAggregateConfig(orderNo, CheckoutAggregateEnum.ALI).then(({ data }) => {
aggregateInfo.value = data aggregateInfo.value = data
}).catch((res) => { }).catch((res) => {
router.push({ name: 'ErrorResult', query: { msg: res.message } }) router.push({ name: 'ErrorResult', query: { msg: res.message }, replace: true })
}) })
// 判断是否自动拉起支付 // 判断是否自动拉起支付
if (aggregateInfo.value.aggregateConfig.autoLaunch) { if (aggregateInfo.value.aggregateConfig.autoLaunch) {
@@ -81,30 +86,4 @@ function pay() {
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@color: #108ee9;
:deep(.van-key--blue) {
background: @color;
}
.container {
background-color: @color;
width: 100%;
padding: 10px;
border-radius: 10px;
text-align: center;
color: white;
.amount-display {
background-color: white;
color: @color;
border-radius: 20px;
padding: 20px;
margin: 20px 0;
}
.amount-display p {
margin: 5px 0;
}
}
.remark {
color: @color;
}
</style> </style>

View File

@@ -1,19 +1,24 @@
<template> <template>
<div v-if="show"> <div v-if="show">
<div class="container"> <van-overlay :show="loading">
<div style="font-size: 28px;margin-top: 10px;"> <div class="loading-wrapper" @click.stop>
{{ aggregateInfo.config.name || '微信收银台' }} <van-loading size="24px">
支付中...
</van-loading>
</div> </div>
<div class="amount-display"> </van-overlay>
<p style="font-size: 20px"> <van-cell-group inset>
金额 <van-cell title="金额" title-style="font-size: 22px;color: red">
</p> <template #default>
<p style="font-size: 32px;"> <span style="font-size: 22px;color: red">{{ aggregateInfo.order.amount }}</span>
¥ {{ aggregateInfo.order.amount || 0.00 }} </template>
</p> </van-cell>
</div> <van-field label="标题" :model-value="aggregateInfo.order.title" readonly />
</div> <van-field label="订单号" :model-value="aggregateInfo.order.bizOrderNo" readonly />
<van-submit-bar :price="(aggregateInfo.order.amount || 0)*100" button-text="支付" @submit="pay" /> <van-field label="支付号" :model-value="aggregateInfo.order.orderNo" readonly />
<van-field label="描述" rows="2" type="textarea" :model-value="aggregateInfo.order.description" readonly />
</van-cell-group>
<van-submit-bar safe-area-inset-bottom :price="(aggregateInfo.order.amount || 0)*100" button-text="支付" @submit="pay" />
</div> </div>
</template> </template>
@@ -26,9 +31,8 @@ import router from '@/router'
import { import {
AggregateOrderAndConfigResult, aggregatePay, CheckoutAggregatePayParam, AggregateOrderAndConfigResult, aggregatePay, CheckoutAggregatePayParam,
CheckoutAuthCodeParam, CheckoutAuthCodeParam,
CheckoutPayParam,
} from '@/views/daxpay/checkout/CheckoutPay.api' } from '@/views/daxpay/checkout/CheckoutPay.api'
import { auth, checkoutPay, generateAuthUrl, getAggregateConfig } from '@/views/daxpay/checkout/CheckoutPay.api' import { auth, generateAuthUrl, getAggregateConfig } from '@/views/daxpay/checkout/CheckoutPay.api'
import type { WxJsapiSignResult } from '@/views/daxpay/cashier/CashierCode.api' import type { WxJsapiSignResult } from '@/views/daxpay/cashier/CashierCode.api'
@@ -68,7 +72,7 @@ function init() {
const url = res.data const url = res.data
location.replace(url) location.replace(url)
}).catch((res) => { }).catch((res) => {
router.push({ name: 'ErrorResult', query: { msg: res.message } }) router.push({ name: 'ErrorResult', query: { msg: res.message }, replace: true })
}) })
} }
else { else {
@@ -87,14 +91,14 @@ async function initData() {
getAggregateConfig(orderNo, CheckoutAggregateEnum.WECHAT).then(({ data }) => { getAggregateConfig(orderNo, CheckoutAggregateEnum.WECHAT).then(({ data }) => {
aggregateInfo.value = data aggregateInfo.value = data
}).catch((res) => { }).catch((res) => {
router.push({ name: 'ErrorResult', query: { msg: res.message } }) router.push({ name: 'ErrorResult', query: { msg: res.message }, replace: true })
}) })
// 认证获取OpenId // 认证获取OpenId
await auth(authParam.value).then(({ data }) => { await auth(authParam.value).then(({ data }) => {
openId.value = data.openId as string openId.value = data.openId as string
}).catch((res) => { }).catch((res) => {
router.push({ name: 'ErrorResult', query: { msg: res.message } }) router.push({ name: 'ErrorResult', query: { msg: res.message }, replace: true })
}) })
// 判断是否自动拉起支付 // 判断是否自动拉起支付
if (aggregateInfo.value.aggregateConfig.autoLaunch) { if (aggregateInfo.value.aggregateConfig.autoLaunch) {
@@ -144,30 +148,4 @@ function jsapiPay(data: WxJsapiSignResult) {
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@color: #4caf50;
:deep(.van-key--blue) {
background: @color;
}
.container {
background-color: @color;
width: 100%;
padding: 10px;
border-radius: 10px;
text-align: center;
color: white;
.amount-display {
background-color: white;
color: @color;
border-radius: 20px;
padding: 20px;
margin: 20px 0;
}
.amount-display p {
margin: 5px 0;
}
}
.remark {
color: @color;
}
</style> </style>