feat 通道控制台开发

This commit is contained in:
bootx
2024-09-28 22:48:33 +08:00
parent 34bfe028a3
commit 52022dee5a
15 changed files with 228 additions and 107 deletions

8
components.d.ts vendored
View File

@@ -10,16 +10,8 @@ declare module 'vue' {
Loading: typeof import('./src/components/Loading.vue')['default']
Logo: typeof import('./src/components/Logo.vue')['default']
SvgIcon: typeof import('./src/components/SvgIcon.vue')['default']
VanActionBar: typeof import('vant/es')['ActionBar']
VanActionBarButton: typeof import('vant/es')['ActionBarButton']
VanActionSheet: typeof import('vant/es')['ActionSheet']
VanButton: typeof import('vant/es')['Button']
VanCellGroup: typeof import('vant/es')['CellGroup']
VanConfigProvider: typeof import('vant/es')['ConfigProvider']
VanField: typeof import('vant/es')['Field']
VanForm: typeof import('vant/es')['Form']
VanLoading: typeof import('vant/es')['Loading']
VanOverlay: typeof import('vant/es')['Overlay']
VanSwitch: typeof import('vant/es')['Switch']
}
}

View File

@@ -22,18 +22,18 @@ export const BusinessRoute: RouteRecordRaw = {
},
{
path: '/result/success',
name: 'PaySuccessResult',
component: () => import('@/views/result/PaySuccessResult.vue'),
name: 'SuccessResult',
component: () => import('@/views/result/SuccessResult.vue'),
meta: {
title: '支付成功',
},
},
{
path: '/result/error',
name: 'PayErrorResult',
component: () => import('@/views/result/PayErrorResult.vue'),
name: 'ErrorResult',
component: () => import('@/views/result/ErrorResult.vue'),
meta: {
title: '支付失败',
title: '错误页',
},
},
],

View File

