feat(payment): add complete payment system with multi-provider support
Add a full payment and subscription system supporting EasyPay (Alipay/WeChat), Stripe, and direct Alipay/WeChat Pay providers with multi-instance load balancing.
This commit is contained in:
@@ -201,13 +201,73 @@ const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
path: '/purchase',
|
||||
name: 'PurchaseSubscription',
|
||||
component: () => import('@/views/user/PurchaseSubscriptionView.vue'),
|
||||
component: () => import('@/views/user/PaymentView.vue'),
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
requiresAdmin: false,
|
||||
title: 'Purchase Subscription',
|
||||
titleKey: 'purchase.title',
|
||||
descriptionKey: 'purchase.description'
|
||||
titleKey: 'nav.buySubscription',
|
||||
descriptionKey: 'purchase.description',
|
||||
requiresPayment: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/orders',
|
||||
name: 'OrderList',
|
||||
component: () => import('@/views/user/UserOrdersView.vue'),
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
requiresAdmin: false,
|
||||
title: 'My Orders',
|
||||
titleKey: 'nav.myOrders',
|
||||
requiresPayment: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/payment/qrcode',
|
||||
name: 'PaymentQRCode',
|
||||
component: () => import('@/views/user/PaymentQRCodeView.vue'),
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
requiresAdmin: false,
|
||||
title: 'Payment',
|
||||
titleKey: 'payment.qr.scanToPay',
|
||||
requiresPayment: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/payment/result',
|
||||
name: 'PaymentResult',
|
||||
component: () => import('@/views/user/PaymentResultView.vue'),
|
||||
meta: {
|
||||
requiresAuth: false,
|
||||
requiresAdmin: false,
|
||||
title: 'Payment Result',
|
||||
titleKey: 'payment.result.success',
|
||||
requiresPayment: false
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/payment/stripe',
|
||||
name: 'StripePayment',
|
||||
component: () => import('@/views/user/StripePaymentView.vue'),
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
requiresAdmin: false,
|
||||
title: 'Stripe Payment',
|
||||
titleKey: 'payment.stripePay',
|
||||
requiresPayment: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/payment/stripe-popup',
|
||||
name: 'StripePopup',
|
||||
component: () => import('@/views/user/StripePopupView.vue'),
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
requiresAdmin: false,
|
||||
title: 'Payment',
|
||||
requiresPayment: true
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -384,6 +444,45 @@ const routes: RouteRecordRaw[] = [
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// ==================== Payment Admin Routes ====================
|
||||
{
|
||||
path: '/admin/orders/dashboard',
|
||||
name: 'AdminPaymentDashboard',
|
||||
component: () => import('@/views/admin/orders/AdminPaymentDashboardView.vue'),
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
requiresAdmin: true,
|
||||
title: 'Payment Dashboard',
|
||||
titleKey: 'nav.paymentDashboard',
|
||||
requiresPayment: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/admin/orders',
|
||||
name: 'AdminOrders',
|
||||
component: () => import('@/views/admin/orders/AdminOrdersView.vue'),
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
requiresAdmin: true,
|
||||
title: 'Order Management',
|
||||
titleKey: 'nav.orderManagement',
|
||||
requiresPayment: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/admin/orders/plans',
|
||||
name: 'AdminPaymentPlans',
|
||||
component: () => import('@/views/admin/orders/AdminPaymentPlansView.vue'),
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
requiresAdmin: true,
|
||||
title: 'Subscription Plans',
|
||||
titleKey: 'nav.paymentPlans',
|
||||
requiresPayment: true
|
||||
}
|
||||
},
|
||||
|
||||
// ==================== 404 Not Found ====================
|
||||
{
|
||||
path: '/:pathMatch(.*)*',
|
||||
@@ -500,6 +599,16 @@ router.beforeEach((to, _from, next) => {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// Check payment requirement (internal payment system only)
|
||||
if (to.meta.requiresPayment) {
|
||||
const paymentEnabled = appStore.cachedPublicSettings?.payment_enabled
|
||||
if (!paymentEnabled) {
|
||||
next(authStore.isAdmin ? '/admin/dashboard' : '/dashboard')
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 简易模式下限制访问某些页面
|
||||
if (authStore.isSimpleMode) {
|
||||
const restrictedPaths = [
|
||||
|
||||
16
frontend/src/router/meta.d.ts
vendored
16
frontend/src/router/meta.d.ts
vendored
@@ -42,5 +42,21 @@ declare module 'vue-router' {
|
||||
* @default false
|
||||
*/
|
||||
hideInMenu?: boolean
|
||||
|
||||
/**
|
||||
* Whether this route requires internal payment system to be enabled
|
||||
* @default false
|
||||
*/
|
||||
requiresPayment?: boolean
|
||||
|
||||
/**
|
||||
* i18n key for the page title
|
||||
*/
|
||||
titleKey?: string
|
||||
|
||||
/**
|
||||
* i18n key for the page description
|
||||
*/
|
||||
descriptionKey?: string
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user