<template> <view> <u-modal v-model="payWayPop" :title-style="{ color: '#1E1E1E', fontSize: '34rpx' }" title="选择支付方式" width="600rpx" :show-confirm-button="false" :show-cancel-button="false" :mask-close-able="true" @input="modalClose" > <view class="pay-content"> <view class="pay-list"> <radio-group @change="payRadioChange"> <template v-if="projectFlag !== 'zhenning' && projectFlag !== 'wudang'"> <!-- #ifdef H5 || MP-WEIXIN --> <view class="pay-list-item" v-if="wxEnv"> <view class="pay-list-item-image"> <image class="image" src="/static/img/wechat-icon-new.png" mode="aspectFit" /> <view>微信支付</view> </view> <view class="radioBox"> <radio color="#2DCF8C" value="weixin" :checked="'weixin' === radioCurrent" /> </view> </view> <!-- #endif --> </template> <template v-if="alipayEnv && projectFlag === 'puding'"> <view class="pay-list-item"> <view class="pay-list-item-image"> <image class="image" src="/static/img/alipay-icon-new.png" mode="aspectFit" /> <view>支付宝支付<text>随机立减最高10元</text></view> </view> <view class="radioBox"> <radio color="#2DCF8C" value="juhe" :checked="'juhe' === radioCurrent" /> </view> </view> </template> <view class="pay-list-item"> <view class="pay-list-item-image"> <image class="image" src="/static/img/gy-icon-new.png" mode="aspectFit" /> <view>贵州银行</view> </view> <view class="radioBox"> <radio color="#2DCF8C" value="gzyh" :checked="'gzyh' === radioCurrent" /> </view> </view> <template v-if="projectFlag === 'zhenning'"> <view class="pay-list-item"> <view class="pay-list-item-image"> <image class="image" src="/static/img/wechat-icon-new.png" mode="aspectFit" /> <view>微信/支付宝</view> </view> <view class="radioBox"> <radio color="#2DCF8C" value="weixinzn" :checked="'weixinzn' === radioCurrent" /> </view> </view> </template> <template v-if="projectFlag !== 'zhenning'"> <view class="pay-list-item"> <view class="pay-list-item-image"> <image class="image" src="/static/img/juhe-icon-new.png" mode="aspectFit" /> <view>聚合支付</view> </view> <view class="radioBox"> <radio color="#2DCF8C" value="juhe" :checked="'juhe' === radioCurrent" /> </view> </view> </template> </radio-group> </view> <view class="pay-coupon" v-if="radioCurrent === 'weixin' && isShowCoupon"> <u-cell-group :border="false"> <u-cell-item icon="" title="优惠券" :value="couponPopup.currentCoupon.couponName || (couponPopup.couponList.length ? '暂未选择优惠券' : '无可用优惠券')" :border-bottom="false" @click="chooseCoupon" ></u-cell-item> </u-cell-group> </view> <view class="pay-money"> <text class="discount-money" v-if="couponPopup.currentCoupon.couponContent && radioCurrent === 'weixin'" >¥ {{ getDifference(orderMoney, couponPopup.currentCoupon.couponContent).toFixed(2) }}</text > <text class="original-money" :class="couponPopup.currentCoupon.couponContent && radioCurrent === 'weixin' && 'original-discount-money'" >¥ {{ orderMoney }}</text > </view> <view class="pay-btn"> <u-button type="primary" shape="circle" :disabled="!radioCurrent" @tap="$u.debounce(immediatePayment, 1500, true)">立即支付</u-button> </view> </view> </u-modal> <!-- 选择优惠券弹框 --> <u-popup v-model="couponPopup.show" mode="top" length="100%"> <view class="coupon-popup"> <u-navbar back-text="" title="我的优惠券" :background="couponPopup.background" title-color="#fff" back-icon-color="#fff" :custom-back="customBack" /> <view class="coupon-popup-list"> <template v-if="couponPopup.couponList.length"> <radio-group @change="couponRadioChange"> <view class="coupon-popup-list-item" v-for="(item, index) in couponPopup.couponList" :key="index"> <view class="coupon-popup-list-item-top"> <view class="coupon-popup-list-item-top-left"> <view class="cplitl-left"> <view> <text>¥</text> <text>{{ item.couponContent }}</text> </view> <view class="cplitl-left-bottom">{{ Number(item.threshold) > 0 ? `停车时长满${item.threshold}分钟` : '无门槛' }}</view> </view> <view class="cplitl-right"> <view>{{ item.couponName }}</view> <view>有限期:剩余{{ calcValidity(item.startTime, item.endTime) }}</view> </view> </view> <view class="coupon-popup-list-item-top-right"> <radio color="#FF6D6D" :value="item.id" :checked="item.id === couponPopup.radioCurrent" @click="couponItemClick(item)" /> </view> </view> <view class="coupon-popup-list-item-bottom"> 适用停车点: <template v-if="item.parkList"> <template v-if="item.parkList.length > 1"> 适用多个停车点 </template> <template v-else> 仅限{{ item.parkList.map((item) => item.parkName).join('、') }} </template> <template v-if="item.parkList && item.parkList.length > 1"> <view class="cplib-point"> <u-read-more text-indent="0" show-height="0" :toggle="true" :shadow-style="{ backgroundImage: 'none' }" fontSize="20rpx" close-text="展开所有停车点" > <view class="cplib-point-content">{{ item.parkList.map((item) => item.parkName).join('、') }}</view> </u-read-more> </view> </template> </template> </view> </view> </radio-group> </template> <template v-else> <u-empty text="没有适合的优惠券" mode="coupon" margin-top="300"></u-empty> </template> </view> <view class="coupon-popup-btn"> <u-button type="primary" shape="circle" @click="confimCoupon">确 定</u-button> </view> </view> </u-popup> <u-toast ref="uToast" /> </view> </template> <script> import { getEnvIsWx, getEnvIsAlipay } from '@/utils/judgEnvironment.js'; import $wxPay from '@/utils/wxPay.js'; export default { props: { // 订单数组 curOrderList: { type: Array, default: null }, // 设备编号 deviceNo: { type: String, default: null }, // 地磁支付需要字段 payeeId: { type: String, default: undefined }, // 地磁支付需要字段 payeeName: { type: String, default: undefined }, // 扫码支付需要字段 sanPay: { type: Boolean, default: false }, // 追缴类型 pursueType: { type: String, default: undefined }, // 车牌号 vehicleNo: { type: String, default: undefined }, // 跳转页面 jumpUrl: { type: String, default: null }, // 出口扫码 接口不一样 exportFlag: { type: Boolean, default: false }, // 区分包月支付 isMonthPay: { type: Boolean, default: false }, // 包月id monthId: { type: String, default: null }, // 室内扫码 isIndoor: { type: Boolean, default: false } }, data() { return { // 支付弹框显示 payWayPop: false, // 是否微信环境 wxEnv: true, // 支付宝环境 alipayEnv: true, // 支付方式选择 radioCurrent: '', // 订单金额 orderMoney: '', // 显示优惠券选项 isShowCoupon: false, // 是否取消优惠券标识 isCancelCoupon: false, // 选择优惠券弹框 couponPopup: { // 弹框标识 show: false, // 优惠券列表 couponList: [], // 优惠券选中项value radioCurrent: '', // navbar背景 background: { backgroundColor: '#008CFF' }, // 优惠券选中项 currentCoupon: {} } }; }, methods: { /** * 打开弹框触发 * @date 2023-02-17 * @param {any} details * @param {any} numType single 单笔订单 multiple 多比订单 用于区分多笔订单不能使用优惠券 * @param {any} orderType road 路段订单 parking 停车场订单 用于区分路段订单不使用优惠券 * @returns {any} */ openPopup(details, numType = 'single', orderType = 'road') { // 获取环境信息 this.wxEnv = getEnvIsWx(); // 判断支付宝环境 this.alipayEnv = getEnvIsAlipay(); if (this.projectFlag === 'zhenning') { this.radioCurrent = 'weixinzn'; } else if (this.wxEnv) { this.radioCurrent = 'weixin'; } else { this.radioCurrent = 'juhe'; } // 打开弹出层 this.payWayPop = true; // 计算订单金额 this.orderMoney = details.payAmount.toFixed(2); // 如果是单个停车订单,且是路边停车,且不是月卡支付,则显示优惠券 if (numType === 'single' && orderType === 'parking' && !this.isMonthPay && this.wxEnv) { this.isShowCoupon = true; this.isCancelCoupon = true; this.getCouponList(details.id); } }, /** * 获取优惠券列表 * @date 2023-02-17 * @param {any} orderId * @returns {any} */ getCouponList(orderId) { this.$u.api.getCouponByOrderIdApi({ orderId }).then((res) => { this.couponPopup.couponList = res?.data ?? []; }); }, /** * 选中支付类型 * @date 2023-02-17 * @param {any} {detail} * @returns {any} */ payRadioChange({ detail }) { this.radioCurrent = detail.value; }, /** * 选中优惠券 * @date 2023-02-17 * @returns {any} */ chooseCoupon() { this.couponPopup.show = true; }, /** * 贵阳银行支付 * @param {Array} orderList 需要支付的订单号组成的数组 * @param {String} deviceNo 设备编号(只有车位锁部分有) * */ async gyBankPay() { const params = { orderList: this.curOrderList, deviceNo: this.deviceNo, jumpUrl: this.jumpUrl, payeeId: this.payeeId, payeeName: this.payeeName, pursueType: this.pursueType, vehicleNo: this.vehicleNo, sanPay: this.sanPay }; const apiCall = this.exportFlag ? this.$u.api.quickPayExportApi : this.$u.api.payGzbank; try { const res = await apiCall({ ...params }); if (res.data.needPay) { location.href = res.data.url; } else { this.showToast('无需支付', 'info'); setTimeout(() => { location.reload(); }, 1000); } } catch (err) { // this.showToast(err.msg, 'error'); } }, /** * @description: 贵阳银行包月支付 * @return {*} */ async gyBankMonthPay() { try { const res = await this.$u.api.monthPay({ monthId: this.monthId, jumpUrl: this.jumpUrl }); if (res.code === 200) { location.href = res?.data?.url; } } catch (err) { this.showToast('无法调起支付', 'error'); } }, /** * @description: 显示报错信息 * @param {*} title * @param {*} type * @return {*} */ showToast(title, type = 'error') { this.$refs.uToast.show({ title, type }); }, /** * 聚合支付 * */ juhePay() { this.getWXPayByJava(this.curOrderList, this.deviceNo); }, /** * @description: 聚合包月支付 * @return {*} */ async juheMonthPay() { const params = { monthId: this.monthId, jumpUrl: this.jumpUrl }; try { const res = await this.$u.api.monthlyWxPay({ ...params }); if (res.code === 200) { ocalStorage.setItem('jumpUrl', this.jumpUrl); location.href = res.data.qrCodeUrl; } } catch (err) { // this.showToast(`无法调起${this.alipayEnv ? '支付宝' : this.wxEnv ? '微信' : '聚合'}支付!`, type: 'error'); } }, /** * 微信支付处理参数 */ wechatPay() { const params = { orderList: this.curOrderList, openid: this.vuex_wxinfo.openId, deviceNo: this.deviceNo || undefined, payeeId: this.payeeId || undefined, payeeName: this.payeeName || undefined, vehicleNo: this.vehicleNo, sanPay: this.sanPay }; if (this.couponPopup.radioCurrent) { params.couponMemberId = this.couponPopup.radioCurrent; } this.handleWxPay.call(this, params); }, /** * @description: 微信支付 * @param {*} params * @return {*} */ handleWxPay(params) { const api = this.exportFlag ? this.$u.api.parkingWechatPayApi : this.$u.api.wechatPayApi; api(params).then((res) => { if (res.code !== 200) { return; } if (!res.data.needPay) { this.showToast('无需支付', 'info'); setTimeout(() => { uni.hideLoading(); location.reload(); }, 1000); return; } $wxPay.weixinPay(res.data.wx).then((r) => { const messageMap = { 0: '成功', 1: '已取消支付', 2: '支付失败,请检查!' }; switch (Number(r.code)) { case 0: // 成功 //#ifdef H5 location.reload(); //#endif break; case 1: // 取消 if (this.isCancelCoupon) { this.cancelCoupon(messageMap[r.code]); } else { this.showToast(messageMap[r.code], 'info'); } break; case 2: // 支付失败 this.showToast(messageMap[r.code], 'error'); break; } }); }); }, /** * @description: 取消优惠券 * @param {*} msg * @return {*} */ async cancelCoupon(msg) { try { const { code } = await this.$u.api.updateCouponStatusApi({ orderList: this.curOrderList }); if (code === 200) { this.showToast(msg, 'info'); location.reload(); } } catch (error) {} }, /** * @description: 微信包月支付 * @return {*} */ wechatMonthPay() { this.$u.api.wechatMonthlyPayapi({ monthId: this.monthId, openid: this.vuex_wxinfo.openId }).then((response) => { if (response.code === 200) { $wxPay.weixinPay(response.data.wx).then((res) => { this.handleMonthlyPay.call(this, res); }); } }); }, /** * @description: 微信包月支付响应处理 * @param {*} response * @return {*} */ handleMonthlyPay(response) { const messageMap = { 0: { title: '成功', jumpUrl: this.jumpUrl }, 1: { title: '已取消支付' }, 2: { title: '支付失败,请检查!', type: 'error' } }; const message = messageMap[Number(response.code)]; this.showToast(message.title, message.type || 'info'); if (message.jumpUrl) { location.href = message.jumpUrl; } }, /** * 直接通过后台获取贵阳银行微信支付地址 * @param {Array} list 需要支付的订单组合数组 * @param {Number} deviceNo 设备编号(在停车锁部分需要) * */ async getWXPayByJava(orderList, deviceNo) { try { let params = { orderList, openid: this.vuex_wxinfo.openId, jumpUrl: this.jumpUrl, deviceNo: deviceNo ? deviceNo : null, payeeId: this.payeeId, payeeName: this.payeeName, pursueType: this.pursueType, vehicleNo: this.vehicleNo, sanPay: this.sanPay }; const api = this.exportFlag ? 'polyPayExportApi' : 'ordinaryWxPay'; // 优化代码 const res = await this.$u.api[api](params); if (res.code === 200) { if (res.data.needPay) { localStorage.setItem('jumpUrl', this.jumpUrl); location.href = res.data.qrCodeUrl; } else { this.showToast('无需支付', 'info'); setTimeout(() => { location.href = this.jumpUrl; }, 1000); } } else { uni.hideLoading(); } } catch (err) { // this.showToast(`无法调起${this.alipayEnv ? '支付宝' : this.wxEnv ? '微信' : '聚合'}支付!`, 'error'); } }, /** * @description: 镇宁微信支付 * @param {*} orderList * @param {*} deviceNo * @return {*} */ async znWechatPay() { try { const params = { orderList: this.curOrderList, openid: '', jumpUrl: this.jumpUrl, deviceNo: this.deviceNo ? this.deviceNo : null, payeeId: this.payeeId, payeeName: this.payeeName, pursueType: this.pursueType }; const res = await this.$u.api.ordinaryWxPay(params); if (res.code === 200) { const { needPay, qrCodeUrl } = res.data; if (needPay) { localStorage.setItem('jumpUrl', this.jumpUrl); location.href = qrCodeUrl; } else { this.showToast('无需支付', 'info'); setTimeout(() => { location.href = this.jumpUrl; }, 1000); } } else { uni.hideLoading(); } } catch (err) { this.showToast('无法调起微信支付!', 'error'); } }, /** * @description: 镇宁聚合 * @return {*} */ async getWXMonthPayByJava() { const { monthId, jumpUrl } = this; try { const res = await this.$u.api.monthlyWxPay({ monthId, jumpUrl }); if (res.code === 200) { localStorage.setItem('jumpUrl', jumpUrl); location.href = res.data.qrCodeUrl; } } catch (err) { // this.showToast('无法调起支付!', 'error'); } }, /** * 支付弹框关闭触发 * @date 2023-02-17 * @returns {any} */ modalClose() { Object.assign(this, { payWayPop: false, wxEnv: true, alipayEnv: true, radioCurrent: '', orderMoney: '', isShowCoupon: false, isCancelCoupon: false, couponPopup: { show: false, couponList: [], radioCurrent: '', background: { backgroundColor: '#008CFF' }, currentCoupon: {} } }); this.$emit('closePaymentMethod'); }, /** * 关闭优惠券弹框 * @date 2023-02-17 * @returns {any} */ customBack() { this.couponPopup.show = false; }, /** * 优惠券单选触发 * @date 2023-02-17 * @param {any} val * @returns {any} */ couponRadioChange(val) { // this.couponPopup.radioCurrent = val.detail.value; // this.couponPopup.currentCoupon = this.couponPopup.couponList.find((item) => item.id === this.couponPopup.radioCurrent); }, couponItemClick(item) { this.couponPopup.radioCurrent = item.id === this.couponPopup.radioCurrent ? '' : item.id; }, /** * 优惠券确认 * @date 2023-02-17 * @returns {any} */ confimCoupon() { this.couponPopup.currentCoupon = this.couponPopup.radioCurrent ? this.couponPopup.couponList.find((item) => item.id === this.couponPopup.radioCurrent) : {}; this.couponPopup.show = false; }, /** * 立即支付 * @date 2023-02-17 * @returns {any} */ async immediatePayment() { if (this.isIndoor) { const relationObj = { weixin: 'wechat', gzyh: 'quick', juhe: 'poly' }; this.indoorPayment(relationObj[this.radioCurrent]); } else { const paymentMethods = { weixin: this.isMonthPay ? this.wechatMonthPay : this.wechatPay, gzyh: this.isMonthPay ? this.gyBankMonthPay : this.gyBankPay, juhe: this.isMonthPay ? this.juheMonthPay : this.juhePay, weixinzn: this.isMonthPay ? this.getWXMonthPayByJava : this.znWechatPay }; const paymentMethod = paymentMethods[this.radioCurrent]; if (paymentMethod) { await paymentMethod.call(this); } } }, /** * @description: 室内支付 * @param {*} payMode * @return {*} */ async indoorPayment(payMode) { const { curOrderList, couponPopup, vuex_wxinfo, jumpUrl } = this; const params = { orderList: curOrderList, payMode, couponMemberId: couponPopup?.radioCurrent, openid: vuex_wxinfo?.openId, sanPay: true, jumpUrl }; const { code, data } = await this.$u.api.indoorPaymentApi({ ...params }); if (code === 200) { if (data?.needPay) { switch (payMode) { case 'wechat': // 微信支付 $wxPay.weixinPay(data?.wechat?.wx).then((r) => { const messageMap = { 0: '成功', 1: '已取消支付', 2: '支付失败,请检查!' }; switch (Number(r.code)) { case 0: // 成功 //#ifdef H5 this.jumpUrl ? (location.href = `${this.jumpUrl}&polyOrderId=${data.polyOrderId}`) : location.reload(); //#endif break; case 1: // 取消 if (this.isCancelCoupon) { this.cancelCoupon(messageMap[r.code]); } else { this.showToast(messageMap[r.code], 'info'); } break; case 2: // 支付失败 this.showToast(messageMap[r.code], 'error'); break; } }); break; case 'quick': // 快捷支付 location.href = data?.quick?.url; break; case 'poly': localStorage.setItem('jumpUrl', this.jumpUrl); location.href = data?.poly?.qrCodeUrl; break; } } else { this.showToast('无需支付', 'info'); setTimeout(() => { this.jumpUrl ? (location.href = `${this.jumpUrl}&polyOrderId=${data.polyOrderId}`) : location.reload(); }, 1000); } } }, /** * 计算剩余时间 * @date 2022-02-17 * @param {any} datetime * @returns {any} */ calcValidity(startTime, endTime) { let endTimeStr = new Date(endTime).valueOf(), nowTimeStr = new Date(startTime).valueOf() < Date.now() ? Date.now() : new Date(startTime).valueOf(), remainTimeStr = endTimeStr - nowTimeStr, day = Math.floor(remainTimeStr / (1000 * 3600 * 24)), dayOver = remainTimeStr % (1000 * 3600 * 24), hours = Math.floor(dayOver / (3600 * 1000)), hourOver = dayOver % (3600 * 1000), minutes = Math.floor(hourOver / (60 * 1000)); return `${day}天${hours}小时${minutes}分`; }, getDifference(a, b) { return a > b ? a - b : 0; } } }; </script> <style lang="scss" scoped> @import './choosePayment.scss'; </style>