uniapp 微信小程序 支付

<template>
  <view class="wrap">
    <view class="payComplete">
      <image class="img" src="@/static/image/index/6.png" />
      <text class="adress">支付完成后填写</text>
    </view>
    <view class="commodityWrap">
      <view class="title">
        <text class="border" />
        <text>商品信息</text>
      </view>
      <view class="min">
        <image v-if="productObj.picUrl" class="img" :src="productObj.picUrl" />
        <image v-else class="img" src="@/static/image/index/defaultImg.png" />
        <view class="right">
          <view class="name">
            <text class="secondaryContent">
              {{ productObj.productName }}
            </text>
            <text class="num"
              >¥ {{ productObj.price ? (Number(productObj.price) / 100).toFixed(2) : '0.00' }}</text
            >
          </view>
          <view class="name illustrate">
            <text class="secondaryContent">
              {{ productObj.productExt }}
            </text>
          </view>
        </view>
      </view>
      <view class="bottomNum">
        <view class="wraps">
          <text>选择数量</text>
          <up-number-box
            @change="valChange"
            v-model="chooseNumber"
            @blur="onNumberChange"
            :min="1"
            :max="999"
          />
        </view>
      </view>
    </view>
    <view class="commodityWrap payWay">
      <view class="title">
        <text class="border" />
        <text>支付方式</text>
      </view>
      <view class="payList">
        <view class="left">
          <image class="img" src="@/static/image/index/8.png" />
          <text class="adress">微信支付</text>
        </view>
        <image class="right" src="@/static/image/index/7.png" />
      </view>
    </view>
    <view class="goPay">
      <view class="wraps">
        <view class="left">
          <text class="name">应付:</text>
          <text class="name">¥ </text>
          <text class="name">{{ payNumberInteger }}</text>
          <text class="name">.{{ payNumberDecimal }}</text>
        </view>
        <view class="right" @tap="toPay"> 去支付 </view>
      </view>
    </view>
    <view class="bg" v-if="bgShow" />
    <view class="bgTwo" v-if="bgShowTwo" />
  </view>
</template>

<script setup lang="ts">
import { reactive, ref } from 'vue'
import { onLoad, onShow, onUnload, onHide } from '@dcloudio/uni-app'
import { productInfoInfo, orderPaid, orderStatus } from '@/api/index'
const state = reactive({
  timeQuestions: null
})
const chooseNumber = ref(1)
const chooseNumberSure = ref(1)
const productId = ref('')
const productObj = ref({})
const bizOrderNo = ref('')
const userInfo = ref({})
const isstop = ref(false)
const isBack = ref(false)
// 整数部分
const payNumberInteger = ref('0')
// 小数部分
const payNumberDecimal = ref('00')
const bgShow = ref(false)
const bgShowTwo = ref(false)

