feat:支付

This commit is contained in:
dzc committed 2025-12-11 11:19:48 +08:00
1 parent 056594e809
commit 184ba62d6f
6 files changed
+621 -186

No files matched your search

+7
View File
@@ -209,6 +209,13 @@
{
"root": "pages/profile",
"pages": [
{
"path": "pay-result",
"style": {
"navigationBarTitleText": "支付结果",
"navigationStyle": "custom"
}
},
{
"path": "userinfo",
"style": {
+134 -101
View File
@@ -10,8 +10,7 @@
<scroll-view style="height: calc(100dvh - 88px)" scroll-y>
<view
class="mx-4 p-4 rounded-2 bg-gradient-to-b from-#111 to-#222 b-4 b-solid b-t-#D29E52/60 b-l-#D29E52/40 b-r-#D29E52/40 b-b-#D29E52/20"
>
class="mx-4 p-4 rounded-2 bg-gradient-to-b from-#111 to-#222 b-4 b-solid b-t-#D29E52/60 b-l-#D29E52/40 b-r-#D29E52/40 b-b-#D29E52/20">
<view class="text-color-theme-dark font-900 font-italic text-xl mb-1">VIP</view>
<view class="flex-col-center mb-4">
<view class="text-gray mb-2 text-xl font-900 font-italic tracking-1.5">
@@ -25,20 +24,12 @@
<view class="mt-3 px-4">
<scroll-view scroll-x class="w-full" :show-scrollbar="false">
<view class="flex">
<view
v-for="item in openTypeList"
:key="item.id"
class="mr-3 ml-1 my-1"
@click="curOpenTypeId = item.id"
>
<view
class="w-220rpx rounded-3 flex-col-center transition-all duration-200"
:class="[
curOpenTypeId === item.id
? 'bg-#111 text-white b-3 b-solid b-#D29E52/60'
: 'b-3 b-solid b-#333',
]"
>
<view v-for="item in openTypeList" :key="item.id" class="mr-3 ml-1 my-1" @click="curOpenTypeId = item.id">
<view class="w-220rpx rounded-3 flex-col-center transition-all duration-200" :class="[
curOpenTypeId === item.id
? 'bg-#111 text-white b-3 b-solid b-#D29E52/60'
: 'b-3 b-solid b-#333',
]">
<view class="mt-2 text-sm text-#ffffff">{{ item.title }}</view>
<view class="mt-1 text-lg font-900 text-color-theme-dark">
¥{{ fen2yuan(item.preferentialPrice) }}
@@ -59,18 +50,14 @@
<view class="flex justify-between gap-3">
<view
class="flex-1 rounded-full flex-row-center px-4 py-2 b-3 b-solid b-#222 bg-#333 transition-all duration-200"
:style="{ borderColor: payMethod === 'alipay' ? '#D29E52' : '' }"
@click="payMethod = 'alipay'"
>
:style="{ borderColor: payMethod === 'alipay' ? '#D29E52' : '' }" @click="payMethod = 'alipay'">
<image class="size-40rpx mr-2" src="@/static/alipay.png" mode="aspectFill" />
<text>支付宝</text>
</view>
<view
class="flex-1 rounded-full flex-row-center px-4 py-2 b-3 b-solid b-#222 bg-#333 transition-all duration-200"
:style="{ borderColor: payMethod === 'wechat' ? '#D29E52' : '' }"
@click="payMethod = 'wechat'"
>
:style="{ borderColor: payMethod === 'wechat' ? '#D29E52' : '' }" @click="payMethod = 'wechat'">
<image class="size-40rpx mr-2" src="@/static/weixin.png" mode="aspectFill" />
<text>微信支付</text>
</view>
@@ -83,21 +70,15 @@
<text class="text-color-theme-dark">《荷塘月色会员协议》</text>
</view>
<view
v-if="openTypeList.length"
<view v-if="openTypeList.length"
class="mt-4 w-2/3 mx-auto py-2 text-center rounded-full bg-color-theme-dark text-black text-sm active:bg-color-theme"
@click="handleOpenVip"
>
@click="handleOpenVip">
立即开通VIP
</view>
<view class="mt-6 px-4">
<view class="grid grid-cols-3 gap-2">
<view
v-for="(item, index) in benefits"
:key="index"
class="p-2 flex flex-col items-center"
>
<view v-for="(item, index) in benefits" :key="index" class="p-2 flex flex-col items-center">
<view class="mb-1 size-120rpx rounded-full bg-#333 text-center line-height-120rpx">
<uni-icons :type="item.icon" size="32" color="#d29e52"></uni-icons>
</view>
@@ -112,82 +93,134 @@
</template>
<script setup lang="ts">
import { computed, ref } from 'vue';
// @ts-ignore
import { fen2yuan } from '@/sheep/hooks/useGoods';
import { onLoad } from '@dcloudio/uni-app';
import RecentApi from '@/sheep/api/member/recent';
import { useMessage } from '@/uni_modules/wot-design-uni';
// @ts-ignore
import $store from '@/sheep/store';
// @ts-ignore
import PayOrderApi from '@/sheep/api/pay/order';
// @ts-ignore
import sheep from '@/sheep';
import { computed, ref } from 'vue';
// @ts-ignore
import { fen2yuan } from '@/sheep/hooks/useGoods';
import { onLoad, onShow } from '@dcloudio/uni-app';
import RecentApi from '@/sheep/api/member/recent';
import { useMessage } from '@/uni_modules/wot-design-uni';
// @ts-ignore
import $store from '@/sheep/store';
// @ts-ignore
import PayOrderApi from '@/sheep/api/pay/order';
// @ts-ignore
import sheep from '@/sheep';
import { jumpToWechatMiniProgram } from '@/sheep/util/wechat-tool';
const messageBox = useMessage();
const messageBox = useMessage();
interface OpenTypeItem {
id: number;
title: string;
icon: string;
preferentialPrice: number;
originalPrice: number;
duration: number;
status: string;
isHot: boolean;
sort: number;
createTime: number;
interface OpenTypeItem {
id: number;
title: string;
icon: string;
preferentialPrice: number;
originalPrice: number;
duration: number;
status: string;
isHot: boolean;
sort: number;
createTime: number;
}
const benefits: any = [
{ icon: 'chat-filled', desc: '解锁微信', subDesc: '每天10个' },
{ icon: 'chatboxes-filled', desc: '无限畅聊', subDesc: '每天10个' },
{ icon: 'vip-filled', desc: '尊贵身份', subDesc: '专属标识' },
{ icon: 'locked-filled', desc: '个人身份', subDesc: '安全保密' },
{ icon: 'medal-filled', desc: '更多特权', subDesc: '敬请期待' },
];
const payMethodMap = [
{
title: "支付宝",
payment: '',
key: 'alipay'
},
{
title: "微信支付",
payment: 'wx_lite',
key: 'wechat'
}
]
const payMethod = ref<'alipay' | 'wechat'>('alipay'); // 支付方式:alipay / wechat
const openTypeList = ref<OpenTypeItem[]>([]); // 会员类型列表
const curOpenTypeId = ref<number>(); // 当前选择的会员类型id
const currentOpenType = computed<OpenTypeItem | undefined>(() =>
openTypeList.value?.find((item) => item.id === curOpenTypeId.value),
); // 当前选择的会员类型
const benefits: any = [
{ icon: 'chat-filled', desc: '解锁微信', subDesc: '每天10个' },
{ icon: 'chatboxes-filled', desc: '无限畅聊', subDesc: '每天10个' },
{ icon: 'vip-filled', desc: '尊贵身份', subDesc: '专属标识' },
{ icon: 'locked-filled', desc: '个人身份', subDesc: '安全保密' },
{ icon: 'medal-filled', desc: '更多特权', subDesc: '敬请期待' },
];
const payMethod = ref<'alipay' | 'wechat'>('alipay'); // 支付方式:alipay / wechat
const openTypeList = ref<OpenTypeItem[]>([]); // 会员类型列表
const curOpenTypeId = ref<number>(); // 当前选择的会员类型id
const currentOpenType = computed<OpenTypeItem | undefined>(() =>
openTypeList.value?.find((item) => item.id === curOpenTypeId.value),
); // 当前选择的会员类型
onLoad(async () => {
const { data = null } = await RecentApi.getMemberOpenTypeList();
openTypeList.value = data ?? [];
if (openTypeList.value && openTypeList.value[0]) {
curOpenTypeId.value = openTypeList.value[0].id;
onLoad(async (params) => {
if (params) {
if (params.openTypeId && params.payMethod) {
payMethod.value = params.payMethod
disposeWechatPay(params.openTypeId)
}
});
}
});
onShow(async () => {
const { data = null } = await RecentApi.getMemberOpenTypeList();
openTypeList.value = data ?? [];
if (openTypeList.value && openTypeList.value[0]) {
curOpenTypeId.value = openTypeList.value[0].id;
}
})
// 开通会员
const handleOpenVip = () => {
if (!curOpenTypeId.value || !currentOpenType.value?.id)
return uni.showToast({ title: '请选择会员类型', icon: 'none' });
// 开通会员
const handleOpenVip = () => {
if (!curOpenTypeId.value || !currentOpenType.value?.id) {
uni.showToast({ title: '请选择会员类型', icon: 'none' });
return
}
const payMethodItem = payMethodMap.find((item) => item.key === payMethod.value);
if (!payMethodItem) {
uni.showToast({ title: '请选择支付方式', icon: 'none' });
return
}
if (!payMethodItem.payment) {
uni.showToast({ title: `不支持${payMethodItem.title}支付`, icon: 'none' });
return
}
messageBox
.confirm({
msg: '确认开通?',
title: '提示',
})
.then(async () => {
// #ifdef MP-WEIXIN
disposeWechatPay(curOpenTypeId.value)
// #endif
// #ifndef MP-WEIXIN
jumpToWechatPage()
// #endif
})
.catch(() => { });
};
messageBox
.confirm({
msg: '确认开通?',
title: '提示',
})
.then(async () => {
const { code, data } = await RecentApi.memberOpenTypePay({
openTypeId: curOpenTypeId.value,
});
if (code !== 0) return uni.showToast({ title: '创建订单失败', icon: 'fail' });
// 处理微信支付
const disposeWechatPay = async (openTypeId: any) => {
uni.showLoading({ title: '支付中...', mask: true });
try {
const { code, data } = await RecentApi.memberOpenTypePay({
openTypeId: openTypeId,
});
console.log("开通vipId:", data);
if (code !== 0) {
uni.showToast({ title: '创建订单失败', icon: 'none' });
throw new Error('创建订单失败');
}
sheep.$platform.pay(payMethod.value, 'recharge', data);
// 更新用户信息
$store('user').getInfo();
uni.showToast({ title: '支付成功', icon: 'success' });
} catch (error) {
console.error("|处理微信支付|,意外的错误error:", error);
}
}
// const { data } = await PayOrderApi.getOrder(data, true);
sheep.$platform.pay(payMethod.value, 'recharge', data.payOrderId);
// uni.showToast({ title: '开通成功', icon: 'success' });
$store('user').getInfo();
// setTimeout(() => {
// uni.navigateBack();
// }, 500);
})
.catch(() => {});
};
// 跳转到微信小程序
const jumpToWechatPage = () => {
jumpToWechatMiniProgram("openVip", {
openTypeId: curOpenTypeId.value,
payMethod: payMethod.value
})
}
</script>
+313
View File
@@ -0,0 +1,313 @@
<!-- 支付结果页面 -->
<template>
<wd-config-provider theme="dark">
<wd-navbar title="支付结果" safeAreaInsetTop :bordered="false">
<template #left>
<navigator open-type="navigateBack" hover-class="navigator-hover">
<uni-icons type="back" size="30" color="#D29E52"></uni-icons>
</navigator>
</template>
</wd-navbar>
<view class="flex-col justify-center items-center pay-result-box">
<!-- 信息展示 -->
<view class="pay-waiting m-b-30rpx" v-if="payResult === 'waiting'" />
<view class="tip-text m-b-30rpx" v-if="payResult === 'success'">支付成功</view>
<view class="tip-text m-b-30rpx" v-if="payResult === 'failed'">支付失败</view>
<view class="tip-text m-b-30rpx" v-if="payResult === 'closed'">该订单已关闭</view>
<view class="tip-text m-b-30rpx" v-if="payResult === 'waiting'">正在查询支付结果...</view>
<view class="pay-total-num ss-flex" v-if="payResult === 'success'">
<view>¥{{ fen2yuan(state.orderInfo.price) }}</view>
</view>
<!-- 操作区 -->
<view class="btn-box ss-flex ss-row-center ss-m-t-50">
<view
class="m-x-100rpx bg-color-theme-dark active_cl_bg-color-theme text-base text-center px-80rpx py-12rpx rounded-full"
@tap="backHome">
返回首页
</view>
</view>
<!-- #ifdef MP -->
<view class="subscribe-box ss-flex ss-m-t-44" v-if="showSubscribeBtn && state.orderType === 'goods'">
<image class="subscribe-img" :src="sheep.$url.static('/static/img/shop/order/cargo.png')" />
<view class="subscribe-title ss-m-r-48 ss-m-l-16">获取实时发货信息与订单状态</view>
<view class="subscribe-start" @tap="subscribeMessage">立即订阅</view>
</view>
<!-- #endif -->
</view>
</wd-config-provider>
</template>
<script setup>
import { onHide, onLoad, onShow } from '@dcloudio/uni-app';
import { computed, reactive, ref } from 'vue';
import { isEmpty } from 'lodash-es';
import sheep from '@/sheep';
import PayOrderApi from '@/sheep/api/pay/order';
import { fen2yuan } from '@/sheep/hooks/useGoods';
import OrderApi from '@/sheep/api/trade/order';
import { WxaSubscribeTemplate } from '@/sheep/helper/const';
const state = reactive({
id: 0, // 支付单号
orderType: 'goods', // 订单类型
result: 'unpaid', // 支付状态
orderInfo: {}, // 支付订单信息
tradeOrder: {}, // 商品订单信息,只有在 orderType 为 goods 才会请求。目的:【我的拼团】按钮的展示
counter: 0, // 获取结果次数
});
// 支付结果 result => payResult
const payResult = computed(() => {
if (state.result === 'unpaid') {
return 'waiting';
}
if (state.result === 'paid') {
return 'success';
}
if (state.result === 'failed') {
return 'failed';
}
if (state.result === 'closed') {
return 'closed';
}
});
// 返回首页
function backHome() {
uni.switchTab({ url: "/pages/wechat-tabbar/index" })
}
function showRepayModal() {
if (state.result !== 'failed') return;
uni.showModal({
title: '确认支付',
content: '未检测到您的支付结果,请确认您是否已经支付完成?',
cancelText: '取消',
confirmText: '我已支付',
success: function (res) {
if (res.confirm) {
state.counter = 0;
setTimeout(() => {
getOrderInfo(state.id);
}, 100);
}
},
});
}
// 获得订单信息
async function getOrderInfo(id) {
state.counter++;
// 1. 加载订单信息
const { data, code } = await PayOrderApi.getOrder(id, true);
if (code === 0) {
state.orderInfo = data;
if (!state.orderInfo || state.orderInfo.status === 30) {
// 支付关闭
state.result = 'closed';
return;
}
if (state.orderInfo.status !== 0) {
// 非待支付,可能是已支付,可能是已退款
state.result = 'paid';
// #ifdef MP
uni.showModal({
title: '支付结果',
showCancel: false, // 不要取消按钮
content: '支付成功',
success: () => {
// 订阅只能由用户主动触发,只能包一层 showModal 诱导用户点击
autoSubscribeMessage();
},
});
// #endif
// 特殊:获得商品订单信息
if (state.orderType === 'goods') {
const { data, code } = await OrderApi.getOrderDetail(
state.orderInfo.merchantOrderId,
true,
);
if (code === 0) {
state.tradeOrder = data;
}
}
return;
}
}
// 2.1 情况三一:未支付,且轮询次数小于五次,则继续轮询
if (state.counter < 5 && state.result === 'unpaid') {
setTimeout(() => {
getOrderInfo(id);
}, 2000);
}
// 2.2 情况二:超过五次检测才判断为支付失败
if (state.counter >= 5) {
state.result = 'failed';
showRepayModal();
}
}
// #ifdef MP
const showSubscribeBtn = ref(false); // 默认隐藏
const SUBSCRIBE_BTN_STATUS_STORAGE_KEY = 'subscribe_btn_status';
function subscribeMessage() {
if (state.orderType !== 'goods') {
return;
}
const event = [WxaSubscribeTemplate.TRADE_ORDER_DELIVERY];
if (state.tradeOrder.type === 3) {
event.push(WxaSubscribeTemplate.PROMOTION_COMBINATION_SUCCESS);
}
sheep.$platform.useProvider('wechat').subscribeMessage(event, () => {
// 订阅后记录一下订阅状态
uni.removeStorageSync(SUBSCRIBE_BTN_STATUS_STORAGE_KEY);
uni.setStorageSync(SUBSCRIBE_BTN_STATUS_STORAGE_KEY, '已订阅');
// 隐藏订阅按钮
showSubscribeBtn.value = false;
});
}
async function autoSubscribeMessage() {
// 1. 校验是否手动订阅过
const subscribeBtnStatus = uni.getStorageSync(SUBSCRIBE_BTN_STATUS_STORAGE_KEY);
if (!subscribeBtnStatus) {
showSubscribeBtn.value = true;
return;
}
// 2. 订阅消息
subscribeMessage();
}
// #endif
onLoad(async (options) => {
// 支付订单号
if (options.id) {
state.id = options.id;
}
// 订单类型
if (options.orderType) {
state.orderType = options.orderType;
}
// 支付结果传值过来是失败,则直接显示失败界面
if (options.payState === 'fail') {
state.result = 'failed';
} else {
// 轮询五次检测订单支付结果
await getOrderInfo(state.id);
}
});
onShow(() => {
if (isEmpty(state.orderInfo)) {
return;
}
getOrderInfo(state.id);
});
onHide(() => {
state.result = 'unpaid';
state.counter = 0;
});
</script>
<style lang="scss" scoped>
@keyframes rotation {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.score-img {
width: 36rpx;
height: 36rpx;
margin: 0 4rpx;
}
.pay-result-box {
padding: 60rpx 0;
.pay-waiting {
margin-top: 20rpx;
width: 60rpx;
height: 60rpx;
border: 10rpx solid rgb(233, 231, 231);
border-bottom-color: rgb(204, 204, 204);
border-radius: 50%;
display: inline-block;
// -webkit-animation: rotation 1s linear infinite;
animation: rotation 1s linear infinite;
}
.pay-img {
width: 130rpx;
height: 130rpx;
}
.tip-text {
font-size: 30rpx;
font-weight: bold;
color: #D29E52;
}
.pay-total-num {
font-size: 36rpx;
font-weight: 500;
color: #D29E52;
font-family: OPPOSANS;
}
.btn-box {
width: 100%;
.back-btn {
width: 190rpx;
height: 70rpx;
font-size: 28rpx;
border: 2rpx solid #dfdfdf;
border-radius: 35rpx;
font-weight: 400;
color: #595959;
}
.check-btn {
width: 190rpx;
height: 70rpx;
font-size: 28rpx;
border: 2rpx solid #dfdfdf;
border-radius: 35rpx;
font-weight: 400;
color: #595959;
margin-left: 32rpx;
}
}
.subscribe-box {
.subscribe-img {
width: 44rpx;
height: 44rpx;
}
.subscribe-title {
font-weight: 500;
font-size: 32rpx;
line-height: 36rpx;
color: #434343;
}
.subscribe-start {
color: var(--ui-BG-Main);
font-weight: 700;
font-size: 32rpx;
line-height: 36rpx;
}
}
}
</style>
+112 -74
View File
@@ -7,14 +7,8 @@
</navigator>
</template>
<template #right>
<navigator
url="/pages/profile/recharge-record"
open-type="navigate"
hover-class="navigator-hover"
>
<view
class="flex items-center rounded-full h-44rpx bg-color-theme py-1 px-2 text-black text-sm"
>
<navigator url="/pages/profile/recharge-record" open-type="navigate" hover-class="navigator-hover">
<view class="flex items-center rounded-full h-44rpx bg-color-theme py-1 px-2 text-black text-sm">
历史记录
</view>
</navigator>
@@ -23,8 +17,7 @@
<scroll-view style="height: calc(100dvh - 88px)" scroll-y>
<view
class="mx-4 p-4 rounded-2 bg-gradient-to-b from-#111 to-#222 b-4 b-solid b-t-#D29E52/60 b-l-#D29E52/40 b-r-#D29E52/40 b-b-#D29E52/20"
>
class="mx-4 p-4 rounded-2 bg-gradient-to-b from-#111 to-#222 b-4 b-solid b-t-#D29E52/60 b-l-#D29E52/40 b-r-#D29E52/40 b-b-#D29E52/20">
<view class="text-color-theme-dark font-900 font-italic text-xl mb-1">VIP</view>
<view class="flex-col-center mb-4">
<view class="text-gray mb-2 text-xl font-900 font-italic tracking-1.5">
@@ -35,13 +28,7 @@
</view>
<view class="flex-col-center gap-6 my-8 relative">
<uni-icons
class="absolute right-80 -top-10"
type="reload"
color="#D29E52"
size="24"
@click="getWallet"
/>
<uni-icons class="absolute right-80 -top-10" type="reload" color="#D29E52" size="24" @click="getWallet" />
<view>余额(宝石)</view>
<view class="font-bold text-xl">{{ fen2yuan(userWallet.balance) }}</view>
</view>
@@ -52,40 +39,28 @@
<view class="flex justify-between gap-3">
<view
class="flex-1 rounded-full flex-row-center px-4 py-2 b-3 b-solid b-#222 bg-#333 transition-all duration-200"
:style="{ borderColor: payMethod === 'alipay' ? '#D29E52' : '' }"
@click="payMethod = 'alipay'"
>
:style="{ borderColor: payMethod === 'alipay' ? '#D29E52' : '' }" @click="payMethod = 'alipay'">
<image class="size-40rpx mr-2" src="@/static/alipay.png" mode="aspectFill" />
<text>支付宝</text>
</view>
<view
class="flex-1 rounded-full flex-row-center px-4 py-2 b-3 b-solid b-#222 bg-#333 transition-all duration-200"
:style="{ borderColor: payMethod === 'wechat' ? '#D29E52' : '' }"
@click="payMethod = 'wechat'"
>
:style="{ borderColor: payMethod === 'wechat' ? '#D29E52' : '' }" @click="payMethod = 'wechat'">
<image class="size-40rpx mr-2" src="@/static/weixin.png" mode="aspectFill" />
<text>微信支付</text>
</view>
</view>
</view>
<view
v-if="rechargePackag.length"
v-for="item in rechargePackag"
:key="item.id"
class="mx-4 text-base"
>
<view v-if="rechargePackag.length" v-for="item in rechargePackag" :key="item.id" class="mx-4 text-base">
<view class="flex justify-between items-center my-4">
<view class="flex-row-center">
<image class="size-60rpx mr-2" src="@/static/diamond.png" mode="scaleToFill" />
<text>{{ fen2yuanSimple(item.bonusPrice) }}</text>
<text class="text-xs ml-2">({{ item.name }})</text>
</view>
<text
class="px-2 py-1 rounded-2 bg-color-theme-dark active:bg-color-theme"
@click="handleRecharge(item)"
>
<text class="px-2 py-1 rounded-2 bg-color-theme-dark active:bg-color-theme" @click="handleRecharge(item)">
¥{{ fen2yuanSimple(item.payPrice) }}
</text>
</view>
@@ -97,51 +72,114 @@
</template>
<script setup lang="ts">
import { computed, ref } from 'vue';
// @ts-ignore
import { fen2yuan, fen2yuanSimple } from '@/sheep/hooks/useGoods';
import RecentApi from '@/sheep/api/member/recent';
import { useMessage } from '@/uni_modules/wot-design-uni';
import { onLoad } from '@dcloudio/uni-app';
// @ts-ignore
import sheep from '@/sheep';
// @ts-ignore
import PayOrderApi from '@/sheep/api/pay/order';
import { computed, ref } from 'vue';
// @ts-ignore
import { fen2yuan, fen2yuanSimple } from '@/sheep/hooks/useGoods';
import RecentApi from '@/sheep/api/member/recent';
import { useMessage } from '@/uni_modules/wot-design-uni';
import { onLoad, onShow } from '@dcloudio/uni-app';
// @ts-ignore
import sheep from '@/sheep';
// @ts-ignore
import PayOrderApi from '@/sheep/api/pay/order';
import { jumpToWechatMiniProgram } from '@/sheep/util/wechat-tool';
const messageBox = useMessage();
const messageBox = useMessage();
const payMethod = ref<'alipay' | 'wechat'>('alipay'); // 支付方式:alipay / wechat
// 充值套餐列表
const rechargePackag = ref<{ id: number; name: string; payPrice: number; bonusPrice: number }[]>(
[],
);
const userWallet = computed(() => sheep.$store('user').userWallet);
const payMethodMap = [
{
title: "支付宝",
payment: '',
key: 'alipay'
},
{
title: "微信支付",
payment: 'wx_lite',
key: 'wechat'
}
]
onLoad(async () => {
const { data } = await RecentApi.getWalletRechargePackage();
rechargePackag.value = data ?? [];
});
const payMethod = ref<'alipay' | 'wechat'>('alipay'); // 支付方式:alipay / wechat
// 充值套餐列表
const rechargePackag = ref<{ id: number; name: string; payPrice: number; bonusPrice: number }[]>(
[],
);
const userWallet = computed(() => sheep.$store('user').userWallet);
const getWallet = () => {
sheep.$store('user').getWallet();
};
onLoad((params) => {
if (params) {
if (params.packageId && params.payMethod) {
payMethod.value = params.payMethod
disposeWechatPay(params.packageId)
}
}
});
const handleRecharge = (item: any) => {
if (!item.id) return uni.showToast({ title: '请选择会员类型', icon: 'none' });
messageBox
.confirm({
msg: `确认购买套餐 ${fen2yuanSimple(item.payPrice)} 元?`,
title: '提示',
})
.then(async () => {
const { code, data } = await RecentApi.walletRecharge({ packageId: item.id });
if (code !== 0) return uni.showToast({ title: '创建订单失败', icon: 'fail' });
// const { data } = await PayOrderApi.getOrder(data.payOrderId, true);
sheep.$platform.pay(payMethod.value, 'recharge', data.payOrderId);
onShow(async () => {
const { data } = await RecentApi.getWalletRechargePackage();
rechargePackag.value = data ?? [];
})
// uni.showToast({ title: '购买成功', icon: 'success' });
getWallet();
})
.catch(() => {});
};
const getWallet = () => {
sheep.$store('user').getWallet();
};
const handleRecharge = (item: any) => {
if (!item.id) {
uni.showToast({ title: '请选择会员类型', icon: 'none' });
return
}
const payMethodItem = payMethodMap.find((item) => item.key === payMethod.value);
if (!payMethodItem) {
uni.showToast({ title: '请选择支付方式', icon: 'none' });
return
}
if (!payMethodItem.payment) {
uni.showToast({ title: `不支持${payMethodItem.title}支付`, icon: 'none' });
return
}
messageBox
.confirm({
msg: `确认购买套餐 ${fen2yuanSimple(item.payPrice)} 元?`,
title: '提示',
})
.then(async () => {
// #ifdef MP-WEIXIN
disposeWechatPay(item.id)
// #endif
// #ifndef MP-WEIXIN
jumpToWechatPage(item.id)
// #endif
})
.catch(() => { });
};
// 处理微信支付
const disposeWechatPay = async (packageId: any) => {
uni.showLoading({ title: '支付中...', mask: true });
try {
const { code, data } = await RecentApi.walletRecharge({ packageId: packageId });
console.log("发起订单id,data:", data);
if (code !== 0) {
uni.showToast({ title: '创建订单失败', icon: 'none' });
throw new Error()
}
sheep.$platform.pay(payMethod.value, 'recharge', data.payOrderId);
// 更新用户钱包
getWallet();
uni.showToast({ title: '支付成功', icon: 'success' });
} catch (error) {
console.error("|处理微信支付|,意外的错误error:", error);
} finally {
uni.hideLoading();
}
}
// 跳转到微信小程序
const jumpToWechatPage = (packageId: any) => {
jumpToWechatMiniProgram("recharge", {
packageId,
payMethod: payMethod.value
})
}
</script>
+7 -11
View File
@@ -150,9 +150,8 @@ export default class SheepPay {
async wechatWapPay() {
const { error, data } = await this.prepay();
if (error === 0) {
const redirect_url = `${getRootUrl()}pages/pay/result?id=${this.id}&payment=${
this.payment
}&orderType=${this.orderType}`;
const redirect_url = `${getRootUrl()}pages/pay/result?id=${this.id}&payment=${this.payment
}&orderType=${this.orderType}`;
location.href = `${data.pay_data.h5_url}&redirect_url=${encodeURIComponent(redirect_url)}`;
}
}
@@ -265,13 +264,13 @@ export default class SheepPay {
// 解析支付参数
let payConfig = JSON.parse(data.displayContent);
if(typeof payConfig.appId === 'undefined'){
if (typeof payConfig.appId === 'undefined') {
payConfig.appId = payConfig.appid;
}
if(typeof payConfig.nonceStr === 'undefined'){
if (typeof payConfig.nonceStr === 'undefined') {
payConfig.nonceStr = payConfig.noncestr;
}
if(typeof payConfig.timeStamp === 'undefined'){
if (typeof payConfig.timeStamp === 'undefined') {
payConfig.timeStamp = payConfig.timestamp;
}
// 调用微信支付
@@ -378,11 +377,8 @@ export function getPayMethods(channels) {
// 支付结果跳转,success:成功,fail:失败
export function goPayResult(id, orderType, resultType) {
sheep.$router.redirect('/pages/pay/result', {
id,
orderType,
payState: resultType,
});
const url = `/pages/pay/result?id=${id}&orderType=${orderType}&payState=${resultType}`;
uni.redirectTo({ url: url })
}
export function goBindWeixin() {
+48
View File
@@ -0,0 +1,48 @@
// @ts-nocheck
import { isEmpty } from 'lodash-es';
const targetAppId = 'wx2b4e4d3feff8267f';
const paramsToQuery = (params: Record<string, any>) => {
if (isEmpty(params)) {
return '';
}
let query = [];
for (let key in params) {
query.push(key + '=' + params[key]);
}
return query.join('&');
}
export const jumpToWechatMiniProgram = (
action: 'recharge' | 'openVip',
params: Record<string, any>,
) => {
let path = '';
if (action === 'recharge') {
path = 'pages/profile/recharge';
}
if (action === 'openVip') {
path = 'pages/profile/apply-vip';
}
if (params) {
path += `?${paramsToQuery(params)}`;
}
console.info(`跳转到appId:${targetAppId},page:${path}`);
return new Promise((resolve, reject) => {
uni.navigateToMiniProgram({
appId: targetAppId,
path: path,
envVersion: 'release',
success(res) {
console.log('跳转成功', res);
resolve(res);
},
fail(res) {
console.log('跳转失败', res);
reject(res);
},
});
});
}