石广澎
2025-11-17 8771da2ccf6f7c3fd2a8c89a1a0e230c6386db7f
pages/pay/discountpay.vue
New file
@@ -0,0 +1,616 @@
<!-- 扫码支付 -->
<template>
   <view class="page">
      <u-alert type="warning" closable description="安全提醒:请谨慎核对商家、订单信息,保护自己资金安全!"></u-alert>
      <view class="pay-box">
         <view class="u-font-26 color-666">应付金额</view>
         <view class="u-m-t-14">
            <text class="u-font-36 color-333 u-m-r-8">¥</text>
            <text class="money">{{money.split(".")[0]}}</text>
            <text class="u-font-40">.{{money.split(".")[1]}}</text>
         </view>
      </view>
      <view v-if="discountInfo.shopDiscount!=1&&money*(1-discountInfo.shopDiscount)>=0.01" class="bg-fff u-m-h-32 u-m-t-20 u-p-h-32 u-br-10">
         <view class="u-p-v-32 u-flex u-row-between u-border-bottom u-font-30 color-333">
            <view>{{discountInfo.memberGradeName}}专属折扣</view>
            <view>-{{ money*(1-discountInfo.shopDiscount).toFixed(2) }}</view>
         </view>
      </view>
      <view v-if="canUseIntegral||canUseCoupon" class="u-p-h-32 bg-fff u-m-h-32 u-br-10">
         <view class="u-font-28 u-m-t-32">选择优惠方式</view>
         <view v-if="canUseIntegral" class="u-p-v-24 u-border-bottom u-flex u-m-t-10">
            <image class="item-icon" style="align-self: flex-start;position: relative;top: -3rpx;" src="/static/integral.png" mode=""></image>
            <view class="u-flex-1 u-m-h-16">
               <view class="u-font-30">积分抵扣</view>
               <view class="u-font-24 color-999 u-m-t-20">可用<text style="color: #D31F28;">{{integral}}</text>积分
               </view>
            </view>
            <input-number @handleCount="changeInt" :value="canUseInt" :min="0" :max="maxIntegral">
            </input-number>
         </view>
         <view v-if="canUseCoupon" class="u-flex u-p-v-32">
            <image class="item-icon" src="/static/coupon-icon.png" mode=""></image>
            <view class="u-font-30 u-flex-1 u-m-h-16">优惠券</view>
            <view @click="showCoupon" class="u-flex">
               <view v-if="couponInfo.id" class="tag-pain">
                  满{{parseFloat((couponInfo.thresholdValue/100).toFixed(2))}}元减{{parseFloat((couponInfo.discount/100).toFixed(2))}}元
               </view>
               <text v-else class="u-font-26">请选择</text>
               <u-icon class="u-m-l-10" name="arrow-right" color="#333" size="13"></u-icon>
            </view>
         </view>
      </view>
      <view class="bg-fff u-m-h-32 u-m-t-20 u-p-h-32 u-br-10">
         <view v-if="discount" class="u-p-v-32 u-flex u-row-between u-border-bottom u-font-30 color-333">
            <view>实际抵扣</view>
            <view>-{{ discount }}</view>
         </view>
         <view class="u-p-v-32 u-flex u-row-between">
            <view class="u-font-30 color-333">实付金额</view>
            <view class="color-red">
               <text class="u-font-26 u-m-r-6">¥</text>
               <text class="u-font-34">{{ price }}</text>
            </view>
         </view>
      </view>
      <button class="pay-it" @click="pay">确定支付</button>
      <!-- 优惠券弹窗 -->
      <u-popup mode="bottom" :closeable="true" :show="couponShow" @close="couponShow = false" :round="10">
         <view class="u-font-32 color-333 u-text-center u-p-t-30">优惠券</view>
         <view v-if="checkCoupon.id" class="choose-coupon">
            已选择优惠券1张,共抵扣¥{{parseFloat((checkCoupon.discount/100).toFixed(2))}}</view>
         <!-- <view class="choose-coupon">选择优惠券</view> -->
         <scroll-view scroll-y class="u-p-30 coupon-list">
            <view @click="clickCoupon(item)" class="u-m-b-24 u-flex coupon" v-for="(item, index) in couponList" :key="index">
               <view style="color: #D31F28;" class="u-p-h-28">
                  <view class="font-bold">
                     <text class="u-font-36">¥</text>
                     <text class="money">{{parseFloat(item.discount/100)}}</text>
                  </view>
                  <view class="u-font-24 u-m-t-20">满{{parseFloat(item.thresholdValue/100)}}元使用</view>
               </view>
               <view class="butt"></view>
               <view class="u-p-30 u-flex-1 u-flex">
                  <view class="u-flex-1">
                     <view class="u-font-28 color-333 u-line-2">{{item.name}}</view>
                     <view class="u-font-22 color-999 u-m-t-20">
                        有效期至:{{$u.timeFormat(item.outTime, 'yyyy-mm-dd hh:MM')}}
                     </view>
                  </view>
                  <u-icon v-if="item.id==checkCoupon.id" name="checkmark-circle-fill" color="#D31F28" size="20">
                  </u-icon>
               </view>
            </view>
         </scroll-view>
         <view @click="getCoupon" class="coupon-btn">确定</view>
      </u-popup>
      <!-- 数字键盘 -->
      <u-popup :show="bordShow" :overlay="false" @close="bordShow = false">
         <key-bord @changeMoney="changeMoney" :num.sync="money" @close="bordShow = false" @pay="pay"></key-bord>
      </u-popup>
      <!-- 支付验证码 -->
      <u-popup :show="codeShow" closeable mode="center" @close="codeShow = false">
         <view class="u-p-h-40 u-p-b-40">
            <view class="u-text-center u-p-t-20 u-m-b-30 u-font-34">请输入手机验证码</view>
            <view class="u-text-center u-m-b-20 color-666">{{ shopInfo.shop_name }}</view>
            <view class="u-flex u-row-center font-bold u-m-b-40"><text class="u-font-42">¥</text><text class="u-font-money">{{ price }}</text>
            </view>
            <u-code-input @finish="bankPay" v-model="smscode" mode="box" :focus="true"></u-code-input>
         </view>
      </u-popup>
   </view>