onLoad((options) => {
  productId.value = options.productId
})
onUnload(() => {
  const isScan = uni.getStorageSync('wxScans')
  clearInterval(state.timeQuestions)
  state.timeQuestions = null
  if (isScan && isScan == 'true' && !isBack.value) {
    uni.switchTab({
      url: '/pages/load/index'
    })
    // uni.switchTab({
    //   url: '/pages/index/index'
    // })
  }
})
onHide(() => {
  uni.removeStorageSync('isBack')
  uni.removeStorageSync('isChoose')
})
onShow(() => {
  bgShow.value = false
  bgShowTwo.value = false
  userInfo.value = uni.getStorageSync('userInfo') ? JSON.parse(uni.getStorageSync('userInfo')) : {}
  productObj.value = {}
  chooseNumber.value = 1
  chooseNumberSure.value = 1
  payNumberInteger.value = '0'
  payNumberDecimal.value = '00'
  init()
})
const init = () => {
  if (uni.getStorageSync('paySuccess') == 'true') {
    uni.showLoading({
      title: '支付中...'
    })
    bgShowTwo.value = true
  } else {
    uni.showLoading({
      title: '加载中'
    })
  }
  const param = '?productId=' + productId.value
  productInfoInfo(param).then((res: any) => {
    if (isstop.value == false) {
      uni.hideLoading()
    }
    if (res.code == 0) {
      if (res.data) {
        if (res.data.productStatus == 'off') {
          uni.removeStorageSync('isBack')
          uni.removeStorageSync('isChoose')
          bgShowTwo.value = true
          uni.showToast({
            title: '该商品已下架',
            icon: 'none',
            duration: 2000
          })
          setTimeout(() => {
            bgShowTwo.value = false
            uni.switchTab({
              url: '/pages/index/index'
            })
          }, 2000)
        } else {
          if (res.data && res.data.productName) {
            productObj.value = res.data
            const price =
              res.data && res.data.price ? (Number(res.data.price) / 100).toFixed(2) : '0.00'
            payNumberInteger.value = price.split('.')[0]
            payNumberDecimal.value = price.split('.')[1]
          }
        }
      }
    }
  })
}
const valChange = (e) => {
  chooseNumberSure.value = e.value
  const price = (
    (productObj.value && productObj.value.price ? Number(productObj.value.price) / 100 : 0) *
    e.value
  ).toFixed(2)
  payNumberInteger.value = price.split('.')[0]
  payNumberDecimal.value = price.split('.')[1]
}
const onNumberChange = (event) => {
  if (!event.value) {
    chooseNumber.value = 1000
    chooseNumberSure.value = 1000
    setTimeout(() => {
      chooseNumber.value = 1
      chooseNumberSure.value = 1
    }, 20)

    const price =
      productObj.value && productObj.value.price
        ? (Number(productObj.value.price) / 100).toFixed(2)
        : '0.00'
    payNumberInteger.value = price.split('.')[0]
    payNumberDecimal.value = price.split('.')[1]
  }
}
//支付
const toPay = () => {
  uni.showLoading({
    title: '加载中'
  })

  const param = {
    patientId: userInfo.value.patientId,
    openid: userInfo.value.openId,
    productId: productId.value,
    doctorId: userInfo.value.bindDoctorId ? userInfo.value.bindDoctorId : null,
    num: chooseNumberSure.value
  }
  orderPaid(param).then((res: any) => {
    uni.hideLoading()
    if (res.code == 0) {
      const payParam = JSON.parse(res.data.payBody)
      bizOrderNo.value = res.data.bizOrderNo
      uni.requestPayment({
        provider: 'wxpay',
        timeStamp: payParam.timeStamp,
        nonceStr: payParam.nonceStr,
        package: payParam.package,
        signType: payParam.signType,
        paySign: payParam.paySign,
        success: function (res) {
          isstop.value = true
          bgShow.value = true
          uni.setStorageSync('paySuccess', 'true')
          loopTime()
          console.log('success:' + JSON.stringify(res))
        },
        fail: function (err) {
          isstop.value = false
          isBack.value = true
          bgShow.value = false
          bgShowTwo.value = false
          //   console.log('支付失败')
          uni.removeStorageSync('isBack')
          uni.removeStorageSync('isChoose')
          uni.redirectTo({
            url:
              '/packA/pages/pay/nopayIndex?productId=' +
              productId.value +
              '&chooseNumberSure=' +
              chooseNumberSure.value +
              '&bizOrderNo=' +
              bizOrderNo.value
          })
          console.log('fail:' + JSON.stringify(err))
        }
      })
    }
  })
}
const loopTime = () => {
  let s = 0
  state.timeQuestions = setInterval(() => {
    s++
后端说 orderStatusFun这个方法的接口 两秒内肯定会更新支付状态  所以两秒后调用这个方法
    if (s >= 2) {
      s = 0
      orderStatusFun()
    }
  }, 1000)
}
const orderStatusFun = () => {
  const param = bizOrderNo.value
  orderStatus(param).then((res) => {
    isstop.value = true
    if (res.data.payState == 'PROGRESS') {
      console.log('PROGRESS')
    } else if (res.data.payState == 'SUCCESS') {
      bgShow.value = false
      uni.removeStorageSync('paySuccess')
      clearInterval(state.timeQuestions)
      state.timeQuestions = null
      uni.showToast({
        title: '支付成功',
        icon: 'none',
        duration: 2000
      })
      setTimeout(() => {
        isstop.value = false
        bgShowTwo.value = false
        isBack.value = true
        uni.removeStorageSync('isBack')
        uni.removeStorageSync('isChoose')
        uni.hideLoading()
        uni.redirectTo({ url: '/packA/pages/address/index?bizOrderNo=' + bizOrderNo.value })
      }, 2000)
    } else {
      clearInterval(state.timeQuestions)
      state.timeQuestions = null
    }
  })
}
</script>

