前端支付宝支付流程

504 阅读1分钟

支付宝支付思路如下

  • 首先点击商品的支付按钮 同时拿到这个订单的编号等一些信息

  • 然后拿着这些数据去调用后端给的支付的接口 支付的接口会返回一个链接 这个链接就是订单对接支付宝 支付宝给我们用来跳转的链接

  • 拿着这个链接去调原生的方法 就可以唤醒支付宝支付了

  • 唤醒支付宝后我们再调用一个原生的方法 这个方法是监听我们支付完成后 有没有返回进入了我们的app 当我们返回app的时候 可以拿到这个状态

  • 这个时候判断这个状态 如果状态为返回了app 我们就要调用一个后端的接口来判断我们是否支付成功了

  • 然后就可以进行支付后的动作了

  • 代码如下 项目不同 不能直接复制 仅供参考

没有接微信的支付 因为公司用的是聚合支付 原生说如果调用微信支付的话 他拿不到回调(我也不懂) 反正就是需要前端开发一个小程序专门用来支付 然后点击按钮使app跳转到小程序去支付 好麻烦就暂时没做了

<template>
  <div class="module_paymentHome">
    <div class="payment-cont">
      <van-radio-group v-model="payParams.payType" class="payment-mode">
        <van-cell-group>
          <van-cell clickable>
            <template #title>
              <img class="icon-pay" src="@/assets/images/sharedData/icon_pay_zfb.png" alt="" />
              <span>支付宝支付</span>
            </template>
            <template #right-icon>
              <van-radio name="ALIPAY" />
            </template>
          </van-cell>
          <van-cell v-if="false" clickable>
            <template #title>
              <img class="icon-pay" src="@/assets/images/sharedData/icon_pay_wx.png" alt="" />
              <span>微信支付</span>
            </template>
            <template #right-icon>
              <van-radio name="WECHAT" />
            </template>
          </van-cell>
        </van-cell-group>
      </van-radio-group>
    </div>

    <div class="btn-area">
      <button class="btn-submit" :class="{'disable': !payParams.payType}" @click="confirmPay">
        确认支付
      </button>
    </div>
  </div>
</template>
<script>
import { Toast } from 'vant'
import deviceEnv from '@/utils/deviceEnv'
// import cookie from '../../utils/cookie'
import payment from '@/api/payment'
export default {
  name: '',

  data() {
    return {
      isSubmit: false, // 防重复提交
      payType: '',
      channel: '',
      orderId: '',
      payParams: {
        orderNo: '', // 数据id
        payType: 'ALIPAY', // 支付渠道
        uid: this.guid(),
        paySubType: 'APP'
      }
    }
  },

  watch: {
  },
  created() {
    this.payParams.orderNo = this.$route.params.id
    window.isPaymentSuc = this.isPaymentSuc
  },
  methods: {
    S4() {
      return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)
    },
    guid() {
      return (this.S4() + this.S4() + '-' + this.S4() + '-' + this.S4() + '-' + this.S4() + '-' + this.S4() + this.S4() + this.S4())
    },
    async confirmPay() {
      if (this.isSubmit) {
        return
      }
      Toast.loading({
        message: '加载中...',
        forbidClick: true,
        duration: 10000
      })
      this.isSubmit = true
      // console.log(this.payParams.payType)
      // console.log(cookie.readCookie('sdktoken'))
      // +++++++++  微信  +++++++++
      // if (this.payParams.payType === 'WECHAT') {
      // console.log(deviceEnv.isFromIos())
      // console.log('ios')
      // if (deviceEnv.isFromIos()) {
      // ios
      // window.webkit.messageHandlers.adaPay.postMessage({
      //   body: {
      //     payType: this.payParams.payType,
      //     merchantNo: this.payParams.orderNo, // id
      //     token: cookie.readCookie('sdktoken'),
      //     type: this.$route.query.target ? 'exhibit' : ''
      //   }
      // })
      // } else {
      // 安卓
      // }
      // }
      // =================  支付宝支付 =================
      if (this.payParams.payType === 'ALIPAY') {
        const param = {
          orderNo: this.payParams.orderNo,
          payType: this.payParams.payType,
          uid: this.payParams.uid,
          paySubType: 'APP'
        }
        // +++++++++  支付的接口  +++++++++
        const res = await payment.pay(param)
        console.log(res)
        if (res.code === 0) {
          this.orderId = res.data.orderId
          if (deviceEnv.isFromIos()) {
          // IOS
            window.webkit.messageHandlers.adaPaydoPay.postMessage({ body: res.data.bankReturnMsg })
          } else if (deviceEnv.isFromAndroid()) {
          // 安卓
            window.android.adaPaydoPay(res.data.bankReturnMsg, 'isPaymentSuc')
          }
        } else {
          this.$toast(res.message)
          if (res.code === 60000) {
            setTimeout(() => {
              this.$router.go(-1)
            }, 2000)
          }
        }
      }
    },
    // 是否支付成功
    async isPaymentSuc() {
      Toast.loading({
        message: '加载中...',
        forbidClick: true,
        duration: 10000
      })
      const result = await payment.orderDetail(this.payParams.orderNo)

      Toast.clear()
      // if (result.code === 0) {
      console.log(result, 'result')
      if (result.message === 'success' && result.data === true) {
        // 订单id没有 只有订单编号
        this.$toast({
          message: '支付成功',
          duration: 2000,
          forbidClick: true,
          icon: 'success'
        })
        setTimeout(() => {
          this.$router.go(-1)
        }, 2000)
      } else {
        this.$toast({
          message: '支付失败',
          duration: 2000,
          forbidClick: true,
          icon: 'success'
        })
        setTimeout(() => {
          this.$router.go(-1)
        }, 2000)
        // }
        // else {
        //   this.$router.replace({
        //     path: '/paymentSuccess',
        //     query: {
        //       status: result.data
        //     }
        //   });
        // }
        // if (result.data === 'failed') {
        //   // this.$toast('支付失败');
        // }
        // if (result.data === 'cancel') {
        //   this.$toast('订单取消');
        // }
      }
    }

  }
}
</script>

