支付模块对接
本章节介绍一下前台如何调用微信和支付宝进行支付
1、微信二维码请求接口
- 效果
1.1 微信请求二维码
接口说明
/pay/getPayCode
- 说明:接口请求微信支付二维码
- 请求方式:get
- 请求参数:buyYears: 年限 (1,2,3),数值类型
- 返回结果:
- buyYears: 购买年限
- payName: 支付订单名称
- payNo: 支付订单号
- qrCode: 支付二维码
- totalAmount: 支付价格
参考代码
<template>
<a-layout style="background: white">
<a-layout-content style="margin: 0 auto; text-align: center; width: 100%">
<div class="vip-upper">
<div class="select-year">
<a-radio-group v-model:value="payData.buyYears" size="large">
<a-radio :value="1">1年</a-radio>
<a-radio :value="2">2年</a-radio>
<a-radio :value="3">3年</a-radio>
</a-radio-group>
</div>
<div class="vip">
<Qrcode v-model:value="qrCodeImgUrl" style="text-align: left" />
<div class="immed-pay">
<a-button class="immed-btn" @click="payClick">获取支付二维码</a-button>
</div>
</div>
</div>
</a-layout-content>
</a-layout>
</template>
<script lang="ts" name="pay">
import { defineComponent, onMounted, ref, unref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import Qrcode from "@/components/Qrcode/src/Qrcode.vue";
import {defHttp} from "@/utils/http/axios";
export default defineComponent({
name: 'pay',
components: {
Qrcode,
},
setup() {
const payData = ref<any>({});
const { createMessage } = useMessage();
//标题
const pageTitle = ref<string>('成为会员');
//微信支付二维码
const qrCodeImgUrl = ref<string>('');
/**
* 立即支付
*/
function payClick() {
let params = { buyYears: unref(payData).buyYears };
let res = defHttp.get({ url: "/pay/getPayCode", params }, { isTransformResponse: false }).then((res) => {
qrCodeImgUrl.value = res.result.qrCode;
payData.value.payNo = res.result.payNo
});
}
return {
payData,
labelCol: {
xs: { span: 24 },
sm: { span: 4 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 18 },
},
payClick,
pageTitle,
qrCodeImgUrl,
};
},
});
</script>
<style lang="less" scoped>
.immed-pay {
margin-bottom: 80px;
text-align:left;
.immed-btn {
width: 200px;
height: 40px;
border-radius: 4px;
background: #286cfb !important;
color: white !important;
}
}
.vip-upper {
width: 800px;
margin: 0 auto;
text-align: center;
}
.buy-version{
text-align: left;
margin-top: 20px;
}
.select-year {
text-align: left;
margin-top: 20px;
:deep(.ant-radio-checked .ant-radio-inner) {
border-color: #ff8533 !important ;
}
:deep(.ant-radio-checked .ant-radio-inner:after) {
background-color: #ff8533;
}
:deep(.ant-radio:hover .ant-radio-inner) {
border-color: #ff8533;
}
:deep(.ant-radio-checked .ant-radio-inner:focus) {
border-color: #ff8533;
}
:deep(.ant-radio) {
transform: scale(1.2) !important;
}
:deep(.ant-radio-wrapper){
font-size: 16px;
}
}
</style>
1.2 微信支付状态查询
接口说明
/pay/queryPayStatus
- 说明:定时查询支付状态,用于提醒用户是否支付成功
- 请求方式:get
- 请求参数:payNo: 请求二维码之后返回的订单号
- 返回结果:
- NOTPAY: 未支付
- PAYERROR: 支付失败
- SUCCESS:支付成功
参考代码
/**
* 立即支付
*/
function payClick() {
let params = { buyYears: unref(payData).buyYears };
let res = defHttp.get({ url: "/pay/getPayCode", params }, { isTransformResponse: false }).then((res) => {
qrCodeImgUrl.value = res.result.qrCode;
payData.value.payNo = res.result.payNo
queryPayStatus();
});
}
const queryPayStatusInterval = ref();
/**
* 查询订单状态
*/
function queryPayStatus() {
//定时查询该订单是否已支付
queryPayStatusInterval.value = setInterval(()=>{
let params = { 'orderNo': payData.value.payNo };
defHttp.get({ url: "/pay/queryPayStatus", params }, { isTransformResponse: false }).then((res) => {
if(res.success){
if(res.result && res.result ==='SUCCESS'){
clearInterval(queryPayStatusInterval.value);
createMessage.success("支付成功");
}
if(res.result && res.result ==='PAYERROR'){
clearInterval(this.queryPayStatusInterval);
createMessage.error("支付失败!");
}
}
}).catch(()=>{
this.$message.success("支付失败,请稍后重试!");
clearInterval(queryPayStatusInterval.value);
})
},2000)
}
onUnmounted(()=>{
clearInterval(queryPayStatusInterval.value);
})
2、支付宝支付请求接口
- 效果
2.1 支付宝支付请求链接
接口说明
/pay/alipay/getAlipayVipForm
- 说明:请求支付宝链接
- 请求方式:get
- 请求参数:buyYears: 年限 (1,2,3),数值类型
- 返回结果:支付宝支付form,前台需要新窗口打开此链接
参考代码
<template>
<a-layout style="background: white">
<a-layout-content style="margin: 0 auto; text-align: center; width: 100%">
<div class="vip-upper">
<div class="select-year">
<a-radio-group v-model:value="payData.buyYears" size="large">
<a-radio :value="1">1年</a-radio>
<a-radio :value="2">2年</a-radio>
<a-radio :value="3">3年</a-radio>
</a-radio-group>
</div>
<div class="vip">
<div class="immed-pay">
<a-button class="immed-btn" @click="payClick">支付宝支付</a-button>
</div>
</div>
</div>
</a-layout-content>
</a-layout>
</template>
<script lang="ts" name="pay">
import {defineComponent, onMounted, onUnmounted, ref, unref} from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import Qrcode from "@/components/Qrcode/src/Qrcode.vue";
import {defHttp} from "@/utils/http/axios";
export default defineComponent({
name: 'pay',
components: {
Qrcode,
},
setup() {
const payData = ref<any>({});
const { createMessage } = useMessage();
//标题
const pageTitle = ref<string>('成为会员');
/**
* 立即支付
*/
function payClick() {
let params = { buyYears: unref(payData).buyYears };
//支付宝支付
let res = defHttp.get({ url: "/pay/alipay/getAlipayVipForm", params }, { isTransformResponse: false }).then((res) => {
const div = document.createElement('div')
/* 此处form就是后台返回接收到的数据 */
div.innerHTML = res.result;
document.body.appendChild(div)
document.forms[0].target = "_blank";
document.forms[0].submit();
document.body.removeChild(div);
});
}
return {
payData,
labelCol: {
xs: { span: 24 },
sm: { span: 4 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 18 },
},
payClick,
pageTitle,
};
},
});
</script>
<style lang="less" scoped>
.immed-pay {
margin-top: 20px;
margin-bottom: 80px;
text-align:left;
.immed-btn {
width: 200px;
height: 40px;
border-radius: 4px;
background: #286cfb !important;
color: white !important;
}
}
.vip-upper {
width: 800px;
margin: 0 auto;
text-align: center;
}
.buy-version{
text-align: left;
margin-top: 20px;
}
.select-year {
text-align: left;
margin-top: 20px;
:deep(.ant-radio-checked .ant-radio-inner) {
border-color: #ff8533 !important ;
}
:deep(.ant-radio-checked .ant-radio-inner:after) {
background-color: #ff8533;
}
:deep(.ant-radio:hover .ant-radio-inner) {
border-color: #ff8533;
}
:deep(.ant-radio-checked .ant-radio-inner:focus) {
border-color: #ff8533;
}
:deep(.ant-radio) {
transform: scale(1.2) !important;
}
:deep(.ant-radio-wrapper){
font-size: 16px;
}
}
</style>