</template>
<script>
   import {
      ACCESSTOKEN
   } from '@/common/config.js';
   import {
      queryMyUseSweepPayMaxCoupon,
      queryUseSweepPayCoupon,
      getWechatConfigInfo,
      saveWxOrder,
      tlPay
   } from '@/common/api/index'
   import wx from 'weixin-js-sdk'; // 使用js-sdk
   export default {
      data() {
         return {
            cid: null,
            bordShow: false, // 显示键盘
            scoreWorth: 0,
            shopInfo: {
               shop_name: '',
               scan_flag: '',
               use_score_flag: 0, //商铺是否可用积分 0否 1是
               user_coupon_flag: 0, //商铺是否可用优惠券 0否 1是
               app_pay_use_score_flag: 0, //微信/支付宝是否可用积分 0否 1是
               app_pay_use_coupon_flag: 0, //微信/支付宝是否可用优惠券 0否 1是
               bank_pay_use_score_flag: 0, //银行卡支付是否可用积分 0否 1是
               bank_pay_use_coupon_flag: 0, //银行卡支付是否可用优惠券 0否 1是
            },
            money: 0.00, // 金额
            integral: 0, // 使用积分
            canUseInt: 0, // 可用积分
            couponList: [], // 优惠券
            couponShow: false, // 优惠券弹窗
            couponInfo: {
               id: '',
               discount: 0,
               thresholdValue: 0
            }, // 优惠券内容
            payWay: 3, // 5支付宝 2微信 3银行卡
            isNew: false,
            codeShow: false,
            smscode: '',
            thpinfo: null,
            canReset: false,
            checkCoupon: {
               id: null,
               discount: 0,
               thresholdValue: 0
            },
            discountInfo: {
               memberGradeName: '',
               shopDiscount: 10
            }
         };
      },
      watch: {
         integralDiscount(val) {
            if (this.couponInfo.id && val < this.couponInfo.thresholdValue) {
               this.couponInfo = {
                  id: '',
                  discount: 0,
                  thresholdValue: 0
               }
               this.checkCoupon = {
                  id: '',
                  discount: 0,
                  thresholdValue: 0
               }
            }
         }
      },
      computed: {
         canUseIntegral() {
            if (this.payWay == 3) { //银行卡
               return this.shopInfo.use_score_flag && this.shopInfo.bank_pay_use_score_flag
            } else {
               return this.shopInfo.use_score_flag && this.shopInfo.app_pay_use_score_flag
            }
         },
         canUseCoupon() {
            if (this.payWay == 3) { //银行卡
               return this.shopInfo.user_coupon_flag && this.shopInfo.bank_pay_use_coupon_flag
            } else {
               return this.shopInfo.user_coupon_flag && this.shopInfo.app_pay_use_coupon_flag
            }
         },
         maxIntegral() {
            if (this.couponInfo.id) {
               const num = Math.ceil((this.money * this.discountInfo.shopDiscount - this.couponInfo.thresholdValue / 100) / (
                  this.scoreWorth / 100))
               if (num < 0) {
                  return 0
               }
               return num
            } else {
               const num = Math.ceil((this.money * this.discountInfo.shopDiscount - this.couponInfo.thresholdValue / 100) / (
                  this.scoreWorth / 100))
               if (num < 0) {
                  return 0
               }
               return num
            }
         },
         integralDiscount() {
            let num = 0;
            num = parseInt(parseFloat((this.money * this.discountInfo.shopDiscount * 100).toPrecision(12)) - this.canUseInt *
               this.scoreWorth);
            return num;
         },
         discount() {
            let num = 0;
            num = ((this.canUseInt * this.scoreWorth + parseFloat(this.couponInfo.discount)) / 100).toFixed(2);
            if (parseFloat(num) > parseFloat(this.money * this.discountInfo.shopDiscount)) {
               return this.money * this.discountInfo.shopDiscount
            }
            return num;
         },
         price() {
            let num = 0;
            num = parseFloat((this.money * this.discountInfo.shopDiscount * 100).toPrecision(12)) - this.canUseInt * this
               .scoreWorth - this.couponInfo
               .discount;
            num = num > 0 ? (num / 100).toFixed(2) : '0.00';
            return num;
         }
      },
      onLoad(opt) {
         this.isNew = uni.getStorageSync('IS_NEW')
         this.cid = uni.getStorageSync('CID')
         this.discountInfo = uni.getStorageSync('DISCOUNT_INFO') || {
            shopDiscount: 1
         }
         const token = uni.getStorageSync(ACCESSTOKEN) || null
         this.shopInfo = uni.getStorageSync('SHOP_INFO')
         if (opt.scoreWorth) {
            this.scoreWorth = Number(opt.scoreWorth)
         }
         if (opt.integral) {
            this.integral = Number(opt.integral)
         }
         if (opt.money) {
            this.money = parseFloat(opt.money).toFixed(2)
            let ds = parseFloat(this.discountInfo.shopDiscount)
            let dis = this.money * 100 * (1 - ds)
            let money = parseInt((this.money * 100 * ds))
            if (dis < 1) {
               money = parseInt((this.money * 100))
            }
            queryMyUseSweepPayMaxCoupon({
               params: {
                  shopId: this.shopInfo.id,
                  money: money < 1 ? 1 : money
               }
            }).then(res => {
               if (res && this.canUseCoupon) {
                  this.couponInfo = res
                  this.checkCoupon = res
               }
            })
         }
         if (opt.payWay) {
            this.payWay = opt.payWay
         }
         if (opt.bankCardId) {
            this.bankCardId = opt.bankCardId
         }
         this.init()
      },
      methods: {
         // 更新金额
         changeMoney(str) {
            this.money = str;
         },
         // 展示键盘
         showBord() {
            this.bordShow = true;
         },
         init() {
            uni.showLoading()
            if (this.payWay == 2) {
               const uri = encodeURIComponent(window.location)
               getWechatConfigInfo({
                  url: uri
               }).then(res => {
                  uni.hideLoading()
                  wx.config({
                     debug: false, // 开启调试模式
                     appId: res.appId, // 必填,公众号的唯一标识
                     timestamp: res.timestamp, // 必填,生成签名的时间戳
                     nonceStr: res.nonceStr, // 必填,生成签名的随机串
                     signature: res.signature, // 必填,签名
                     jsApiList: ['chooseWXPay'], // 必填,需要使用的 JS 接口列表
                     // openTagList: ['wx-open-launch-weapp'] //可选,需要使用的开放标签列表
                  });
               }).catch(() => {
                  uni.hideLoading()
               })
            }
         },
         // 更改积分
         changeInt(num) {
            this.canUseInt = num;
         },
         pay() {
            this.bordShow = false
            uni.showLoading()
            const params = {
               money: parseFloat((this.money * 100).toPrecision(12)),
               shopId: this.shopInfo.id,
               cid: this.cid,
               payWay: this.payWay,
               score: this.canUseInt,
               couponDetailId: this.couponInfo.id
            }
            if (this.payWay == 3) {
               params.bankCardId = this.bankCardId
            }
            saveWxOrder(params).then(res => {
               uni.hideLoading()
               try {
                  this.orderId = res.orderId
                  res.youHuiInfo.shopName = this.shopInfo.shop_name
                  this.youHuiInfo = res.youHuiInfo
                  if (res.isOk == 1) {
                     uni.navigateTo({
                        url: `/pages/pay/paySuccess?orderId=${this.orderId}&youHuiInfo=${JSON
                           .stringify(this.youHuiInfo)}`
                     })
                  } else {
                     if (res.toPayMethod == 1) {
                        if (this.payWay == 3) {
                           this.smscode = ''
                           this.codeShow = true
                        }
                     } else if (res.toPayMethod == 2) {
                        if (this.payWay == 2) {
                           this.wxPay(res.paymentData)
                        }
                        if (this.payWay == 5) {
                           this.aliPay(res.paymentData)
                        }
                     } else if (res.toPayMethod == 3) {
                        window.location.href = res.paymentUrl
                     }
                  }
               } catch (e) {
                  //TODO handle the exception
                  console.error(e);
               }
            }).catch(() => {
               uni.hideLoading()
            })
         },
         // 微信支付
         wxPay(res) {
            /*setTimeout(() => {
               wx.chooseWXPay({
                  timestamp: res.timeStamp, // 支付签名时间戳
                  nonceStr: res.nonceStr, // 支付签名随机串,不长于 32 位
                  package: res.package, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*)
                  signType: res.signType, // 微信支付V3的传入 RSA ,微信支付V2的传入格式与V2统一下单的签名格式保持一致
                  paySign: res.paySign, // 支付签名
                  success: function(res) {
                     // 支付成功后的回调函数
                     uni.navigateTo({
                        url: `/pages/pay/paySuccess?orderId=${this.orderId}&youHuiInfo=${JSON
                           .stringify(this.youHuiInfo)}`
                     })
                  }
               });
            }, 200)*/
            setTimeout(() => {
               WeixinJSBridge.invoke(
                  'getBrandWCPayRequest', {
                     "appId": res.appId, //公众号ID,由商户传入
                     "timeStamp": res.timeStamp, //时间戳,自1970年以来的秒数
                     "nonceStr": res.nonceStr, //随机串
                     "package": res.package,
                     "signType": res.signType, //微信签名方式:
                     "paySign": res.paySign //微信签名
                  },
                  (res) => {
                     if (res.err_msg == "get_brand_wcpay_request:ok") {
                        // 使用以上方式判断前端返回,微信团队郑重提示:
                        //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
                        /*uni.navigateTo({
                           url: `/pages/pay/paySuccess?orderId=${this.orderId}&youHuiInfo=${JSON
                        .stringify(this.youHuiInfo)}`
                        })*/
                     }
                  });
            }, 200)
         },
         //支付宝支付
         aliPay(res) {
            ap.tradePay({
               tradeNO: res.tradeNO
            }, (res) => {
               if (res.resultCode == 9000) {
                  /*uni.navigateTo({
                     url: `/pages/pay/paySuccess?orderId=${this.orderId}&youHuiInfo=${JSON
                        .stringify(this.youHuiInfo)}`
                  })*/
                  // 支付成功
               } else if (res.resultCode == 8000 || res.resultCode == 6001) {
                  // 正在处理中 || 取消
               } else {
                  // 支付失败
               }
            });
         },
         //银行卡支付
         bankPay(e) {
            uni.showLoading()
            tlPay({
               orderId: this.orderId,
               payWay: 3,
               bankCardId: this.bankCardId,
               smscode: e
            }).then(res => {
               uni.hideLoading()
               uni.hideKeyboard()
               this.codeShow = false
               uni.navigateTo({
                  url: `/pages/pay/paySuccess?orderId=${this.orderId}&youHuiInfo=${JSON
                     .stringify(this.youHuiInfo)}`
               })
            }).catch(() => {
               uni.hideLoading()
            })
         },
         //显示优惠券
         showCoupon() {
            uni.showLoading()
            queryUseSweepPayCoupon({
               params: {
                  cusid: this.shopInfo.cusid,
                  c: this.shopInfo.c,
                  money: parseFloat((this.money * 100).toPrecision(12)),
                  score: this.canUseInt
               }
            }).then(res => {
               uni.hideLoading()
               if (res.length > 0) {
                  this.couponList = res
                  this.checkCoupon = this.couponInfo
                  this.couponShow = true;
               } else {
                  uni.showToast({
                     icon: 'none',
                     title: '暂无可用优惠券'
                  })
               }
            }).catch(() => {
               uni.hideLoading()
            })
         },
         clickCoupon(item) {
            if (this.checkCoupon.id == item.id) {
               this.checkCoupon = {
                  id: '',
                  discount: 0,
                  thresholdValue: 0
               }
            } else {
               this.checkCoupon = item
            }
         },
         getCoupon() {
            // item 为优惠券信息
            this.couponInfo = this.checkCoupon;
            this.couponShow = false;
         }
      }
   };
