Files
yusheng-h5/pages/other/weChatPay.vue

433 lines
9.6 KiB
Vue
Raw Permalink Normal View History

2026-01-08 16:06:53 +08:00
<template>
<view class="view-page" :style="{backgroundImage: `url('${ThemeData ? ThemeData.app_bg : baseBgUrl }')`}">
<navBar :style="{marginTop: `${statusBarHeight}${uni.getSystemInfoSync().platform === 'ios' ? 'px': 'dp'}`}"
:navTitle="'羽声充值'" :isLeftSlot="true">
</navBar>
<view class="content">
<view class="">
<uni-easyinput prefixIcon="search" clearSize="18" v-model="searchValue" placeholder="请输入您在羽声语音的ID">
</uni-easyinput>
</view>
<view class="show_ByIdView">
<view class="">
余额
</view>
<view class="">
金币
</view>
</view>
<view class="coinWrap">
<view
class="coinBox"
:class="{ 'selected': selectedIndex === index }"
v-for="(ele, index) in moneyList"
:key="index"
@click="selectAmount(index)"
>
<view class="w-fill coin">
<img style="width: 40rpx;height: 40rpx;" :src="Coin" alt="" />{{ele.coin}}
</view>
<view class="w-fill money">
{{ele.money}}
</view>
</view>
</view>
<view class="text-wrap">
<view class="" style="margin-bottom: 20rpx;">
充值小贴士
</view>
<view class="font-24" style="margin-bottom: 20rpx;">
1.为避免您的账号及资金被冻结请勿通过非官方渠道 充值谨防上当受损
</view>
<view class="font-24">
2.充值前请确定您已满18周岁
</view>
</view>
<view class="pay-button-wrap">
<button
class="pay-button"
:class="{ 'disabled': selectedIndex === -1 || isPaying || !isAgreed }"
:disabled="selectedIndex === -1 || isPaying || !isAgreed"
@click="handlePay"
>
{{ isPaying ? '支付中...' : '立即支付' }}
</button>
<view class="agreement-wrap">
<checkbox-group @change="handleAgreementChange">
<label class="agreement-label">
<checkbox
:checked="isAgreed"
color="#3ABC6D"
style="transform: scale(0.8);"
/>
<text class="agreement-text">我已阅读并同意</text>
<text class="agreement-link" @click.stop="showAgreement">充值协议</text>
</label>
</checkbox-group>
</view>
</view>
</view>
</view>
</template>
<script>
import config from '@/until/config.js';
import navBar from '@/component/nav.vue';
import Coin from '@/static/image/income/coin.png';
import wxPay from '@/until/wxpay.js';
export default {
components: {
navBar
},
data() {
return {
baseBgUrl: config.new_unionUrl || '',
unionBgUrl: config.unicon_url || '',
statusBarHeight: 0,
ThemeData: null,
searchValue: "",
Coin: Coin,
moneyList: [{
coin: 300,
money: 3,
},
{
coin: 500,
money: 5,
},
{
coin: 1000,
money: 10,
},
{
coin: 1500,
money: 15,
},
{
coin: 2000,
money: 20,
},
{
coin: 3000,
money: 30,
},
{
coin: 5000,
money: 50,
},
{
coin: 10000,
money: 100,
}
],
selectedIndex: -1, // 选中的充值金额索引
selectedAmount: 0, // 选中的金额(元)
selectedCoin: 0, // 选中的金币数量
isPaying: false,
isAgreed: false // 是否同意协议
}
},
onLoad() {
// 页面加载时初始化微信 JS-SDK
this.initWxPay();
},
methods: {
// 初始化微信支付
async initWxPay() {
try {
await wxPay.initWxJsSDK();
} catch (error) {
console.error('初始化微信支付失败:', error);
}
},
// 选择充值金额
selectAmount(index) {
this.selectedIndex = index;
this.selectedAmount = this.moneyList[index].money;
this.selectedCoin = this.moneyList[index].coin;
},
// 协议勾选变化
handleAgreementChange(e) {
this.isAgreed = e.detail.value.length > 0;
},
// 查看协议
showAgreement() {
uni.showModal({
title: '充值协议',
content: '1. 充值前请确认您已满18周岁\n2. 充值金额一经充值成功,不支持退款\n3. 请勿通过非官方渠道充值,谨防上当受骗\n4. 充值遇到问题请联系客服处理\n5. 本平台保留最终解释权',
confirmText: '我知道了',
showCancel: false
});
},
// 立即支付
async handlePay() {
// 1. 验证用户ID
if (!this.searchValue || this.searchValue.trim() === '') {
uni.showToast({
title: '请输入您在羽声语音的ID',
icon: 'none',
duration: 2000
});
return;
}
// 2. 验证是否选择了充值金额
if (this.selectedIndex === -1) {
uni.showToast({
title: '请选择充值金额',
icon: 'none',
duration: 2000
});
return;
}
// 3. 验证是否同意协议
if (!this.isAgreed) {
uni.showToast({
title: '请先阅读并同意充值协议',
icon: 'none',
duration: 2000
});
return;
}
// 4. 防止重复点击
if (this.isPaying) {
return;
}
this.isPaying = true;
uni.showLoading({
title: '正在发起支付...',
mask: true
});
try {
// 5. 生成订单号
const orderNo = this.generateOrderNo();
// 6. 计算支付金额(单位:分)
const payAmount = Math.round(this.selectedAmount * 100);
// 7. 附加信息用户ID和金币数量
const attach = JSON.stringify({
userId: this.searchValue.trim(),
coin: this.selectedCoin
});
// 8. 调用微信支付
const result = await wxPay.pay(payAmount, orderNo, attach);
uni.hideLoading();
// 9. 处理支付结果
if (result.success) {
uni.showToast({
title: '支付成功',
icon: 'success',
duration: 2000
});
// 支付成功后的处理
setTimeout(() => {
this.handlePaySuccess();
}, 2000);
} else {
uni.showToast({
title: result.message || '支付失败',
icon: 'none',
duration: 2000
});
}
} catch (error) {
uni.hideLoading();
console.error('支付错误:', error);
let errorMsg = '支付失败';
if (error.message) {
if (error.message.includes('取消')) {
errorMsg = '您已取消支付';
} else {
errorMsg = error.message;
}
}
uni.showToast({
title: errorMsg,
icon: 'none',
duration: 2000
});
} finally {
this.isPaying = false;
}
},
// 生成订单号
generateOrderNo() {
const timestamp = Date.now();
const random = Math.floor(Math.random() * 10000).toString().padStart(4, '0');
return `YS${timestamp}${random}`;
},
// 支付成功后的处理
handlePaySuccess() {
// 清空选择
this.selectedIndex = -1;
this.selectedAmount = 0;
this.selectedCoin = 0;
this.isAgreed = false;
// 可以跳转到支付成功页面或刷新余额
// uni.navigateTo({
// url: '/pages/other/paySuccess'
// });
// 或者返回上一页
// uni.navigateBack();
}
}
}
</script>
<style lang="scss" scoped>
.view-page {
min-height: 100vh;
font-family: Source Han Sans CN, Source Han Sans CN;
background-repeat: no-repeat;
background-size: 100% 100%;
.content {
padding: 0 32rpx;
.show_ByIdView {
margin: 16rpx 0;
width: 100%;
display: inline-flex;
justify-content: space-between;
font-size: 24rpx;
}
.coinWrap {
display: inline-grid;
grid-template-columns: repeat(3, 1fr);
/* 创建3列每列等宽 */
grid-template-rows: repeat(3, 1fr);
/* 创建3行每行等高 */
gap: 10px;
/* 网格项之间的间隙 */
.coinBox {
width: 212rpx;
height: 152rpx;
background: #FFFFFF;
border-radius: 20rpx;
text-align: center;
display: inline-flex;
flex-wrap: wrap;
align-content: center;
border: 2rpx solid transparent;
transition: all 0.3s ease;
cursor: pointer;
&.selected {
border-color: #3ABC6D;
background: rgba(58, 188, 109, 0.1);
.coin {
color: #3ABC6D;
}
.money {
color: #3ABC6D;
}
}
.coin {
font-size: 44rpx;
font-family: D-DIN-PRO, D-DIN-PRO;
font-weight: bold;
font-size: 44rpx;
color: #333333;
margin-left: 10rpx;
}
.money {
color: rgba(0, 0, 0, 0.45);
font-size: 28rpx;
}
}
}
.text-wrap {
margin-top: 32rpx;
font-size: 28rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 500;
color: rgba(0, 0, 0, 0.85);
text-align: left;
font-style: normal;
text-transform: none;
}
.pay-button-wrap {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 20rpx 32rpx;
// background: #FFFFFF;
// box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
.agreement-wrap {
margin-top: 20rpx;
.agreement-label {
display: flex;
align-items: center;
justify-content: center;
.agreement-text {
font-size: 24rpx;
color: #666666;
margin-left: 8rpx;
}
.agreement-link {
font-size: 24rpx;
color: #3ABC6D;
text-decoration: underline;
margin-left: 4rpx;
}
}
}
.pay-button {
width: 100%;
height: 88rpx;
background: #3ABC6D;
border-radius: 44rpx;
font-size: 32rpx;
font-weight: 500;
color: #FFFFFF;
border: none;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
&.disabled {
background: #CCCCCC;
opacity: 0.6;
}
}
}
}
}
</style>