<!-- 支付结果页面 --> <template> <s-layout title="支付结果" :bgStyle="{ color: '#FFF' }"> <view class="pay-result-box ss-flex-col ss-row-center ss-col-center"> <!-- 信息展示 --> <view class="pay-waiting ss-m-b-30" v-if="payResult === 'waiting'" /> <image class="pay-img ss-m-b-30" v-if="payResult === 'success'" :src="sheep.$url.static('/static/img/shop/order/order_pay_success.gif')" /> <image class="pay-img ss-m-b-30" v-if="['failed', 'closed'].includes(payResult)" :src="sheep.$url.static('/static/img/shop/order/order_paty_fail.gif')" /> <view class="tip-text ss-m-b-30" v-if="payResult === 'success'">支付成功</view> <view class="tip-text ss-m-b-30" v-if="payResult === 'failed'">支付失败</view> <view class="tip-text ss-m-b-30" v-if="payResult === 'closed'">该订单已关闭</view> <view class="tip-text ss-m-b-30" v-if="payResult === 'waiting'">检测支付结果...</view> <view class="pay-total-num ss-flex" v-if="payResult === 'success'"> <view>¥{{ fen2yuan(state.orderInfo.price) }}</view> </view> <!-- 操作区 --> <view class="btn-box ss-flex ss-row-center ss-m-t-50"> <button class="back-btn ss-reset-button" @tap="sheep.$router.go('/pages/index/index')"> 返回首页 </button> <button class="check-btn ss-reset-button" v-if="payResult === 'failed'" @tap=" sheep.$router.redirect('/pages/pay/index', { id: state.id, orderType: state.orderType }) " > 重新支付 </button> <button class="check-btn ss-reset-button" v-if="payResult === 'success'" @tap="onOrder"> 查看订单 </button> <button class="check-btn ss-reset-button" v-if="payResult === 'success' && state.tradeOrder.type === 3" @tap="sheep.$router.redirect('/pages/activity/groupon/order')" > 我的拼团 </button> </view> <!-- #ifdef MP --> <view class="subscribe-box ss-flex ss-m-t-44" v-if="showSubscribeBtn && state.orderType === 'goods'" > <image class="subscribe-img" :src="sheep.$url.static('/static/img/shop/order/cargo.png')" /> <view class="subscribe-title ss-m-r-48 ss-m-l-16">获取实时发货信息与订单状态</view> <view class="subscribe-start" @tap="subscribeMessage">立即订阅</view> </view> <!-- #endif --> </view> </s-layout> </template> <script setup> import { onLoad, onHide, onShow } from '@dcloudio/uni-app'; import { reactive, computed, ref } from 'vue'; import { isEmpty } from 'lodash-es'; import sheep from '@/sheep'; import PayOrderApi from '@/sheep/api/pay/order'; import { fen2yuan } from '@/sheep/hooks/useGoods'; import OrderApi from '@/sheep/api/trade/order'; import { WxaSubscribeTemplate } from '@/sheep/util/const'; const state = reactive({ id: 0, // 支付单号 orderType: 'goods', // 订单类型 result: 'unpaid', // 支付状态 orderInfo: {}, // 支付订单信息 tradeOrder: {}, // 商品订单信息,只有在 orderType 为 goods 才会请求。目的:【我的拼团】按钮的展示 counter: 0, // 获取结果次数 }); // 支付结果 result => payResult const payResult = computed(() => { if (state.result === 'unpaid') { return 'waiting'; } if (state.result === 'paid') { return 'success'; } if (state.result === 'failed') { return 'failed'; } if (state.result === 'closed') { return 'closed'; } }); // 获得订单信息 async function getOrderInfo(id) { state.counter++; // 1. 加载订单信息 const { data, code } = await PayOrderApi.getOrder(id); if (code === 0) { state.orderInfo = data; if (!state.orderInfo || state.orderInfo.status === 30) { // 支付关闭 state.result = 'closed'; return; } if (state.orderInfo.status !== 0) { // 非待支付,可能是已支付,可能是已退款 state.result = 'paid'; // #ifdef MP uni.showModal({ title: '支付结果', showCancel: false, // 不要取消按钮 content: '支付成功', success: () => { // 订阅只能由用户主动触发,只能包一层 showModal 诱导用户点击 autoSubscribeMessage(); }, }); // #endif // 特殊:获得商品订单信息 if (state.orderType === 'goods') { const { data, code } = await OrderApi.getOrder(state.orderInfo.merchantOrderId); if (code === 0) { state.tradeOrder = data; } } return; } } // 2.1 情况三一:未支付,且轮询次数小于三次,则继续轮询 if (state.counter < 3 && state.result === 'unpaid') { setTimeout(() => { getOrderInfo(id); }, 1500); } // 2.2 情况二:超过三次检测才判断为支付失败 if (state.counter >= 3) { state.result = 'failed'; } } function onOrder() { if (state.orderType === 'recharge') { sheep.$router.redirect('/pages/pay/recharge-log'); } else { sheep.$router.redirect('/pages/order/list'); } } // #ifdef MP const showSubscribeBtn = ref(false); // 默认隐藏 const SUBSCRIBE_BTN_STATUS_STORAGE_KEY = 'subscribe_btn_status'; function subscribeMessage() { if (state.orderType !== 'goods') { return; } const event = [WxaSubscribeTemplate.TRADE_ORDER_DELIVERY]; if (state.tradeOrder.type === 3) { event.push(WxaSubscribeTemplate.PROMOTION_COMBINATION_SUCCESS); } sheep.$platform.useProvider('wechat').subscribeMessage(event, () => { // 订阅后记录一下订阅状态 uni.removeStorageSync(SUBSCRIBE_BTN_STATUS_STORAGE_KEY); uni.setStorageSync(SUBSCRIBE_BTN_STATUS_STORAGE_KEY, '已订阅'); // 隐藏订阅按钮 showSubscribeBtn.value = false; }); } async function autoSubscribeMessage() { // 1. 校验是否手动订阅过 const subscribeBtnStatus = uni.getStorageSync(SUBSCRIBE_BTN_STATUS_STORAGE_KEY); if (!subscribeBtnStatus) { showSubscribeBtn.value = true; return; } // 2. 订阅消息 subscribeMessage(); } // #endif onLoad(async (options) => { // 支付订单号 if (options.id) { state.id = options.id; } // 订单类型 if (options.orderType) { state.orderType = options.orderType; } // 支付结果传值过来是失败,则直接显示失败界面 if (options.payState === 'fail') { state.result = 'failed'; } else { // 轮询三次检测订单支付结果 await getOrderInfo(state.id); } }); onShow(() => { if (isEmpty(state.orderInfo)) { return; } getOrderInfo(state.id); }); onHide(() => { state.result = 'unpaid'; state.counter = 0; }); </script> <style lang="scss" scoped> @keyframes rotation { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .score-img { width: 36rpx; height: 36rpx; margin: 0 4rpx; } .pay-result-box { padding: 60rpx 0; .pay-waiting { margin-top: 20rpx; width: 60rpx; height: 60rpx; border: 10rpx solid rgb(233, 231, 231); border-bottom-color: rgb(204, 204, 204); border-radius: 50%; display: inline-block; // -webkit-animation: rotation 1s linear infinite; animation: rotation 1s linear infinite; } .pay-img { width: 130rpx; height: 130rpx; } .tip-text { font-size: 30rpx; font-weight: bold; color: #333333; } .pay-total-num { font-size: 36rpx; font-weight: 500; color: #333333; font-family: OPPOSANS; } .btn-box { width: 100%; .back-btn { width: 190rpx; height: 70rpx; font-size: 28rpx; border: 2rpx solid #dfdfdf; border-radius: 35rpx; font-weight: 400; color: #595959; } .check-btn { width: 190rpx; height: 70rpx; font-size: 28rpx; border: 2rpx solid #dfdfdf; border-radius: 35rpx; font-weight: 400; color: #595959; margin-left: 32rpx; } } .subscribe-box { .subscribe-img { width: 44rpx; height: 44rpx; } .subscribe-title { font-weight: 500; font-size: 32rpx; line-height: 36rpx; color: #434343; } .subscribe-start { color: var(--ui-BG-Main); font-weight: 700; font-size: 32rpx; line-height: 36rpx; } } } </style>