</script>
<style scoped lang="scss">
   .page {
      height: calc(100vh - 0px);
      display: flex;
      flex-direction: column;
      line-height: 1;
   }
   .avg-img {
      width: 80rpx;
      height: 80rpx;
   }
   .pay-box {
      text-align: center;
      padding: 65rpx 0 42rpx;
   }
   .money {
      font-size: 64rpx;
   }
   .tag-pain {
      border: 1px solid #D31F28;
      font-size: 22rpx;
      color: #D31F28;
      border-radius: 4rpx;
      line-height: 1;
      padding: 8rpx 4rpx;
   }
   .item-icon {
      width: 38rpx;
      height: 38rpx;
   }
   .pay-it {
      position: absolute;
      width: 686rpx;
      height: 98rpx;
      bottom: 0;
      border-radius: 10rpx;
      font-size: 34rpx;
      color: #ffffff;
      background-color: #de2d35;
      margin: 32rpx;
   }
   .choose-coupon {
      margin: 32rpx 32rpx 0;
      border-radius: 10rpx;
      background: #fff1f1;
      padding: 26rpx 16rpx;
      color: #D31F28;
      font-size: 28rpx;
   }
   .coupon-list {
      box-sizing: border-box;
      height: calc(50vh - 44px);
   }
   .coupon {
      background-color: rgba(255, 241, 241, 0.47);
      height: 171rpx;
      border: solid 1rpx #f85d64;
      border-radius: 10rpx;
      position: relative;
      overflow: hidden;
   }
   .butt {
      width: 1rpx;
      height: 100%;
      position: relative;
      z-index: 9;
      border-left: 1rpx dashed #f85d64;
   }
   .butt:before {
      z-index: 10;
      box-sizing: border-box;
      position: absolute;
      content: "";
      width: 24rpx;
      height: 12rpx;
      border-bottom: 1rpx solid #f85d64;
      border-right: 1rpx solid #f85d64;
      border-left: 1rpx solid #f85d64;
      border-radius: 0 0 24rpx 24rpx;
      left: -12rpx;
      background-color: #ffffff;
   }
   .butt:after {
      box-sizing: border-box;
      position: absolute;
      content: "";
      width: 24rpx;
      height: 12rpx;
      bottom: 0;
      border-bottom: 1rpx solid #ffff;
      border-right: 1rpx solid #f85d64;
      border-left: 1rpx solid #f85d64;
      border-top: 1rpx solid #f85d64;
      border-radius: 24rpx 24rpx 0 0;
      left: -12rpx;
      background-color: #ffffff;
   }
   .coupon-btn {
      margin: 0 32rpx;
      height: 98rpx;
      border-radius: 10rpx;
      background-color: #D31F28;
      font-size: 34rpx;
      color: #fff;
      line-height: 98rpx;
      text-align: center;
   }
   .u-font-money {
      font-size: 60rpx;
   }
</style>