效果图:
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>