效果图:

custom-payment : 在生成预付订单之后页面中需要弹出一个弹层,弹层中展示的内容为支付方式(渠道),由用户选择一种支付方式进行支付。
该弹层组件是以扩展组件 uni-popup 为核心的,关于 uni-popup 组件的使用文档请查看这里,这里只介绍我们用到的部分:
- type属性,指定弹层出现的位置
- is-mask-click是否允许点击蒙层关闭弹层
- maskClick点击弹层时触发事件
custom-payment 代码:
<!-- components/custom-payment/custom-payment.vue -->
<script lang="ts" setup>
import { ref } from 'vue'
// 在线支付弹层
const paymentPopup = ref()
// 打开弹层
const open = () => {
  paymentPopup.value.open()
}
// 关闭弹层
const close = () => {
  paymentPopup.value.close()
}
// 2.把方法暴露出去给外部使用
defineExpose({
  open,
  close
})
//3. 处理选择支付渠道
const paymentMethod = ref()
const paymentChannel = [
  {
    title: '微信支付',
    thumb: '/static/images/wechatpay-icon.png',
  },
  {
    title: '支付宝支付',
    thumb: '/static/images/alipay-icon.png',
  },
]
const changePayment = (index: number) => {
  paymentMethod.value = index
}
const emit = defineEmits<{
  (e: 'close'): void
  (e: 'confirm', index: number): void
}>()
</script>
<template>
  <uni-popup :is-mask-click="false" ref="paymentPopup" type="bottom" @maskClick="emit('close')">
    <view class="payment-container">
      <view class="payment-header">
        <text class="title">选择支付方式</text>
        <uni-icons class="uni-icons-close" size="18" color="#333" type="closeempty" @click="emit('close')" />
      </view>
      <view class="order-amount">¥ {{ amount.toFixed(2) }} </view>
      <uni-list :border="false">
        <uni-list-item clickable v-for="(item, index) in paymentChannel" :key="index" :title="item.title"
          :thumb="item.thumb" @click="changePayment(index)">
          <template #footer>
            <uni-icons v-if="paymentMethod === index" size="26" color="#16C2A3" type="checkbox-filled" />
            <uni-icons v-else size="26" color="#d1d1d1" type="circle" />
          </template>
        </uni-list-item>
      </uni-list>
      <button class="uni-button" @click="emit('confirm', paymentMethod)">立即支付</button>
    </view>
  </uni-popup>
</template>
<style lang="scss">
.payment-container {
  min-height: 400rpx;
  border-radius: 30rpx 30rpx 0 0;
  background-color: #fff;
  padding: 10rpx 30rpx 40rpx;
  .payment-header {
    height: 88rpx;
    line-height: 88rpx;
    text-align: center;
    margin-bottom: 20rpx;
    font-size: 32rpx;
    color: #333;
    position: relative;
  }
  .uni-icons-close {
    position: absolute;
    top: 2rpx;
    right: 0;
  }
  .order-amount {
    padding: 10rpx 0 10rpx;
    text-align: center;
    font-size: 40rpx;
    color: #333;
  }
  :deep(.uni-list-item__container) {
    padding: 40rpx 0 !important;
  }
  :deep(.uni-list-item--hover) {
    background-color: #fff !important;
  }
  :deep(.uni-list-item__icon) {
    margin-right: 0;
  }
  .uni-button {
    margin-top: 40rpx;
  }
}
</style>
支付流程
一般的支付流程如下:
- 第三方支付提供的开发者平台注册账号、创建应用、申请认证用的证书或者 key
- 前端获取待支付订单ID、支付金额、支付渠道等数据,传递给后端接口
- 后端接口在获取前端传递的数据后,根据支付平台提供文档与支付平台接口进行对接
- 后端与支付平台对接成功后,后端将支付信息再回传给前端
- 前端根据回传的信息引导用户进行支付
在整个支付的过程中前端的任务仍然是调用接口(与调用普通的接口几乎没有差别),真正完成支付任务的其实是后端接口。
支付宝支付
- 自行注册支付宝支付账号
- 在企业中开发时需要创建应用,然而创建应用后还需要一些资质才可以进行支付,无法满足这些资质,好在支付定平台提供了沙箱环境,沙箱环境是协助开发者进行接口开发及主要功能联调的模拟环境,目前仅支持网页/移动应用和小程序两种应用类型。
- 在正式应用或沙箱应用中获取到商家账号、认证证书、APPID、回调地址等。
- 上述的操作其实都是由后端来操作的,这里只是让大家了解一下支付管理后台的相关信息。
父组件使用组件:
 <script lang="ts" setup>
 // 弹层选择支付渠道
  customPaymentRef.value.open()
//  处理支付渠道组件的自定义事件
const onPaymentConfirm = async (index: number) => {
  if (index === undefined) return uni.showToast({ title: '请选择支付方式', icon: 'none' })
  if (index === 0) return uni.showToast({ title: '暂不支持微信支付', icon: 'none' })
  //  调用后端接口
  const { payUrl } = await orderPayApi({
    orderId: orderId.value,
    paymentMethod: index + '',
    payCallback: 返回地址
  })
  // #ifdef H5
  window.location.href = payUrl
  // #endif
  // #ifdef MP-WEIXIN
  // 引导用户支付(wx.requestPayment 小程序)
  // wx.requestPayment({
  //   // 4 个参数
  // })
  // #endif
}
//  关闭支付弹层
const onPaymentClose = async () => {
  const res = await uni.showModal({
    title: '关闭支付',
    content: '取消支付将无法获得医生回复,医生接诊名额有限,是否确认关闭?',
    cancelText: '仍要关闭',
    cancelColor: '#848484',
    confirmText: '继续支付',
    confirmColor: '#16C2A3',
  })
  if (!res.confirm) {
    customPaymentRef.value.close()
    uni.reLaunch({
      url: '/pages/index/index',
    })
  }
}
</script>
<template>
<!-- 支付渠道弹层 -->
  <custom-payment   ref="customPaymentRef"
    @close="onPaymentClose" @confirm="onPaymentConfirm" />
</template>


