<style lang="scss" scoped>
.wrap {
  min-height: 100vh;

  .payComplete {
    display: inline-block;
    width: calc(100% - 64rpx);
    margin: 32rpx 32rpx 24rpx;
    padding: 24rpx 32rpx;
    border-radius: 16rpx;
    background: #fff;
    color: #222;
    font-size: 32rpx;
    font-weight: 700;

    .img {
      display: inline-block;
      width: 32rpx;
      height: 32rpx;
      margin-right: 16rpx;
      vertical-align: middle;
    }

    .adress {
      display: inline-block;
      vertical-align: middle;
    }
  }

  .commodityWrap {
    margin: 0 32rpx;
    overflow: hidden;
    border-radius: 16rpx;
    background: #fff;

    .title {
      position: relative;
      padding: 24rpx 32rpx;
      color: #222;
      font-size: 32rpx;
      font-weight: 700;

      .border {
        position: absolute;
        top: 50%;
        left: 0;
        width: 8rpx;
        height: 32rpx;
        transform: translateY(-50%);
        background: #316ffe;
      }
    }

    .min {
      padding: 0 32rpx;

      .img {
        display: inline-block;
        width: 136rpx;
        height: 136rpx;
        border-radius: 12rpx;
        vertical-align: top;
      }

      .right {
        display: inline-block;
        width: calc(100% - 160rpx);
        margin-left: 24rpx;
        vertical-align: top;

        .name {
          position: relative;
          width: 100%;
          color: #222;
          font-size: 28rpx;
          font-weight: 700;

          .secondaryContent {
            display: -webkit-box;
            width: calc(100% - 140rpx);
            height: 73rpx;
            overflow: hidden;
            text-overflow: ellipsis;
            -webkit-box-orient: vertical;
            -webkit-line-clamp: 2; /* 定义文本的行数 */
          }

          .num {
            position: absolute;
            top: 0;
            right: 0;
            width: 140rpx;
            color: #ff503d;
            text-align: right;
            white-space: nowrap;
          }

          &.illustrate {
            margin-top: 24rpx;
            color: #999;
            font-size: 24rpx;
            font-weight: 400;

            .secondaryContent {
              width: 100%;
              height: auto;
              -webkit-line-clamp: 1;
            }
          }
        }
      }
    }

    ::v-deep .bottomNum {
      padding: 24rpx 32rpx;
      color: #222;
      font-size: 30rpx;

      .wraps {
        position: relative;
        height: 56rpx;
        line-height: 56rpx;

        .u-number-box {
          position: absolute;
          top: 50%;
          right: 0rpx;
          transform: translateY(-50%);
          border: 1rpx solid #e5e6eb;
          border-radius: 4rpx;

          .u-number-box__minus,
          .u-number-box__input,
          .u-number-box__plus {
            height: 56rpx !important;
            background-color: #fff !important;
          }

          .u-number-box__input {
            width: 80rpx !important;
            margin: 0 !important;
            border-right: 1rpx solid #e5e6eb;
          }

          .u-number-box__minus {
            border-right: 1rpx solid #e5e6eb;

            &.u-number-box__minus--disabled {
              .u-icon__icon {
                color: #cfcfcf !important;
              }
            }
          }

          .u-number-box__plus {
            &.u-number-box__minus--disabled {
              .u-icon__icon {
                color: #cfcfcf !important;
              }
            }
          }
        }
      }
    }

    &.payWay {
      margin-top: 24rpx;
      padding-bottom: 24rpx;

      .payList {
        position: relative;
        margin: 0 32rpx;
        padding: 8rpx 0 32rpx;
        border-bottom: 1rpx solid #e5e6eb;

        .left {
          .img {
            display: inline-block;
            width: 32rpx;
            height: 32rpx;
            vertical-align: middle;
          }

          .adress {
            display: inline-block;
            margin-left: 16rpx;
            color: #222;
            font-size: 32rpx;
            font-weight: 700;
            vertical-align: middle;
          }
        }

        .right {
          display: block;
          position: absolute;
          top: calc(50% - 12rpx);
          right: 0;
          width: 32rpx;
          height: 32rpx;
          transform: translateY(-50%);
        }
      }
    }
  }

  .goPay {
    position: fixed;
    bottom: 0;
    left: 0;
    width: 100%;
    padding-bottom: constant(safe-area-inset-bottom);
    padding-bottom: env(safe-area-inset-bottom);
    background: #fff;

    .wraps {
      position: relative;
      padding: 32rpx 40rpx;

      .left {
        color: #222;
        font-size: 28rpx;
        font-weight: 700;

        .name {
          &:nth-child(2),
          &:nth-child(4) {
            color: #ff503d;
            font-size: 24rpx;
          }

          &:nth-child(3) {
            color: #ff503d;
            font-size: 56rpx;
          }
        }
      }

      .right {
        position: absolute;
        top: 50%;
        right: 32rpx;
        padding: 22rpx 64rpx;
        transform: translateY(-50%);
        border-radius: 44rpx;
        background: #ff503d;
        color: #fff;
        font-size: 32rpx;
      }
    }
  }

  .bg {
    position: fixed;
    z-index: 1;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgb(0 0 0 / 50%);
  }

  .bgTwo {
    position: fixed;
    z-index: 1;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgb(0 0 0 / 0.1%);
  }
}
</style>
posted @   风雪中de冲破  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示