<style lang="less" scoped>
.module_paymentHome{
  min-height: 100%;
  position: relative;
  background: #ffffff;
  padding-bottom: 3.125rem;

  .btn-area{
    position: fixed;
    width: 100%;
    left: 0;
    bottom: 0;
    padding: 1rem;

    .btn-submit{
      font-size: 1rem;
      line-height: 1;
      padding: 0.9375rem;
      width: 100%;
      display: block;
      color: #ffffff;
      border: none;
      background: linear-gradient(90deg, #54CC54, #30B654);
      border-radius: 0.3125rem;

      &.disable{
        opacity: .6;
        background: #888888;
      }
    }
  }

  .icon-pay{
    width: 1.75rem;
    height: 1.75rem;
    display: inline-block;
    margin-right: 0.625rem;
  }

  .van-cell{
    padding: 1.5625rem 1.25rem;
  }

  .payment-status{
    padding: 2rem 2.125rem;
    background: #ffffff;
    text-align: center;
    border-bottom: 0.625rem solid #f5f5f5;

    &-icon{
      width: 4.875rem;
      height: 4.875rem;
      margin: 0 auto;
      background: url('~@/assets/images/payment/icon_time.png') no-repeat center top;
      background-size: 100%;
      margin-bottom: 0.5rem;
    }

    &-info{
      font-size: 0.9375rem;
      color: #333333;

      span{
        display: block;
      }

      &-time{
        font-size: 0.75rem;
        color: #666666;
        margin-top: 0.625rem;
      }
    }
  }

  .payment-cont{
    padding: 0.6875rem;
  }

  .payment-product{
    display: flex;
    padding: 0.875rem;
    margin-bottom: 0.875rem;
    border-bottom: 0.0625rem solid #E6E6E6;

    &-poster{
      min-width: 5rem;
      max-width: 5rem;
      height: 5rem;
      border-radius: 0.625rem;
      overflow: hidden;
      margin-right: 0.625rem;

      img{
        width: 100%;
        height: 100%;
      }
    }

    &-info{
      width: 100%;
    }
    &-name{
      font-size: 0.875rem;
      color: #333333;
      line-height: 1.125rem;
      margin-bottom: 1.5rem;
    }

    &-price{
      display: flex;
      justify-content: space-between;
      font-size: 0.6875rem;
      color: #999999;

      span{
        &:first-child{
          color: #EA291F;
          font-size: 1.125rem;
        }
      }
    }

    &-total{
      text-align: right;
      padding: 0 0.875rem;
      margin-bottom: 3.125rem;

      span{
        font-size: 0.8125rem;

        &:last-child{
          color: #EA291F;
          font-size: 1.125rem;
        }
      }
    }
  }

}

</style>