@@ -13,7 +13,7 @@ export const DaxPayRoute: RouteRecordRaw = {
{
path: '/alipay/auth/:appId/:channel/:queryCode/:aliAppId',
name: 'AlipayAuth',
component: () => import('@/views/daxpay/channel/alipay/AlipayAuthCallback.vue'),
component: () => import('@/views/daxpay/channel/alipay/auth/AlipayAuth.vue'),
meta: {
title: '支付宝信息获取',
},
@@ -21,10 +21,34 @@ export const DaxPayRoute: RouteRecordRaw = {
{
path: '/wechat/auth/:appId/:channel/:queryCode',
name: 'WechatAuth',
component: () => import('@/views/daxpay/channel/wechat/WechatAuthCallback.vue'),
component: () => import('@/views/daxpay/channel/wechat/auth/WechatAuth.vue'),
meta: {
title: '微信信息获取',
},
},
{
path: '/channel/cashier/:appId/:channel',
name: 'ChannelCashier',
component: () => import('@/views/daxpay/channel/ChannelCashier.vue'),
meta: {
title: '收银台',
},
},
{
path: '/alipay/cashier/:mchNo/:appId',
name: 'AlipayCashier',
component: () => import('@/views/daxpay/channel/alipay/cashier/AlipayCashier.vue'),
meta: {
title: '支付宝收银台',
},
},
{
path: '/wechat/cashier/:mchNo/:appId',
name: 'WechatCashier',
component: () => import('@/views/daxpay/channel/wechat/cashier/WechatCashier.vue'),
meta: {
title: '微信收银台',
},
},
],
}

View File

@@ -1,38 +0,0 @@
import type { RouteRecordRaw } from 'vue-router'
const Layout = () => import('@/layout/index.vue')
/**
* 演示模块路由
*/
export const DemoRoute: RouteRecordRaw = {
path: '/demo',
name: 'demo',
component: Layout,
children: [
{
path: '/aggregate/alipay',
name: 'AliPayAggregate',
component: () => import('@/views/demo/aggregate/AliPayAggregate.vue'),
meta: {
title: '支付宝聚合支付',
},
},
{
path: '/aggregate/wechatPay',
name: 'WechatPayAggregate',
component: () => import('@/views/demo/aggregate/WechatPayAggregate.vue'),
meta: {
title: '微信聚合支付',
},
},
{
path: '/cashier/uniCashier',
name: 'UniCashier',
component: () => import('@/views/demo/cashier/UniCashier.vue'),
meta: {
title: '手机收银台',
},
},
],
}

View File

@@ -7,13 +7,11 @@ import { useRouteStoreWidthOut } from '@/store/modules/route'
// 菜单
import { BusinessRoute } from '@/router/business'
import { DemoRoute } from '@/router/demo'
import { DaxPayRoute } from '@/router/daxpay'
// 普通路由
export const constantRouter: RouteRecordRaw[] = [
DaxPayRoute,
DemoRoute,
ErrorPageRoute,
BusinessRoute,
]
@@ -24,7 +22,7 @@ routeStore.setMenus(routeModuleList)
routeStore.setRouters(constantRouter.concat(routeModuleList))
const router = createRouter({
// 重定向时hash模式可能无法跳转需要使用history模式
// 重定向时hash模式有场景无法跳转需要使用history模式
history: createWebHistory(''),
routes: constantRouter.concat(...routeModuleList),
strict: true,

View File

@@ -13,6 +13,7 @@ export function authAndSet(param: AuthCodeParam) {
})
}
/**
* 通道认证参数
*/

View File

@@ -0,0 +1,18 @@
import { http } from '@/utils/http/axios'
import type { Result } from '#/axios'
/**
* 通道认证参数
*/
export interface CashierAuthCodeParam {
// 标识码
authCode?: string
// 查询Code
queryCode?: string
// 商户号
mchNo?: string
// 应用号
appId?: string
// 收银台类型
cashierType?: string
}

View File

@@ -0,0 +1,58 @@
<template>
<div class="page-container flex flex-col justify-center" v-if="show">
<div class="text-center">
<img src="~@/assets/icons/exception/403.svg" alt="">
</div>
<div class="text-center">
<h1 class="text-base text-gray-500">
请使用支付宝微信等支付程序进行扫码支付
</h1>
</div>
</div>
</template>
<script setup lang="ts">
import { useRoute } from 'vue-router'
import router from '@/router'
import { ref } from "vue";
const route = useRoute()
const { mchNo, appId } = route.params
const { fixed, amount } = route.query
const show = ref(false)
const ua = navigator.userAgent
if (ua.includes('MicroMessenger')) {
router.push({ path: `/wechat/cashier/${mchNo}/${appId}`, query: { fixed, amount }, replace: true })
}
else if (ua.includes('Alipay')) {
router.push({ path: `/alipay/cashier/${mchNo}/${appId}`, query: { fixed, amount }, replace: true })
}
else {
router.push({ name: 'ErrorResult', query: { msg: '请使用支付宝、微信等支付程序进行扫码支付' }, replace: true })
}
</script>
<style scoped lang="less">
.page-container {
width: 100%;
border-radius: 4px;
padding: 50px 0;
height: 100vh;
.text-center {
h1 {
color: #666;
padding: 5vh 0;
font-size: x-large;
}
}
img {
width: 350px;
margin: 0 auto;
}
}
</style>

View File

@@ -0,0 +1,9 @@
<template>
</template>
<script setup lang="ts">
</script>
<style scoped lang="less">
</style>

View File

@@ -1,5 +1,5 @@
<template>
<van-overlay :show="true" v-show="show">
<van-overlay v-show="show" :show="true">
<div class="wrapper" @click.stop>
<van-loading size="24px">
获取中...
@@ -10,10 +10,10 @@
<script setup lang="ts">
import { useRoute } from 'vue-router'
import { ref, onMounted } from 'vue'
import { onMounted, ref } from 'vue'
import { showDialog } from 'vant'
import type { AuthCodeParam } from '@/views/daxpay/channel/ChannelAuth.api'
import { authAndSet } from '@/views/daxpay/channel/ChannelAuth.api'
import { showDialog } from "vant";
const route = useRoute()
const { appId, channel, queryCode } = route.params

View File

@@ -0,0 +1,104 @@
<template>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { useRoute } from 'vue-router'
import type { WxJsapiSignResult } from '@/views/demo/aggregate/Aggregate.api'
import type { CashierAuthCodeParam } from '@/views/daxpay/channel/ChannelCashier.api'
const route = useRoute()
const { mchNo, appId } = route.params
const { code } = route.query
const loading = ref<boolean>(false)
const amount = ref<number>(0.0)
// 认证参数
const authParam = ref<CashierAuthCodeParam>({
mchNo: mchNo as string,
appId: appId as string,
authCode: code as string,
cashierType: 'wechat_pay',
})
onMounted(() => {
init()
})
/**
* 初始化
*/
function init() {
// 如果不是重定向跳转过来, 跳转到到重定向地址
if (!code) {
// 跳转到微信授权地址
const url = ''
location.replace(url)
}
else {
// 获取并设置OpenId
// 发起收银台支付
// 获取jsapi调用方式
doJsapiPay()
}
}
/**
* 微信jsapi方式支付
*/
function wechatPay() {
loading.value = true
const from = {
bizOrderNo: `M${new Date().getTime()}`,
title: '测试H5支付',
amount: amount.value,
channel: ChannelEnum.WECHAT,
method: MethodEnum.JSAPI,
openId: openId.value,
}
simplePayCashier(from)
.then(({ data }) => {
loading.value = false
// 拉起jsapi支付
const json = JSON.parse(data.payBody)
doJsapiPay(json)
})
.catch((err) => {
// 跳转到错误页
router.push({
name: 'ErrorResult',
query: { msg: err.message },
})
})
}
/**
* 拉起Jsapi支付窗口
*/
function doJsapiPay(data: WxJsapiSignResult) {
const form = {
appId: data.appId, // 公众号ID由商户传入
timeStamp: data.timeStamp, // 时间戳自1970年以来的秒数
nonceStr: data.nonceStr, // 随机串
package: data.package, // 预支付ID
signType: data.signType, // 微信签名方式:
paySign: data.paySign, // 微信签名
}
// 使用微信JsSdk拉起支付
WeixinJSBridge.invoke('getBrandWCPayRequest', form, () => {
if (res.err_msg === 'get_brand_wcpay_request:ok') {
// 跳转到成功页面
setTimeout(() => {
WeixinJSBridge.call('closeWindow')
}, 0)
}
})
}
</script>
<style scoped lang="less">
</style>

View File

@@ -1,45 +0,0 @@
<template>
<div class="page-container flex flex-col justify-center">
<div class="text-center">
<img src="~@/assets/icons/exception/403.svg" alt="">
</div>
<div class="text-center">
<h1 class="text-base text-gray-500">
{{ msg }}
</h1>
</div>
</div>
</template>
<script lang="ts" setup>
import { useRouter } from 'vue-router'
import { unref } from 'vue'
const { currentRoute } = useRouter()
const { query } = unref(currentRoute)
// 获取请求路径下的错误信息
const msg = (query.error as string) || '支付出现错误,请稍后重试'
</script>
<style lang="less" scoped>
.page-container {
width: 100%;
border-radius: 4px;
padding: 50px 0;
height: 100vh;
.text-center {
h1 {
color: #666;
padding: 5vh 0;
font-size: x-large;
}
}
img {
width: 350px;
margin: 0 auto;
}
}
</style>

View File

@@ -1,7 +1,7 @@
<template>
<div class="page-container flex flex-col justify-center">
<div class="text-center">
<img src="~@/assets/icons/exception/403.svg" alt="">
<img src="../../assets/icons/exception/403.svg" alt="">
</div>
<div class="text-center">
<h1 class="text-base text-gray-500">
@@ -19,7 +19,7 @@ const { currentRoute } = useRouter()
const { query } = unref(currentRoute)
//
const msg = (query.msg as string) || '支付出现错误,请稍后重试'
const msg = (query.msg as string) || '出现错误,请稍后重试'
</script>
<style lang="less" scoped>

View File

@@ -17,7 +17,7 @@ const { currentRoute } = useRouter()
const { query } = unref(currentRoute)
//
const msg = (query.msg as string) || '支付成功...'
const msg = (query.msg as string) || '操作成功...'
</script>
<style lang="less" scoped>