mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-23 01:23:35 +00:00
feat(payment): show order status page after EasyPay redirect payment
- After opening pay_url in new window, navigate to order status page with countdown timer and order polling (reuses QRCode view) - QRCode view now shows "pay in new window" UI when no QR code present - Add verbose logging for webhook signature verification failures
This commit is contained in:
@@ -1 +1 @@
|
||||
0.1.108.77
|
||||
0.1.108.78
|
||||
|
||||
@@ -83,7 +83,7 @@ func (h *PaymentWebhookHandler) handleNotify(c *gin.Context, providerKey string)
|
||||
|
||||
notification, err := provider.VerifyNotification(c.Request.Context(), rawBody, headers)
|
||||
if err != nil {
|
||||
slog.Error("[Payment Webhook] verify failed", "provider", providerKey, "error", err)
|
||||
slog.Error("[Payment Webhook] verify failed", "provider", providerKey, "error", err, "method", c.Request.Method, "rawBody", rawBody)
|
||||
c.String(http.StatusBadRequest, "verify failed")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -5095,6 +5095,9 @@ export default {
|
||||
},
|
||||
qr: {
|
||||
scanToPay: 'Scan to Pay',
|
||||
payInNewWindow: 'Complete Payment in New Window',
|
||||
payInNewWindowHint: 'The payment page has opened in a new window. Please complete the payment there and return to this page.',
|
||||
openPayWindow: 'Reopen Payment Page',
|
||||
expiresIn: 'Expires in',
|
||||
expired: 'Order Expired',
|
||||
waitingPayment: 'Waiting for payment...',
|
||||
|
||||
@@ -5292,6 +5292,9 @@ export default {
|
||||
},
|
||||
qr: {
|
||||
scanToPay: '请扫码支付',
|
||||
payInNewWindow: '请在新窗口中完成支付',
|
||||
payInNewWindowHint: '支付页面已在新窗口打开,请在新窗口中完成支付后返回此页面',
|
||||
openPayWindow: '重新打开支付页面',
|
||||
expiresIn: '剩余支付时间',
|
||||
expired: '订单已过期',
|
||||
waitingPayment: '等待支付...',
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
<template>
|
||||
<AppLayout>
|
||||
<div class="mx-auto flex max-w-md flex-col items-center space-y-6 py-8">
|
||||
<h2 class="text-xl font-semibold text-gray-900 dark:text-white">{{ t('payment.qr.scanToPay') }}</h2>
|
||||
<h2 class="text-xl font-semibold text-gray-900 dark:text-white">
|
||||
{{ qrUrl ? t('payment.qr.scanToPay') : t('payment.qr.payInNewWindow') }}
|
||||
</h2>
|
||||
<div v-if="qrUrl" class="rounded-2xl bg-white p-6 shadow-lg dark:bg-dark-800">
|
||||
<canvas ref="qrCanvas" class="mx-auto"></canvas>
|
||||
</div>
|
||||
<div v-else-if="payUrl && !expired" class="w-full space-y-3 text-center">
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400">{{ t('payment.qr.payInNewWindowHint') }}</p>
|
||||
<a :href="payUrl" target="_blank" rel="noopener noreferrer"
|
||||
class="btn btn-primary inline-flex w-full items-center justify-center gap-2 py-3">
|
||||
{{ t('payment.qr.openPayWindow') }}
|
||||
</a>
|
||||
</div>
|
||||
<div v-if="expired" class="text-center">
|
||||
<p class="text-lg font-medium text-red-500">{{ t('payment.qr.expired') }}</p>
|
||||
<button class="btn btn-primary mt-4" @click="router.push('/purchase')">{{ t('payment.result.backToRecharge') }}</button>
|
||||
@@ -41,6 +50,7 @@ const appStore = useAppStore()
|
||||
|
||||
const qrCanvas = ref<HTMLCanvasElement | null>(null)
|
||||
const qrUrl = ref('')
|
||||
const payUrl = ref('')
|
||||
const orderId = ref(0)
|
||||
const remainingSeconds = ref(0)
|
||||
const expired = ref(false)
|
||||
@@ -114,6 +124,7 @@ watch(qrUrl, () => renderQR())
|
||||
onMounted(() => {
|
||||
orderId.value = Number(route.query.order_id) || 0
|
||||
qrUrl.value = (route.query.qr as string) || ''
|
||||
payUrl.value = (route.query.pay_url as string) || ''
|
||||
|
||||
// Calculate countdown from expiresAt
|
||||
const expiresAtStr = route.query.expires_at as string
|
||||
|
||||
@@ -236,6 +236,7 @@ async function createOrder(orderAmount: number, orderType: string, planId?: numb
|
||||
router.push({ path: '/payment/qrcode', query: { order_id: String(result.order_id), qr: result.qr_code || '', pay_url: result.pay_url || '', expires_at: result.expires_at || '' } })
|
||||
} else if (result.pay_url) {
|
||||
window.open(result.pay_url, '_blank')
|
||||
router.push({ path: '/payment/qrcode', query: { order_id: String(result.order_id), pay_url: result.pay_url, expires_at: result.expires_at || '' } })
|
||||
} else {
|
||||
errorMessage.value = t('payment.result.failed')
|
||||
appStore.showError(errorMessage.value)
|
||||
|
||||
Reference in New Issue
Block a user