| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- <template>
- <view class="pay-page">
- <view class="pay-card" v-if="orderNo">
- <text class="pay-title">确认支付</text>
- <text class="pay-amount">¥{{ fenToYuan(amount) }}</text>
- <text class="pay-order" v-if="orderNo">订单号:{{ orderNo }}</text>
- <view v-if="status === 'paid'" class="paid-box">
- <text class="paid-icon">✓</text>
- <text class="paid-text">支付成功</text>
- <button class="primary-btn" @click="goResult('success')">查看结果</button>
- </view>
- <view v-else>
- <button class="pay-btn" :loading="paying" :disabled="paying" @click="handlePay">立即支付</button>
- <view class="pay-tip">测试环境将模拟支付成功</view>
- </view>
- </view>
- <view v-if="!orderNo && !loading" class="empty-tip">
- <text>订单创建失败</text>
- </view>
- </view>
- </template>
- <script>
- import { createPayOrder, getPayStatus } from '@/utils/api.js'
- import { fenToYuan } from '@/utils/format.js'
- import { guardPage } from '@/utils/guard.js'
- export default {
- data() {
- return {
- enrollmentId: '',
- orderNo: '',
- amount: 0,
- status: '',
- prepayParams: null,
- loading: false,
- paying: false,
- pollTimer: null
- }
- },
- onLoad(options) {
- if (!guardPage()) return
- this.enrollmentId = options && options.enrollmentId ? options.enrollmentId : ''
- if (!this.enrollmentId) {
- uni.showToast({ title: '缺少报名信息', icon: 'none' })
- setTimeout(function() {
- uni.navigateBack({ delta: 1 })
- }, 1500)
- return
- }
- this.initOrder()
- },
- onUnload() {
- if (this.pollTimer) {
- clearInterval(this.pollTimer)
- this.pollTimer = null
- }
- },
- methods: {
- fenToYuan: fenToYuan,
- initOrder() {
- var self = this
- self.loading = true
- createPayOrder({ enrollmentId: self.enrollmentId }).then(function(resp) {
- var data = resp.data || {}
- self.orderNo = data.orderNo || ''
- self.amount = data.amount || 0
- self.status = data.status || ''
- self.prepayParams = data.prepayParams || null
- if (self.status === 'paid') {
- setTimeout(function() {
- self.goResult('success')
- }, 800)
- }
- }).catch(function(err) {
- uni.showToast({ title: (err && err.message) || '创建订单失败', icon: 'none' })
- }).finally(function() {
- self.loading = false
- })
- },
- handlePay() {
- var self = this
- if (this.paying) return
- // test-mode:后端 create 时已直接置 paid,直接查询确认
- var pp = this.prepayParams
- if (pp && pp.timeStamp) {
- // 生产模式:调起微信支付(预留)
- this.paying = true
- uni.requestPayment({
- provider: 'wxpay',
- timeStamp: pp.timeStamp,
- nonceStr: pp.nonceStr,
- package: pp.package,
- signType: pp.signType || 'MD5',
- paySign: pp.paySign,
- success: function() {
- self.startPoll()
- },
- fail: function() {
- self.paying = false
- uni.showToast({ title: '支付已取消', icon: 'none' })
- }
- })
- } else {
- // 测试模式:模拟支付成功
- this.paying = true
- uni.showLoading({ title: '模拟支付中…' })
- setTimeout(function() {
- self.startPoll()
- }, 800)
- }
- },
- startPoll() {
- var self = this
- var max = 6
- var count = 0
- if (this.pollTimer) clearInterval(this.pollTimer)
- this.pollTimer = setInterval(function() {
- count++
- getPayStatus({ orderNo: self.orderNo }).then(function(resp) {
- var data = resp.data || {}
- if (data.status === 'paid') {
- clearInterval(self.pollTimer)
- self.pollTimer = null
- self.paying = false
- uni.hideLoading()
- self.status = 'paid'
- self.goResult('success')
- } else if (count >= max) {
- clearInterval(self.pollTimer)
- self.pollTimer = null
- self.paying = false
- uni.hideLoading()
- uni.showToast({ title: '支付处理中,请稍后查看', icon: 'none' })
- }
- }).catch(function() {
- if (count >= max) {
- clearInterval(self.pollTimer)
- self.pollTimer = null
- self.paying = false
- uni.hideLoading()
- }
- })
- }, 1500)
- },
- goResult(status) {
- uni.redirectTo({
- url: '/pages/pay/result?status=' + status + '&amount=' + this.amount + '&orderNo=' + this.orderNo
- })
- }
- }
- }
- </script>
- <style scoped>
- .pay-page { min-height: 100vh; background: #F5F5F5; padding: 32rpx; }
- .pay-card { background: #FFF; border-radius: 16rpx; padding: 48rpx 32rpx; display: flex; flex-direction: column; align-items: center; }
- .pay-title { font-size: 28rpx; color: #5A4F4B; margin-bottom: 24rpx; }
- .pay-amount { font-size: 64rpx; font-weight: 700; color: #2A2326; margin-bottom: 16rpx; }
- .pay-order { font-size: 24rpx; color: #94877F; margin-bottom: 48rpx; }
- .paid-box { display: flex; flex-direction: column; align-items: center; width: 100%; }
- .paid-icon { width: 96rpx; height: 96rpx; border-radius: 50%; background: #22C55E; color: #FFF; font-size: 56rpx; display: flex; align-items: center; justify-content: center; margin-bottom: 24rpx; }
- .paid-text { font-size: 32rpx; font-weight: 600; color: #2A2326; margin-bottom: 48rpx; }
- .pay-btn { width: 100%; height: 88rpx; line-height: 88rpx; background: #FC7A57; color: #FFF; font-size: 30rpx; font-weight: 600; border-radius: 44rpx; border: none; }
- .pay-btn:active { opacity: 0.85; }
- .pay-tip { font-size: 24rpx; color: #94877F; margin-top: 16rpx; }
- .primary-btn { width: 400rpx; height: 80rpx; line-height: 80rpx; background: #FC7A57; color: #FFF; font-size: 28rpx; font-weight: 600; border-radius: 40rpx; border: none; }
- .primary-btn:active { opacity: 0.85; }
- .empty-tip { font-size: 26rpx; color: #94877F; padding: 64rpx 0; text-align: center; }
- </style>
|