feat(payment): tighten gateways and implement Epay
Keep only balance, Alipay, WeChat, PayPal, Stripe, Epay, and card-pass channels; remove placeholder aggregators. Add dual-channel Epay gateway with MD5 notify/return, register cashier methods, and gate card-pass redeem behind the payment channel switch. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,10 +2,11 @@
|
||||
<PaymentSectionPage
|
||||
section="gateway"
|
||||
title="收款接口"
|
||||
desc="管理支付网关、查看连接状态、配置回调口令。"
|
||||
note="当前支持人工确认与测试联调;回调校验口令在接入真实网关时直接复用。"
|
||||
desc="管理余额、支付宝、微信、PayPal、Stripe、易支付与卡密兑换通道。"
|
||||
note="以渠道开关与凭据是否齐全为准;异步回调由各网关验签。卡密为兑换入口,不进入收银台。"
|
||||
:links="[
|
||||
{ label: '余额充值', path: '/payment/recharge' },
|
||||
{ label: '充值卡', path: '/payment/card-pass' },
|
||||
{ label: '付费内容', path: '/payment/paid' },
|
||||
]"
|
||||
>
|
||||
@@ -16,7 +17,7 @@
|
||||
<n-grid-item v-for="gw in gateways" :key="gw.id">
|
||||
<div class="aksrt-gateway__card">
|
||||
<div class="aksrt-gateway__icon" :class="gw.configured ? 'aksrt-gateway__icon--active' : ''">
|
||||
<i :class="gw.id === 'balance' ? 'fas fa-wallet' : 'fas fa-credit-card'"></i>
|
||||
<i :class="iconFor(gw.id)"></i>
|
||||
</div>
|
||||
<div>
|
||||
<strong>{{ gw.name }}</strong>
|
||||
@@ -31,39 +32,8 @@
|
||||
<n-empty v-if="!loading && gateways.length === 0" description="暂无已注册的支付网关" />
|
||||
</n-card>
|
||||
|
||||
<n-card class="aksrt-section-card" title="运行摘要">
|
||||
<n-grid :cols="4" :x-gap="12" :y-gap="12">
|
||||
<n-grid-item>
|
||||
<div class="aksrt-gateway__stat">
|
||||
<strong>{{ modeLabel }}</strong>
|
||||
<p>当前模式</p>
|
||||
</div>
|
||||
</n-grid-item>
|
||||
<n-grid-item>
|
||||
<div class="aksrt-gateway__stat">
|
||||
<strong :class="overview.gateway?.test_enabled ? 'aksrt-text-warning' : ''">
|
||||
{{ overview.gateway?.test_enabled ? '启用' : '关闭' }}
|
||||
</strong>
|
||||
<p>测试网关</p>
|
||||
</div>
|
||||
</n-grid-item>
|
||||
<n-grid-item>
|
||||
<div class="aksrt-gateway__stat">
|
||||
<strong :class="overview.gateway?.manual_review ? 'aksrt-text-info' : ''">
|
||||
{{ overview.gateway?.manual_review ? '启用' : '关闭' }}
|
||||
</strong>
|
||||
<p>人工复核</p>
|
||||
</div>
|
||||
</n-grid-item>
|
||||
<n-grid-item>
|
||||
<div class="aksrt-gateway__stat">
|
||||
<n-tag :type="overview.gateway?.callback_secret ? 'success' : 'warning'" size="small" round>
|
||||
{{ overview.gateway?.callback_secret ? '已设置' : '未设置' }}
|
||||
</n-tag>
|
||||
<p>回调口令</p>
|
||||
</div>
|
||||
</n-grid-item>
|
||||
</n-grid>
|
||||
<n-card v-if="overview.help_text" class="aksrt-section-card" title="运行说明">
|
||||
<p class="aksrt-gateway__help">{{ overview.help_text }}</p>
|
||||
</n-card>
|
||||
</n-spin>
|
||||
</template>
|
||||
@@ -71,7 +41,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useMessage } from 'naive-ui'
|
||||
import PaymentSectionPage from '@/pages/payment/PaymentSectionPage.vue'
|
||||
import api from '@/api'
|
||||
@@ -81,12 +51,14 @@ const gateways = ref([])
|
||||
const overview = ref({})
|
||||
const loading = ref(false)
|
||||
|
||||
const modeLabel = computed(() => {
|
||||
const mode = overview.value.gateway?.mode
|
||||
if (mode === 'test_gateway') return '测试网关'
|
||||
if (mode === 'adapter_ready') return '适配器就绪'
|
||||
return '人工确认'
|
||||
})
|
||||
function iconFor(id) {
|
||||
if (id === 'balance') return 'fas fa-wallet'
|
||||
if (id === 'alipay' || id === 'epay_alipay') return 'fab fa-alipay'
|
||||
if (id === 'wechatpay' || id === 'epay_wxpay') return 'fab fa-weixin'
|
||||
if (id === 'paypal') return 'fab fa-paypal'
|
||||
if (id === 'stripe') return 'fab fa-stripe-s'
|
||||
return 'fas fa-credit-card'
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
loading.value = true
|
||||
@@ -98,7 +70,9 @@ onMounted(async () => {
|
||||
if (gwRes?.data?.gateways) {
|
||||
gateways.value = gwRes.data.gateways
|
||||
}
|
||||
if (ovRes?.data) {
|
||||
if (ovRes?.data?.gateway) {
|
||||
overview.value = ovRes.data.gateway
|
||||
} else if (ovRes?.data) {
|
||||
overview.value = ovRes.data
|
||||
}
|
||||
} catch {
|
||||
@@ -149,31 +123,10 @@ onMounted(async () => {
|
||||
color: var(--color-ink-4, #8a909c);
|
||||
}
|
||||
|
||||
.aksrt-gateway__stat {
|
||||
text-align: center;
|
||||
padding: 16px;
|
||||
border-radius: 8px;
|
||||
background: var(--surface-2, #fafafa);
|
||||
}
|
||||
|
||||
.aksrt-gateway__stat strong {
|
||||
display: block;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: var(--color-ink, #1a1a2e);
|
||||
}
|
||||
|
||||
.aksrt-gateway__stat p {
|
||||
margin: 4px 0 0;
|
||||
font-size: 12px;
|
||||
color: var(--color-ink-4, #8a909c);
|
||||
}
|
||||
|
||||
.aksrt-text-warning {
|
||||
color: var(--color-warning, #f59e0b);
|
||||
}
|
||||
|
||||
.aksrt-text-info {
|
||||
color: var(--color-info, #3b82f6);
|
||||
.aksrt-gateway__help {
|
||||
margin: 0;
|
||||
font-size: 13px;
|
||||
color: var(--color-ink-3, #5c6370);
|
||||
line-height: 1.6;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user