diff --git a/backend/cmd/server/VERSION b/backend/cmd/server/VERSION index e3a9de6b82..fe8bcaa61f 100644 --- a/backend/cmd/server/VERSION +++ b/backend/cmd/server/VERSION @@ -1 +1 @@ -0.1.108.88 +0.1.108.89 diff --git a/frontend/src/components/payment/PaymentQRDialog.vue b/frontend/src/components/payment/PaymentQRDialog.vue new file mode 100644 index 0000000000..8062435100 --- /dev/null +++ b/frontend/src/components/payment/PaymentQRDialog.vue @@ -0,0 +1,249 @@ + + + diff --git a/frontend/src/views/user/PaymentView.vue b/frontend/src/views/user/PaymentView.vue index dbd2325a8f..d7e54c818c 100644 --- a/frontend/src/views/user/PaymentView.vue +++ b/frontend/src/views/user/PaymentView.vue @@ -115,6 +115,16 @@ + + @@ -134,6 +144,7 @@ import AmountInput from '@/components/payment/AmountInput.vue' import PaymentMethodSelector from '@/components/payment/PaymentMethodSelector.vue' import { METHOD_ORDER } from '@/components/payment/providerConfig' import SubscriptionPlanCard from '@/components/payment/SubscriptionPlanCard.vue' +import PaymentQRDialog from '@/components/payment/PaymentQRDialog.vue' import Icon from '@/components/icons/Icon.vue' import type { PaymentMethodOption } from '@/components/payment/PaymentMethodSelector.vue' @@ -153,6 +164,9 @@ const amount = ref(null) const selectedMethod = ref('') const selectedPlan = ref(null) +// Inline QR payment dialog state +const qrDialog = ref({ show: false, orderId: 0, qrCode: '', expiresAt: '', paymentType: '' }) + // All checkout data from single API call const checkout = ref({ methods: {}, global_min: 0, global_max: 0, @@ -273,8 +287,16 @@ async function createOrder(orderAmount: number, orderType: string, planId?: numb if (result.client_secret) { router.push({ path: '/payment/stripe', query: { order_id: String(result.order_id), client_secret: result.client_secret } }) } else if (result.qr_code) { - 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 || '', payment_type: selectedMethod.value } }) + // QR mode: show inline dialog, no page navigation + qrDialog.value = { + show: true, + orderId: result.order_id, + qrCode: result.qr_code, + expiresAt: result.expires_at || '', + paymentType: selectedMethod.value, + } } else if (result.pay_url) { + // Redirect mode: open new window + navigate to polling page 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 || '', payment_type: selectedMethod.value } }) } else {