feat: PC 两处支付入口的支付宝统一改为扫码出码(与微信交互一致)
用户选择:PC 不再跳支付宝账单页,改为像微信一样直接出一张二维码。 此前 PC(收银台 + 购标流程)走电脑网站支付(自提交表单 + 跳转), H5 走扫码,两个渠道两种交互。 改动: - tender/pay.vue 与 template-07/BuyDocument.vue 删除自提交表单整套逻辑 (alipayForm 状态、openAlipayForm 的 document.write、弹窗拦截兜底、 模板里的「前往支付宝付款」分支)——两个渠道现在都是 codeUrl 出码, 渲染与轮询完全复用同一套。 - 支付宝提交 payType=alipay(裸值),由后端按默认渠道(当面付扫码)下单。 - 两处文件头注释同步:支付宝默认当面付,与微信 Native 同一交互。 不改的部分: - 后端本就两条路都实现(precreate / page.pay),本次只翻转默认, 网页支付保留为显式 alipay_page / alipay_web 的可选路径—— 扫码签约「当面付」、网页支付签约「电脑网站支付」,是不同的产品签约, 留一条备用便于按实际签约情况切换,不必改代码。 - H5 原本就是扫码(显式 alipay_qr),行为不变。 验证:eslint 0 error;npm run build:dev 通过。
This commit is contained in:
+10
-58
@@ -62,28 +62,12 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 支付宝网页支付:后端返回一段自提交表单,写进新页面即跳转账单 -->
|
||||
<template v-if="alipayForm">
|
||||
<div class="rounded-md bg-blue-50 px-4 py-6 text-sm text-blue-700">
|
||||
已为你打开支付宝收银台。若新页面没有自动打开,请点击下方按钮。
|
||||
</div>
|
||||
<button
|
||||
class="mt-6 w-full rounded-md bg-blue-600 py-3 font-medium text-white hover:bg-blue-700 disabled:opacity-50"
|
||||
:disabled="confirming"
|
||||
@click="openAlipayForm"
|
||||
>
|
||||
{{ confirming ? '确认中...' : '前往支付宝付款' }}
|
||||
</button>
|
||||
<button
|
||||
class="mt-3 w-full rounded-md border border-gray-300 py-3 font-medium text-gray-700 hover:bg-gray-50 disabled:opacity-50"
|
||||
:disabled="confirming"
|
||||
@click="confirmPaid"
|
||||
>
|
||||
{{ confirming ? '确认中...' : '我已完成支付,确认订单' }}
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<template v-else-if="codeUrl">
|
||||
<!--
|
||||
两个渠道都是出码:微信 Native 与支付宝当面付(默认渠道)返回同一形态的 codeUrl,
|
||||
渲染与轮询完全复用。支付宝不跳转账单——当面付需要在开放平台签约「当面付」,
|
||||
与「电脑网站支付」是不同的产品签约(见 ADR 0010)。
|
||||
-->
|
||||
<template v-if="codeUrl">
|
||||
<!-- 过期只是置灰提示,仍留在页面上:万一用户是刚过点就扫的,还能看见自己扫的是哪张码 -->
|
||||
<div :class="payExpired ? 'opacity-30' : ''">
|
||||
<HjcPayQrcode :value="codeUrl" :size="240" :alt="qrAlt" />
|
||||
@@ -96,7 +80,7 @@
|
||||
</div>
|
||||
|
||||
<button
|
||||
v-if="codeUrl && !alipayForm"
|
||||
v-if="codeUrl"
|
||||
class="mt-6 w-full rounded-md bg-blue-600 py-3 font-medium text-white hover:bg-blue-700 disabled:opacity-50"
|
||||
:disabled="confirming"
|
||||
@click="confirmPaid"
|
||||
@@ -104,7 +88,6 @@
|
||||
{{ confirming ? '确认中...' : '我已完成支付,确认订单' }}
|
||||
</button>
|
||||
<button
|
||||
v-if="!alipayForm"
|
||||
class="mt-6 w-full rounded-md py-3 font-medium disabled:opacity-50"
|
||||
:class="codeUrl
|
||||
? 'border border-gray-300 text-gray-700 hover:bg-gray-50'
|
||||
@@ -136,7 +119,8 @@ import { hjcOrderStatusKey } from '~/utils/orderStatus'
|
||||
* 两份实现共享的只有 `HjcPayQrcode` 与 `useHjcPayStatus`(重活已经都在那里了)。
|
||||
*
|
||||
* 本页只服务微信外(ADR 0010):不因 UA 在微信内就跳 hjc-h5。
|
||||
* 支付方式可选**微信扫码**或**支付宝**;支付宝走电脑网站支付(返回自提交表单)。
|
||||
* 支付方式可选**微信扫码**或**支付宝**;两者都是出码(支付宝默认当面付,
|
||||
* 与微信 Native 同一交互),渲染与轮询完全复用。
|
||||
*/
|
||||
const route = useRoute()
|
||||
const { isLoggedIn, handleAuthCode } = useHjcAuth()
|
||||
@@ -162,8 +146,6 @@ const payOptions = [
|
||||
]
|
||||
|
||||
const codeUrl = ref('')
|
||||
/** 支付宝电脑网站支付的自提交表单 */
|
||||
const alipayForm = ref('')
|
||||
const amount = ref(0)
|
||||
const starting = ref(false)
|
||||
const refreshing = ref(false)
|
||||
@@ -240,14 +222,8 @@ async function startPay() {
|
||||
}
|
||||
if (res?.code === 0) {
|
||||
codeUrl.value = res.data?.codeUrl || ''
|
||||
alipayForm.value = res.data?.alipayForm || ''
|
||||
if (res.data?.amount) amount.value = Number(res.data.amount)
|
||||
if (!codeUrl.value && !alipayForm.value) {
|
||||
error.value = '未获取到支付信息,请稍后重试'
|
||||
} else if (alipayForm.value) {
|
||||
// 网页支付:立刻把表单送去新页面,用户不必再点一次
|
||||
openAlipayForm()
|
||||
}
|
||||
if (!codeUrl.value) error.value = '未获取到支付信息,请稍后重试'
|
||||
} else {
|
||||
error.value = payErrorMessage(res)
|
||||
}
|
||||
@@ -261,35 +237,11 @@ async function startPay() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 把支付宝返回的自提交表单写进一个新页面。
|
||||
*
|
||||
* 用 `document.write` 而不是 `v-html`:表单里带一段自动提交的脚本,
|
||||
* 而 `v-html` 插入的脚本标签**不会执行**(HTML 规范如此),表单永远不会自动提交。
|
||||
* 写进新窗口则脚本正常执行,且原收银台页面保留在原标签页继续轮询查单。
|
||||
*
|
||||
* 注意:本注释不要写出脚本标签的字面量——SFC 的 script 块会被它提前闭合。
|
||||
*/
|
||||
function openAlipayForm() {
|
||||
if (!alipayForm.value) return
|
||||
const w = window.open('', '_blank')
|
||||
if (!w) {
|
||||
// 弹窗被拦截:留在本页提示用户点按钮重试(按钮复用它)
|
||||
error.value = '浏览器拦截了新窗口,请允许弹出窗口后点「前往支付宝付款」'
|
||||
return
|
||||
}
|
||||
w.document.open()
|
||||
w.document.write(alipayForm.value)
|
||||
w.document.close()
|
||||
error.value = ''
|
||||
}
|
||||
|
||||
/** 切换支付方式:清掉上一张码再重新发起,避免两种支付信息同时留在页面上 */
|
||||
async function switchPayType(next: 'wechat' | 'alipay') {
|
||||
if (next === payType.value) return
|
||||
payType.value = next
|
||||
codeUrl.value = ''
|
||||
alipayForm.value = ''
|
||||
error.value = ''
|
||||
await startPay()
|
||||
}
|
||||
|
||||
@@ -73,28 +73,12 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 支付宝电脑网站支付:后端返回自提交表单,写进新页面即跳转账单 -->
|
||||
<template v-if="alipayForm">
|
||||
<div class="rounded-md bg-blue-50 px-4 py-6 text-sm text-blue-700">
|
||||
已为你打开支付宝收银台。若新页面没有自动打开,请点击下方按钮。
|
||||
</div>
|
||||
<button
|
||||
class="mt-6 w-full rounded-md bg-blue-600 py-3 font-medium text-white hover:bg-blue-700 disabled:opacity-50"
|
||||
:disabled="confirming"
|
||||
@click="openAlipayForm"
|
||||
>
|
||||
前往支付宝付款
|
||||
</button>
|
||||
<button
|
||||
class="mt-3 w-full rounded-md border border-gray-300 py-3 font-medium text-gray-700 hover:bg-gray-50 disabled:opacity-50"
|
||||
:disabled="confirming"
|
||||
@click="confirmPaid"
|
||||
>
|
||||
{{ confirming ? '确认中...' : '我已完成支付,确认订单' }}
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<template v-else-if="codeUrl">
|
||||
<!--
|
||||
两个渠道都是出码:微信 Native 与支付宝当面付(默认渠道)返回同一形态的 codeUrl,
|
||||
渲染与轮询完全复用。支付宝不跳转账单——当面付需要在开放平台签约「当面付」,
|
||||
与「电脑网站支付」是不同的产品签约(见 ADR 0010)。
|
||||
-->
|
||||
<template v-if="codeUrl">
|
||||
<!-- 过期只是置灰提示,仍留在页面上:万一用户是刚过点就扫的,还能看见自己扫的是哪张码 -->
|
||||
<div :class="payExpired ? 'opacity-30' : ''">
|
||||
<HjcPayQrcode :value="codeUrl" :size="240" :alt="qrAlt" />
|
||||
@@ -107,7 +91,7 @@
|
||||
</div>
|
||||
|
||||
<button
|
||||
v-if="codeUrl && !alipayForm"
|
||||
v-if="codeUrl"
|
||||
class="mt-6 w-full rounded-md bg-blue-600 py-3 text-white font-medium hover:bg-blue-700 disabled:opacity-50"
|
||||
:disabled="confirming"
|
||||
@click="confirmPaid"
|
||||
@@ -115,7 +99,6 @@
|
||||
{{ confirming ? '确认中...' : '我已完成支付,确认订单' }}
|
||||
</button>
|
||||
<button
|
||||
v-if="!alipayForm"
|
||||
class="mt-6 w-full rounded-md py-3 font-medium disabled:opacity-50"
|
||||
:class="codeUrl
|
||||
? 'border border-gray-300 text-gray-700 hover:bg-gray-50'
|
||||
@@ -167,8 +150,6 @@ const payOptions = [
|
||||
{ value: 'wechat' as const, label: '微信支付' },
|
||||
{ value: 'alipay' as const, label: '支付宝' }
|
||||
]
|
||||
/** 支付宝电脑网站支付的自提交表单 */
|
||||
const alipayForm = ref('')
|
||||
|
||||
/** 提示文案里的渠道名(只影响措辞,不影响判定) */
|
||||
const channelLabel = computed(() => (payType.value === 'alipay' ? '支付宝' : '微信'))
|
||||
@@ -200,35 +181,11 @@ function formatMoney(n?: number | string) {
|
||||
return Number(n ?? 0).toFixed(2)
|
||||
}
|
||||
|
||||
/**
|
||||
* 把支付宝返回的自提交表单写进一个新页面。
|
||||
*
|
||||
* 用 `document.write` 而不是 `v-html`:表单里带一段自动提交的脚本,
|
||||
* 而 `v-html` 插入的脚本标签**不会执行**(HTML 规范如此),表单永远不会自动提交。
|
||||
* 写进新窗口则脚本正常执行,且原页面保留在原标签页继续轮询查单。
|
||||
*
|
||||
* 注意:本注释不要写出脚本标签的字面量——SFC 的 script 块会被它提前闭合。
|
||||
*/
|
||||
function openAlipayForm() {
|
||||
if (!alipayForm.value) return
|
||||
const w = window.open('', '_blank')
|
||||
if (!w) {
|
||||
// 弹窗被拦截:留在本页提示用户点按钮重试(按钮复用它)
|
||||
error.value = '浏览器拦截了新窗口,请允许弹出窗口后点「前往支付宝付款」'
|
||||
return
|
||||
}
|
||||
w.document.open()
|
||||
w.document.write(alipayForm.value)
|
||||
w.document.close()
|
||||
error.value = ''
|
||||
}
|
||||
|
||||
/** 切换支付方式:清掉上一张码再重新发起,避免两种支付信息同时留在页面上 */
|
||||
async function switchPayType(next: 'wechat' | 'alipay') {
|
||||
if (next === payType.value) return
|
||||
payType.value = next
|
||||
codeUrl.value = ''
|
||||
alipayForm.value = ''
|
||||
error.value = ''
|
||||
await refreshQr()
|
||||
}
|
||||
@@ -274,8 +231,7 @@ async function submit() {
|
||||
step.value = 'pay'
|
||||
if (payRes?.code === 0) {
|
||||
codeUrl.value = payRes.data?.codeUrl || ''
|
||||
alipayForm.value = payRes.data?.alipayForm || ''
|
||||
if (alipayForm.value) openAlipayForm()
|
||||
if (!codeUrl.value) error.value = '未获取到支付信息,请稍后重试'
|
||||
} else {
|
||||
error.value = payRes?.message || '发起支付失败,请稍后重试'
|
||||
}
|
||||
@@ -340,11 +296,8 @@ async function refreshQr() {
|
||||
return
|
||||
}
|
||||
codeUrl.value = res.data?.codeUrl || ''
|
||||
alipayForm.value = res.data?.alipayForm || ''
|
||||
if (res.data?.amount) totalAmount.value = Number(res.data.amount)
|
||||
if (alipayForm.value) {
|
||||
openAlipayForm()
|
||||
} else if (!codeUrl.value) {
|
||||
if (!codeUrl.value) {
|
||||
error.value = '未获取到支付信息,请稍后重试'
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user