vue 在微信公众号里使用支付宝支付(h5支付宝支付)
需求:在微信公众号里面支持支付宝支付。
思路:微信是不能直接调用支付宝的,所以我们需要使用一个中间页提示用户在浏览器中打开,然后进行支付宝网页或APP中支付。
步骤:
- 微信中点击支付宝支付时,跳转中间引导页(引导用户在浏览器中打开去唤起支付宝)。
- 浏览器中打开支付宝,唤起支付后进行支付。
- 支付成功后根据后台配置的路径页面跳转,根据支付宝返回的url里面的 out_trade_no去查询支付状态(根据自己具体业务需求,比如我这里跳转的是支付成功页,判断url是否有out_trade_no提示用户是否支付完成,然后根据out_trade_no去查单)。
后台返回接收到form表单数据
流程图:
|
|
|
|
|
|
|
|
|
|
代码:
点击支付宝支付后,下单成功然后进行支付时:
let ua = navigator.userAgent.toLowerCase();
if (ua.match(/MicroMessenger/i) == "micromessenger"){//微信游览器
//跳转中间引导页。参数:ordersId:去中间页使用ordersId请求支付,token:跳转游览器打开时(未登录状态)保存token请求支付接口,jumpBack标识支付后需要返回微信
uni.redirectTo({
url: '/pages/order/toAlipay?ordersId=' +ordersId + "&token=" + uni.getStorageSync("token") + "&jumpBack=WeChat"
});
}else{//普通游览器直接支付
const div = document.createElement('div')
div.innerHTML = res.data //此处form就是后台返回接收到的数据
document.body.appendChild(div)
document.forms[0].submit()
}
引导页(/pages/order/toAlipay.vue)
<template>
<view class="shareit" v-if="is_WeChat">
<image class="arrow" src="@/static/my/arrowhead.png"></image>
<view class="follow">支付宝支付请使用游览器进行支付,<br />请在菜单中选择游览器打开</view>
</view>
</template>
<script>
import { ref, reactive, onMounted } from 'vue'; // 引入需要的
import { getCurrentInstance } from 'vue'
import { payAPI, getOrderCheckListAPI } from '@/api/order'
export default {
setup(props,context){
const { proxy } = getCurrentInstance();
const is_WeChat = ref(false)
onMounted(() => {
console.log(props.ordersId)
if(props.ordersId&&props.token){
let ua = navigator.userAgent.toLowerCase();
if (ua.match(/MicroMessenger/i) == "micromessenger"){//微信游览器
is_WeChat.value = true;//显示引导动作
}else{
is_WeChat.value = false;//不显示引导动作
proxy.$queue.showLoading('支付中...');
uni.setStorageSync("token", props.token)
uni.setStorageSync("jumpBack", props.jumpBack);//需要跳回微信
goToPay(props.ordersId);//去支付
}
}else{
uni.showModal({
title: '',
content: '参数错误,无ordersId或token!',
showCancel: false,
success: function (res) {
if (res.confirm) {
console.log('用户点击确定');
uni.removeStorageSync("token")
uni.removeStorageSync("jumpBack")
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
}
})
const goToPay = (ordersId) => {//支付
let para = {
ordersId :ordersId
}
payAPI(para).then((res) => {//订单支付
uni.hideLoading();
const div = document.createElement('div')
div.innerHTML = res.data //此处form就是后台返回接收到的数据
document.body.appendChild(div)
document.forms[0].submit()
}).catch((err) => {
uni.hideLoading();
goToOrderDetails(ordersId);//支付失败直接跳转订单详情
console.log(err);
});
}
const orderPolling=(ordersId)=>{//订单轮询
proxy.$queue.showLoading('支付信息查询中..');
var timerNum = 0;
var timer = setInterval(function(){//最多遍历10次查单
if(timerNum === 10){
uni.hideLoading();
proxy.$queue.showToast("稍后进入订单详情页核实订单状态,不要重复发起支付");
clearInterval(timer);
goToOrderDetails(ordersId);//跳转订单详情
}else{
timerNum += 1;
getOrderCheckList(ordersId,timer);//支付成功后进行轮询查单
}
},1000);
}
const getOrderCheckList=(ordersId,timer)=>{//支付成功后进行轮询查单
let params = {
ordersId:ordersId
}
getOrderCheckListAPI(params).then((res) => {
if(res.data){
if(res.data.payStatus==1){
clearInterval(timer);//清除定时器
uni.hideLoading();
proxy.$queue.showToast("支付成功");
goToOrderPay(ordersId);//跳转订单成功页
}
}
}).catch((err) => {
console.log(err);
});
}
const goToOrderDetails =(ordersId)=>{//跳转订单详情
uni.redirectTo({
url: '/pages/order/orderDetails?ordersId=' +ordersId
});
}
const goToOrderPay =(ordersId)=>{//跳转订单成功页
uni.redirectTo({
url: '/pages/order/pay?ordersId=' +ordersId
});
}
return {
is_WeChat,
goToPay,
orderPolling,
getOrderCheckList,
goToOrderDetails,
goToOrderPay
}
},
onLoad(e){
let ua = navigator.userAgent.toLowerCase();
if (ua.match(/MicroMessenger/i) == "micromessenger"){//微信游览器
uni.setStorageSync("AliPayOrdersId", e.ordersId);//缓存ordersId,方便后面支付成功后订单轮询查单
}
},
onShow(){
//#ifdef H5
let ua = navigator.userAgent.toLowerCase();
if (ua.match(/MicroMessenger/i) == "micromessenger"){//微信游览器
let that = this
if(uni.getStorageSync("AliPayOrdersId")){//支付成功后跳回微信时
that.is_WeChat = false;
let ordersId = uni.getStorageSync("AliPayOrdersId");
uni.removeStorageSync("AliPayOrdersId");
that.orderPolling(ordersId);//订单轮询
}
}
//#endif
}
}
</script>
<style lang="scss">
.shareit {
-webkit-user-select: none;
position: fixed;
width: 100%;
height: 100vh;
background: rgba(0, 0, 0, 0.6);
text-align: center;
top: 0;
left: 0;
z-index: 999;
}
.shareit img {
max-width: 100%;
}
.arrow {
width: 200rpx;
height: 300rpx;
position: absolute;
right: 5%;
top: 1%;
}
.follow {
margin-right: 120rpx;
margin-left: 60rpx;
width: 90%;
// height: 100rpx;
line-height: 60rpx;
// text-align: left;
text-decoration: none;
font-size: 36rpx;
color: white;
float: left;
margin-top: 360rpx;
}
</style>
支付成功页(/pages/order/pay.vue)
<template>
<view class="container">
<view v-if="!jumpBack">
<view class="title">支付成功</view>
<view class="title2">您可随时在「订单」中查看订单详情</view>
<view><button class="btn gradient-btn" @click="goToOrderDetails">查看订单详情</button></view>
</view>
<view v-if="jumpBack">
<view class="title">支付成功</view>
<view class="title2">请您手动退回微信!</view>
</view>
</view>
</template>
<script>
import { ref,reactive, onMounted } from 'vue'; // 引入需要的
import { getCurrentInstance } from 'vue'
import { getOrderCheckListAPI } from '@/api/order'
export default {
setup(props){
const { proxy } = getCurrentInstance();
const jumpBack = ref(false)
onMounted(() => {
// console.log("获取到的参数", props);
console.log(props)
})
const goToOrderDetails = () => {
if(props.out_trade_no){//h5支付宝回调
uni.redirectTo({
url: '/pages/order/orderDetails?ordersNo=' + props.out_trade_no
});
}else{
uni.redirectTo({
url: '/pages/order/orderDetails?ordersId=' + props.ordersId
});
}
}
const getOrderCheckListAli=(ordersNo,timer)=>{//支付成功后进行轮询查单
let params = {
ordersNo:ordersNo
}
getOrderCheckListAPI(params).then((res) => {
if(res.data){
if(res.data.payStatus==1){
clearInterval(timer);//清除定时器
uni.hideLoading();
proxy.$queue.showToast("支付成功");
}
}
}).catch((err) => {
console.log(err);
});
}
return {
jumpBack,
goToOrderDetails,
getOrderCheckListAli
}
},
onLoad(e){
},
onShow(){
//#ifdef H5
let that = this
if(this.$queue.getUrlCode().out_trade_no&&uni.getStorageSync("jumpBack")=="WeChat"){//微信里使用支付宝支付
that.jumpBack = true
uni.showModal({
title: '提示',
content: '支付成功,请您手动退回微信!',
showCancel: false,
success: function (res) {
if (res.confirm) {
console.log('用户点击确定');
uni.removeStorageSync("token");
uni.removeStorageSync("jumpBack");
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
}else if(this.$queue.getUrlCode().out_trade_no){//h5普通游览器支付宝支付回调
let ordersNo = this.$queue.getUrlCode().out_trade_no
uni.showModal({
title: '',
content: '请确认支付宝支付是否已完成',
confirmText:"已完成支付",
cancelText:"支付有问题,重新下单",
confirmColor:"#2FA15E",
success: function (res) {
if (res.confirm) {
that.$queue.showLoading('支付信息查询中..');
var timerNum = 0;
var timer = setInterval(function(){
if(timerNum === 10){
uni.hideLoading();
that.$queue.showToast("支付信息查询失败,请稍后刷新重试");
clearInterval(timer);
}else{
timerNum += 1;
that.getOrderCheckListAli(ordersNo,timer);//支付成功后进行轮询查单
}
},1000);
} else if (res.cancel) {
// console.log('用户点击取消');
}
}
});
}
//#endif
},
}
</script>
<style lang="scss">
.container{
height: 800rpx;
display: flex;
width: 100%;
align-items: center;
justify-content: center;
}
.title{
font-size: 48rpx;
font-weight: 600;
color: $my-text-color;
line-height: 64rpx;
text-align: center;
}
.title2{
font-size: 28rpx;
font-weight: 400;
color: $my-text-color;
line-height: 36rpx;
margin: 24rpx 0 48rpx 0;
}
.btn{
width: 252rpx;
height: 72rpx;
background: $my-btn-bg-color;
border-radius: 36rpx;
color: $my-text-color4;
font-weight: 500;
font-size: 28rpx;
}
</style>