<template> <view v-if="personal.user_id" class="container" :style="appThemeStyle"> <view class="account-panel dis-flex flex-y-center"> <view class="panel-lable"> <text>账户余额</text> </view> <view class="panel-balance flex-box"> <text>¥{{ personal.balance }}</text> </view> </view> <view class="recharge-panel"> <view class="recharge-label"> <text>充值金额</text> </view> <view class="recharge-plan clearfix"> <block v-for="(item, index) in planList" :key="index"> <view class="recharge-plan_item" :class="{ active: selectedPlanId == item.plan_id }" @click="onSelectPlan(item.plan_id)"> <view class="plan_money"> <text>{{ item.money }}</text> </view> <view class="plan_gift" v-if="item.gift_money > 0"> <text>送{{ item.gift_money }}</text> </view> </view> </block> </view> <!-- 手动充值输入框 --> <view class="recharge-input" v-if="setting.is_custom == 1"> <input class="input" type="digit" placeholder="可输入自定义充值金额" v-model="inputValue" @input="onChangeMoney" /> </view> <!-- 支付方式 --> <view class="recharge-label m-top60"> <text>支付方式</text> </view> <view class="payment-method"> <view v-for="(item, index) in methods" :key="index" class="pay-item dis-flex flex-x-between" @click="handleSelectPayType(index)"> <view class="item-left dis-flex flex-y-center"> <view class="item-left_icon" :class="[item.method]"> <text class="iconfont" :class="[PayMethodIconEnum[item.method]]"></text> </view> <view class="item-left_text"> <text>{{ PayMethodEnum[item.method].name }}</text> </view> </view> <view class="item-right col-m" v-if="curPaymentItem && curPaymentItem.method == item.method"> <text class="iconfont icon-check"></text> </view> </view> </view> <!-- 确认按钮 --> <view class="recharge-submit btn-submit"> <form @submit="onSubmit"> <button class="button" formType="submit" :disabled="disabled">立即充值</button> </form> </view> </view> <!-- 充值描述 --> <view class="describe-panel"> <view class="recharge-label"> <text>充值说明</text> </view> <view class="content"> <text space="ensp">{{ setting.describe }}</text> </view> </view> <!-- 支付确认弹窗 --> <!-- #ifdef H5 --> <u-modal v-if="tempUnifyData" v-model="showConfirmModal" title="支付确认" show-cancel-button confirm-text="已完成支付" :confirm-color="appTheme.mainBg" negative-top="100" :asyncClose="true" @confirm="onTradeQuery(tempUnifyData.outTradeNo, tempUnifyData.method)"> <view class="modal-content"> <text>请在{{ PayMethodClientNameEnum[tempUnifyData.method] }}内完成支付,如果您已经支付成功,请点击“已完成支付”按钮</text> </view> </u-modal> <!-- #endif --> </view> </template> <script> import * as RechargeApi from '@/api/recharge' import { PayMethodEnum } from '@/common/enum/payment' import { inArray, urlEncode } from '@/utils/util' import { Alipay, Wechat } from '@/core/payment' // 支付方式对应的图标 const PayMethodIconEnum = { [PayMethodEnum.WECHAT.value]: 'icon-wechat-pay', [PayMethodEnum.ALIPAY.value]: 'icon-alipay', } // 支付方式的终端名称 const PayMethodClientNameEnum = { [PayMethodEnum.WECHAT.value]: '微信', [PayMethodEnum.ALIPAY.value]: '支付宝' } export default { data() { return { // 正在加载 isLoading: true, // 按钮禁用 disabled: false, // 枚举类 PayMethodEnum, PayMethodIconEnum, PayMethodClientNameEnum, // 个人信息 personal: { balance: '0.00' }, // 充值设置 setting: {}, // 充值方案列表 planList: [], // 当前客户端的支付方式列表(后端根据platform判断) methods: [], // 当前选中的套餐ID selectedPlanId: 0, // 自定义金额 inputValue: '', // 当前选中的支付方式 curPaymentItem: null, // 支付确认弹窗 showConfirmModal: false, // #ifdef H5 // 当前微信支付信息 (临时数据, 仅用于H5端) tempUnifyData: { outTradeNo: '', method: '' }, // #endif } }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { // 获取页面数据 this.getPageData() }, methods: { // 选择充值套餐 onSelectPlan(planId) { this.selectedPlanId = planId this.inputValue = '' }, // 金额输入框 onChangeMoney({ detail }) { this.inputValue = detail.value this.selectedPlanId = 0 }, // 选择支付方式 handleSelectPayType(index) { this.curPaymentItem = this.methods[index] }, // 获取页面数据 getPageData() { const app = this app.isLoading = true return new Promise((resolve, reject) => { RechargeApi.center({ client: app.platform }) .then(result => { app.setting = result.data.setting app.personal = result.data.personal app.planList = result.data.planList app.methods = result.data.paymentMethods app.isLoading = false // 默认选中的支付方式 app.handleSelectPayType(0) // #ifdef H5 // 判断当前页面来源于浏览器返回 this.performance() // #endif }) }) }, // 判断当前页面来源于浏览器返回 // #ifdef H5 performance() { this.alipayPerformance() this.wechatPerformance() }, // H5端支付宝支付完成跳转回当前页面时触发 alipayPerformance() { const app = this app.tempUnifyData = Alipay.performance() if (app.tempUnifyData) { app.onTradeQuery(app.tempUnifyData.outTradeNo, app.tempUnifyData.method) } }, // H5端微信支付完成或返回时触发 wechatPerformance() { const app = this app.tempUnifyData = Wechat.performance('recharge') console.log('wechatPerformance', app.tempUnifyData) if (app.tempUnifyData) { app.showConfirmModal = true } }, // #endif // 立即充值 onSubmit(e) { const app = this // 判断是否选择了支付方式 if (!app.curPaymentItem) { app.$toast('您还没有选择支付方式') return } // 按钮禁用 if (app.disabled) return app.disabled = true // 提交到后端 RechargeApi.submit({ planId: app.selectedPlanId, customMoney: app.inputValue ? app.inputValue : '', method: app.curPaymentItem.method, client: app.platform, extra: app.getExtraAsUnify(app.curPaymentItem.method) }) .then(result => app.onSubmitCallback(result)) .finally(err => { setTimeout(() => app.disabled = false, 10) }) }, // 获取第三方支付的扩展参数 getExtraAsUnify(method) { if (method === PayMethodEnum.ALIPAY.value) { return Alipay.extraAsUnify() } if (method === PayMethodEnum.WECHAT.value) { return Wechat.extraAsUnify() } return {} }, // 订单提交成功后回调 onSubmitCallback(result) { const app = this const method = app.curPaymentItem.method const paymentData = result.data.payment // 余额支付 if (method === PayMethodEnum.BALANCE.value) { app.onShowSuccess(result) } // 发起支付宝支付 if (method === PayMethodEnum.ALIPAY.value) { console.log('paymentData', paymentData) Alipay.payment(paymentData) .then(res => app.onPaySuccess(res)) .catch(err => app.onPayFail(err)) } // 发起微信支付 if (method === PayMethodEnum.WECHAT.value) { console.log('paymentData', paymentData) Wechat.payment({ orderKey: 'recharge', ...paymentData }) .then(res => app.onPaySuccess(res)) .catch(err => app.onPayFail(err)) } }, // 订单支付成功的回调方法 // 这里只是前端支付api返回结果success,实际订单是否支付成功 以后端的查单和异步通知为准 onPaySuccess({ res, option: { isRequireQuery, outTradeNo, method } }) { const app = this // 判断是否需要主动查单 // isRequireQuery为true代表需要主动查单 if (isRequireQuery) { app.onTradeQuery(outTradeNo, method) return true } this.onShowSuccess(res) }, // 显示支付成功信息并页面跳转 onShowSuccess({ message }) { this.$toast(message || '订单支付成功') this.onSuccessNav() }, // 订单支付失败 onPayFail(err) { console.log('onPayFail', err) const errMsg = err.message || '订单未支付' this.$error(errMsg) }, // 已完成支付按钮事件: 请求后端查单 onTradeQuery(outTradeNo, method) { const app = this // 交易查询 // 查询第三方支付订单是否付款成功 RechargeApi.tradeQuery({ outTradeNo, method, client: app.platform }) .then(result => result.data.isPay ? app.onShowSuccess(result) : app.onPayFail(result)) .finally(() => app.showConfirmModal = false) }, // 支付成功后的跳转 onSuccessNav() { const pages = getCurrentPages() const lastPage = pages.length < 2 ? null : pages[pages.length - 2] const backRoutes = ['pages/wallet/index'] if (lastPage && inArray(lastPage.route, backRoutes)) { setTimeout(() => uni.navigateBack(), 1000) } else { setTimeout(() => { this.$navTo('pages/wallet/index', {}, 'redirectTo') }, 1200) } }, } } </script> <style lang="scss" scoped> page, .container { background: #fff; } .container { padding-bottom: 70rpx; } .m-top60 { margin-top: 60rpx; } // 账户面板 .account-panel { width: 650rpx; height: 180rpx; margin: 50rpx auto; padding: 0 60rpx; box-sizing: border-box; border-radius: 12rpx; color: #fff; background: linear-gradient(-125deg, #a46bff, #786cff); box-shadow: 0 5px 22px 0 rgba(0, 0, 0, 0.26); } .panel-lable { font-size: 32rpx; } .recharge-label { color: rgb(51, 51, 51); font-size: 30rpx; margin-bottom: 25rpx; } .panel-balance { text-align: right; font-size: 46rpx; } .recharge-panel { margin-top: 60rpx; padding: 0 60rpx; } // 充值套餐 .recharge-plan { margin-bottom: -20rpx; .recharge-plan_item { width: 192rpx; padding: 15rpx 0; float: left; text-align: center; color: #888; border: 1rpx solid rgb(228, 228, 228); border-radius: 10rpx; margin: 0 20rpx 20rpx 0; &:nth-child(3n + 0) { margin-right: 0; } &.active { color: #786cff; border: 1rpx solid #786cff; .plan_money { color: #786cff; } } } } .plan_money { font-size: 32rpx; color: rgb(82, 82, 82); } .plan_gift { font-size: 25rpx; } .recharge-input { margin-top: 40rpx; .input { display: block; border: 1rpx solid rgb(228, 228, 228); border-radius: 10rpx; padding: 20rpx 26rpx; font-size: 28rpx; } } // 立即充值 .recharge-submit { margin-top: 70rpx; } .btn-submit { .button { font-size: 30rpx; background: #786cff; border: none; color: white; border-radius: 50rpx; padding: 0 120rpx; line-height: 3; } .button[disabled] { background: #a098ff; border-color: #a098ff; color: white; } } // 充值说明 .describe-panel { margin-top: 50rpx; padding: 0 60rpx; .content { font-size: 26rpx; line-height: 1.6; color: #888; } } // 支付方式 .payment-method { .pay-item { padding: 14rpx 0; font-size: 26rpx; .item-left_icon { margin-right: 20rpx; font-size: 44rpx; &.wechat { color: #00c800; } &.alipay { color: #009fe8; } } .item-left_text { font-size: 30rpx; } .item-right { font-size: 30rpx; } .user-balance { margin-left: 20rpx; font-size: 26rpx; } } } // 支付确认弹窗 .modal-content { padding: 40rpx 48rpx; font-size: 30rpx; line-height: 50rpx; text-align: left; color: #606266; // height: 620rpx; box-sizing: border-box; } </style>