feat(payment): 集成PingPong支付SDK并实现支付功能
- 添加PingPong支付SDK动态加载逻辑 - 实现支付组件与SDK的初始化配置 - 配置支付容器自适应不同屏幕尺寸 - 添加支付token校验和错误提示 - 集成Element Plus消息组件显示支付状态 - 配置SDK基础样式和按钮样式参数 - 添加支付页面路由和基本布局结构 - 实现支付结果页面跳转逻辑 - 添加订单状态管理和响应码常量定义 - 集成工具函数支持金额格式化和日期处理 - 配置开发环境变量支持沙箱模式切换 - 添加防抖节流等常用工具函数实现 - 实现订单号生成和状态文本映射逻辑 - 添加表单验证函数支持邮箱和手机校验
This commit is contained in:
139
src/views/Checkout.vue
Normal file
139
src/views/Checkout.vue
Normal file
@@ -0,0 +1,139 @@
|
||||
<template>
|
||||
<div class="checkout">
|
||||
<el-card>
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>PingPong支付收银台</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div id="ufo-container" class="checkout-container"></div>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onMounted, onUnmounted } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import config from '../config'
|
||||
|
||||
const route = useRoute()
|
||||
const token = route.query.token
|
||||
|
||||
onMounted(() => {
|
||||
if (!token) {
|
||||
ElMessage.error('缺少支付token,请重新创建订单')
|
||||
return
|
||||
}
|
||||
|
||||
// 动态加载PingPong SDK
|
||||
loadPingPongSDK()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
// 清理资源
|
||||
})
|
||||
|
||||
const loadPingPongSDK = () => {
|
||||
// 检查SDK是否已加载
|
||||
if (window.ppPay) {
|
||||
initPingPongPay()
|
||||
return
|
||||
}
|
||||
|
||||
// 加载SDK
|
||||
const script = document.createElement('script')
|
||||
script.src = config.pingpongSdkUrl
|
||||
script.onload = () => {
|
||||
initPingPongPay()
|
||||
}
|
||||
script.onerror = () => {
|
||||
ElMessage.error('加载支付SDK失败,请刷新页面重试')
|
||||
}
|
||||
document.head.appendChild(script)
|
||||
}
|
||||
|
||||
const initPingPongPay = () => {
|
||||
try {
|
||||
const client = new window.ppPay({
|
||||
lang: 'zh',
|
||||
root: '#ufo-container',
|
||||
manul: false,
|
||||
located: true,
|
||||
showPrice: true,
|
||||
bill: true,
|
||||
mode: config.pingpongMode, // 根据环境配置:sandbox/test/build
|
||||
menu: false,
|
||||
base: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
fontSize: '14px',
|
||||
backgroundColor: '#fff',
|
||||
showHeader: true,
|
||||
showHeaderLabel: true,
|
||||
headerLabelFont: '支付',
|
||||
headerColor: '#333333',
|
||||
headerSize: '16px',
|
||||
headerBackgroundColor: '#fff',
|
||||
headerPadding: '20px',
|
||||
btnSize: '100%',
|
||||
btnColor: '#fff',
|
||||
btnFontSize: '14px',
|
||||
btnPaddingX: '20px',
|
||||
btnPaddingY: '10px',
|
||||
btnBackgroundColor: '#1fa0e8',
|
||||
btnBorderRadius: '4px',
|
||||
btnMarginTop: '20px'
|
||||
}
|
||||
})
|
||||
|
||||
const sdkConfig = {
|
||||
token: token
|
||||
}
|
||||
|
||||
client.createPayment(sdkConfig)
|
||||
|
||||
// 调整容器大小
|
||||
adjustContainerSize()
|
||||
window.addEventListener('resize', adjustContainerSize)
|
||||
} catch (error) {
|
||||
console.error('初始化支付失败:', error)
|
||||
ElMessage.error('初始化支付失败,请刷新页面重试')
|
||||
}
|
||||
}
|
||||
|
||||
const adjustContainerSize = () => {
|
||||
const container = document.getElementById('ufo-container')
|
||||
if (!container) return
|
||||
|
||||
const winWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth
|
||||
|
||||
if (winWidth >= 500) {
|
||||
const clientW = Math.floor(winWidth / 3)
|
||||
container.style.width = (clientW >= 500 ? clientW : 500) + 'px'
|
||||
container.style.margin = '0 auto'
|
||||
} else {
|
||||
container.style.width = winWidth + 'px'
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.checkout {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.checkout-container {
|
||||
min-height: 600px;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user