Forráskód Böngészése

feat(支付): 三合一。添加微信支付功能,区分支付宝是否自定义金额

- 在config.js中新增支付类型配置和支付宝自定义金额开关
- 实现微信支付授权获取用户openid功能
- 添加微信支付API调用和支付结果处理逻辑
- 根据支付类型动态显示不同支付方式和提示信息
- 优化登录页面布局,添加返回按钮和调整logo位置
- 统一请求拦截器和响应拦截器的代码风格
Shirley 1 hete
szülő
commit
7186cda233
6 módosított fájl, 321 hozzáadás és 129 törlés
  1. 21 15
      src/utils/config.js
  2. 32 32
      src/utils/request.js
  3. 39 63
      src/views/CoinExchange.vue
  4. 49 6
      src/views/Login.vue
  5. 129 10
      src/views/Recharge.vue
  6. 51 3
      src/views/Search.vue

+ 21 - 15
src/utils/config.js

@@ -1,37 +1,43 @@
 // 判断当前环境
-const isDev = process.env.NODE_ENV === 'development'
+const isDev = process.env.NODE_ENV === "development";
 
 // API基础URL配置
-export const API_BASE_URL = isDev 
-  ? 'https://gbyy91.asia/api'
-  : 'https://gbyy91.com/api' // 生产环境 
+export const API_BASE_URL = isDev
+  ? "https://gbyy91.asia/api"
+  : "https://gbyy91.com/api"; // 生产环境
+
+// 支付方式切换参数 ('wechat' | 'alipay')
+export const PAYMENT_TYPE = "alipay";
+
+// 支付宝支付自定义金额模块开关
+export const ALI_CUSTOM = true;
 
 // 支付方式ID
 export const PAY_WAY_ID = {
   ANDROID: 10,
-  IOS: 21
-}
+  IOS: 21,
+};
 
 // 检测设备类型
 export function getDevicePayWayId() {
-  const ua = navigator.userAgent.toLowerCase()
+  const ua = navigator.userAgent.toLowerCase();
   if (/iphone|ipad|ipod|ios/.test(ua)) {
-    return PAY_WAY_ID.IOS
+    return PAY_WAY_ID.IOS;
   }
   // 默认返回安卓支付方式
-  return PAY_WAY_ID.ANDROID
+  return PAY_WAY_ID.ANDROID;
 }
 
 // 获取平台类型
 export function getPlatformType() {
-  const ua = navigator.userAgent.toLowerCase()
+  const ua = navigator.userAgent.toLowerCase();
   if (/iphone|ipad|ipod|ios/.test(ua)) {
-    return 'ios'
+    return "ios";
   } else if (/android/.test(ua)) {
-    return 'android'
+    return "android";
   }
   // 默认返回web平台
-  return 'web'
+  return "web";
 }
 
 // 其他全局配置可以在这里添加
@@ -40,5 +46,5 @@ export default {
   isDev,
   PAY_WAY_ID,
   getDevicePayWayId,
-  getPlatformType
-} 
+  getPlatformType,
+};

+ 32 - 32
src/utils/request.js

@@ -1,46 +1,46 @@
-import axios from 'axios'
-import { Toast, Dialog } from 'vant'
-import { API_BASE_URL } from './config'
+import axios from "axios";
+import { Toast, Dialog } from "vant";
+import { API_BASE_URL } from "./config";
 
 // 创建axios实例
 const service = axios.create({
   baseURL: API_BASE_URL, // 从配置文件获取基础URL
-  timeout: 10000 // 请求超时时间
-})
+  timeout: 10000, // 请求超时时间
+});
 
 // 请求拦截器
 service.interceptors.request.use(
-  config => {
+  (config) => {
     // 在发送请求之前可以做一些处理
     // 从localStorage获取token和userId
-    const token = localStorage.getItem('token')
-    const userId = localStorage.getItem('userId')
-    
+    const token = localStorage.getItem("token");
+    const userId = localStorage.getItem("userId");
+
     // 如果存在token,添加到请求头
     if (token) {
-      config.headers['Authorization'] = token // `Bearer ${token}`
-      config.headers['token'] = token
+      config.headers["Authorization"] = token; // `Bearer ${token}`
+      config.headers["token"] = token;
     }
-    
+
     // 如果存在userId,添加到请求头
     if (userId) {
-      config.headers['userId'] = userId
+      config.headers["userId"] = userId;
     }
-    
-    return config
+
+    return config;
   },
-  error => {
+  (error) => {
     // 处理请求错误
-    console.log(error)
-    return Promise.reject(error)
+    console.log(error);
+    return Promise.reject(error);
   }
-)
+);
 
 // 响应拦截器
 service.interceptors.response.use(
-  response => {
-    console.log(response)
-    const res = response.data
+  (response) => {
+    console.log(response);
+    const res = response.data;
     // 根据后端约定的状态码判断请求是否成功
     if (res.code == 109) {
       Toast.fail("登录令牌失效");
@@ -55,18 +55,18 @@ service.interceptors.response.use(
       console.log("普通提示", res.message);
     } else if (res.code !== 200) {
       //Toast.fail(res.message || '请求失败')
-     // return Promise.reject(new Error(res.message || '请求失败'))
-     return res
+      // return Promise.reject(new Error(res.message || '请求失败'))
+      return res;
     } else {
-      return res
+      return res;
     }
-   // return res
+    // return res
   },
-  error => {
-    console.log('请求错误:', error)
-    Toast.fail('网络异常,请稍后重试')
-    return Promise.reject(error)
+  (error) => {
+    console.log("请求错误:", error);
+    Toast.fail("网络异常,请稍后重试");
+    return Promise.reject(error);
   }
-)
+);
 
-export default service
+export default service;

+ 39 - 63
src/views/CoinExchange.vue

@@ -27,14 +27,8 @@
         <!-- 用户ID输入 -->
         <div class="form-item">
           <div class="form-label">输入要兑换的用户ID</div>
-          <van-field
-            v-model="userId"
-            type="tel"
-            placeholder="请输入6位用户ID"
-            maxlength="6"
-            class="user-id-input"
-            @input="onUserIdInput"
-          />
+          <van-field v-model="userId" type="tel" placeholder="请输入6位用户ID" maxlength="6" class="user-id-input"
+            @input="onUserIdInput" />
         </div>
 
         <!-- 用户信息显示 -->
@@ -56,13 +50,8 @@
         <!-- 兑换数量输入 -->
         <div class="form-item">
           <div class="form-label">输入要兑换的金币数量</div>
-          <van-field
-            v-model="exchangeAmount"
-            type="number"
-            placeholder="请输入金币数量"
-            class="exchange-input"
-            @input="onExchangeAmountInput"
-          />
+          <van-field v-model="exchangeAmount" type="number" placeholder="请输入金币数量" class="exchange-input"
+            @input="onExchangeAmountInput" />
         </div>
 
         <!-- 兑换结果显示 -->
@@ -75,14 +64,8 @@
 
         <!-- 确认兑换按钮 -->
         <div class="confirm-btn-container">
-          <van-button 
-            type="primary" 
-            block 
-            round 
-            :disabled="!canExchange"
-            @click="showConfirmDialog"
-            class="confirm-btn"
-          >
+          <van-button type="primary" block round :disabled="!canExchange" @click="showConfirmDialog"
+            class="confirm-btn">
             确认兑换(-{{ exchangeAmount || 0 }}金币)
           </van-button>
         </div>
@@ -90,16 +73,9 @@
     </div>
 
     <!-- 二次确认弹窗 -->
-    <van-dialog
-      v-model="confirmDialogVisible"
-      title="是否确认ID兑换?"
-      show-cancel-button
-      confirm-button-text="确认兑换"
-      cancel-button-text="取消兑换"
-      @confirm="confirmExchange"
-      @cancel="confirmDialogVisible = false"
-      class="confirm-dialog"
-    >
+    <van-dialog v-model="confirmDialogVisible" title="是否确认ID兑换?" show-cancel-button confirm-button-text="确认兑换"
+      cancel-button-text="取消兑换" @confirm="confirmExchange" @cancel="confirmDialogVisible = false"
+      class="confirm-dialog">
       <div class="confirm-content">
         <div class="confirm-user-info">
           <div class="confirm-avatar">
@@ -113,7 +89,7 @@
             <div class="confirm-user-id">ID: {{ userInfo ? userInfo.id : userId }}</div>
           </div>
         </div>
-        
+
         <div class="confirm-exchange-info">
           <div class="confirm-item">
             <span class="confirm-label">兑换的金币数量:</span>
@@ -156,14 +132,14 @@ export default {
       const amount = parseInt(this.exchangeAmount) || 0
       return amount * this.exchangeRate
     },
-    
+
     // 是否可以兑换
     canExchange() {
       const amount = parseInt(this.exchangeAmount) || 0
-      return this.userInfo && 
-             amount > 0 && 
-             amount <= this.coinBalance &&
-             this.userId.length === 6
+      return this.userInfo &&
+        amount > 0 &&
+        amount <= this.coinBalance &&
+        this.userId.length === 6
     }
   },
   methods: {
@@ -171,17 +147,17 @@ export default {
     goBack() {
       this.$router.go(-1)
     },
-    
+
     // 跳转到兑换记录页面
     goToRecord() {
       this.$router.push('/coin-exchange-record')
     },
-    
+
     // 用户ID输入处理
     async onUserIdInput() {
       // 只允许数字
       this.userId = this.userId.replace(/\D/g, '')
-      
+
       // 当输入6位数字时自动搜索用户
       if (this.userId.length === 6) {
         await this.searchUser()
@@ -189,24 +165,24 @@ export default {
         this.userInfo = null
       }
     },
-    
+
     // 搜索用户信息
     async searchUser() {
       if (!this.userId || this.userId.length !== 6) {
         return
       }
-      
+
       try {
         this.$toast.loading({
           message: '搜索用户中...',
           forbidClick: true,
           duration: 0
         })
-        
+
         // 调用API搜索用户信息
         const res = await getUserInfo(this.userId)
         this.$toast.clear()
-        
+
         if (res.data && res.data.userId) {
           this.userInfo = {
             id: res.data.userId,
@@ -224,12 +200,12 @@ export default {
         console.error('搜索用户失败:', error)
       }
     },
-    
+
     // 兑换数量输入处理
     onExchangeAmountInput() {
       // 只允许正整数
       this.exchangeAmount = this.exchangeAmount.replace(/\D/g, '')
-      
+
       // 检查是否超过余额
       const amount = parseInt(this.exchangeAmount) || 0
       if (amount > this.coinBalance) {
@@ -237,7 +213,7 @@ export default {
         this.exchangeAmount = this.coinBalance.toString()
       }
     },
-    
+
     // 显示确认对话框
     showConfirmDialog() {
       if (!this.canExchange) {
@@ -250,31 +226,31 @@ export default {
         }
         return
       }
-      
+
       this.confirmDialogVisible = true
     },
-    
+
     // 确认兑换
     async confirmExchange() {
       // 关闭弹窗
       this.confirmDialogVisible = false
-      
+
       try {
         this.$toast.loading({
           message: '兑换中...',
           forbidClick: true,
           duration: 0
         })
-        
+
         // 调用兑换API
         const response = await integralExchangeGoldCoinToOther(
           this.userId,
           parseInt(this.exchangeAmount)
         )
-        
+
         this.$toast.clear()
         this.$toast.success('兑换成功')
-        
+
         // 更新余额 - 从API返回值获取最新的integral并更新localStorage
         if (response && response.data && typeof response.data.integral !== 'undefined') {
           this.coinBalance = response.data.integral
@@ -283,17 +259,17 @@ export default {
           // 如果API没有返回integral,则使用原来的减法逻辑
           this.coinBalance -= parseInt(this.exchangeAmount)
         }
-        
+
         // 重置表单
         this.resetForm()
-        
+
       } catch (error) {
         this.$toast.clear()
         this.$toast.fail('兑换失败,请重试')
         console.error('兑换失败:', error)
       }
     },
-    
+
     // 重置表单
     resetForm() {
       this.userId = ''
@@ -631,25 +607,25 @@ export default {
   .balance-card {
     padding: 20px;
   }
-  
+
   .balance-amount {
     font-size: 28px;
   }
-  
+
   .form-card {
     padding: 20px;
   }
-  
+
   .confirm-user-info {
     flex-direction: column;
     text-align: center;
   }
-  
+
   .confirm-avatar {
     margin-right: 0;
     margin-bottom: 12px;
   }
-  
+
   .confirm-user-details {
     text-align: center;
   }

+ 49 - 6
src/views/Login.vue

@@ -3,9 +3,12 @@
     <!-- 顶部标题 -->
     <div class="page-header">
       <div class="header-content">
+        <div class="back-btn" @click="goBack">
+          <van-icon name="arrow-left" size="20" />
+        </div>
         <div class="logo-wrapper">
           <div class="logo-container">
-            <img src="@/assets/images/logo-l.png" alt="告白语音" class="logo-image" />
+            <!-- <img src="@/assets/images/logo-l.png" alt="告白语音" class="logo-image" /> -->
           </div>
         </div>
       </div>
@@ -13,6 +16,9 @@
 
     <!-- 登录表单 -->
     <div class="login-container">
+      <div class="logo">
+        <img src="@/assets/images/logo-l.png" alt="告白语音" class="logo-image" />
+      </div>
       <div class="login-card">
         <div class="login-title">手机号登录</div>
 
@@ -90,6 +96,10 @@ export default {
     },
   },
   methods: {
+    // 返回上一页
+    goBack() {
+      this.$router.go(-1);
+    },
     // 获取验证码
     async getVerifyCode() {
       if (!this.isPhoneValid) {
@@ -163,24 +173,35 @@ export default {
 
 /* 页面头部 */
 .page-header {
-  padding: 40px 16px 10px;
+  padding: 10px 16px;
   text-align: center;
 }
 
 .header-content {
   display: flex;
-  justify-content: center;
+  justify-content: space-between;
   align-items: center;
 }
 
+.back-btn {
+  width: 40px;
+  height: 40px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  cursor: pointer;
+  color: var(--text-color);
+}
+
 .logo-wrapper {
   display: flex;
   justify-content: center;
+  flex: 1;
 }
 
 .logo-container {
-  width: 100px;
-  height: 100px;
+  width: 60px;
+  height: 60px;
   display: flex;
   align-items: center;
   justify-content: center;
@@ -194,9 +215,31 @@ export default {
 
 /* 登录容器 */
 .login-container {
-  padding: 40px 20px;
+  padding: 0px 10px 0;
 }
 
+/* Logo样式 */
+.logo {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  margin-bottom: 20px;
+  padding: 10px 0 10px;
+}
+
+.logo .logo-image {
+  width: 100px;
+  /* height: 60px; */
+  object-fit: contain;
+
+  transition: transform 0.3s ease;
+}
+
+.logo .logo-image:hover {
+  transform: scale(1.05);
+}
+
+
 .login-card {
   background: var(--card-background);
   border-radius: 16px;

+ 129 - 10
src/views/Recharge.vue

@@ -68,7 +68,7 @@
 
     <!-- 支付方式 -->
     <div class="payment-section">
-      <div class="payment-option">
+      <div v-if="paymentType === 'alipay'" class="payment-option">
         <div class="payment-icon">
           <img src="@/assets/images/recharge_paypal.png" alt="支付宝支付" class="alipay-icon" />
         </div>
@@ -77,6 +77,15 @@
           <img src="@/assets/images/duihao.png" alt="选中" class="check-icon" />
         </div>
       </div>
+      <div v-if="paymentType === 'wechat'" class="payment-option">
+        <div class="payment-icon">
+          <img src="@/assets/images/recharge_wechat.png" alt="微信支付" class="wechat-icon" />
+        </div>
+        <div class="payment-name">微信支付</div>
+        <div class="payment-selected">
+          <img src="@/assets/images/duihao.png" alt="选中" class="check-icon" />
+        </div>
+      </div>
     </div>
 
     <!-- 温馨提示 -->
@@ -85,7 +94,8 @@
       <div class="tips-content">
         <div class="tip-item">1. 充值前请确定您已满18周岁并具有完全民事行为能力。</div>
         <div class="tip-item">2. 安全账号转账、理赔转账、刷单、代充均为骗局,请认真核实并确认</div>
-        <div class="tip-item">3. 大额充值,支付方式可选择"零钱通"</div>
+        <div class="tip-item" v-if="paymentType === 'wechat'">3. 大额充值,支付方式可选择"零钱通"</div>
+        <div class="tip-item" v-if="paymentType === 'alipay'">3. 大额充值,请确保支付宝账户余额充足</div>
         <div class="tip-item">4. 如有疑问,请联系服务号客服</div>
       </div>
 
@@ -121,14 +131,16 @@
 import { getProductList } from '@/api/product'
 import { getUserInfo } from '@/api/user'
 import { aliPayCoin, aliPayH5 } from '@/api/pay'
-import { getDevicePayWayId, getPlatformType } from '@/utils/config'
+import { ahtuCodeApi, wechatPayCoin, wxPay } from '@/api/pay'
+import { getDevicePayWayId, getPlatformType, ALI_CUSTOM, PAYMENT_TYPE } from '@/utils/config'
 
 export default {
   name: 'RechargePage',
   data() {
     return {
       resultDataMess: {},
-      userInfo: {
+      userCode: '', // 用于微信支付
+      userInfo: { // 用于支付宝支付
         id: '',
         nickname: '',
         avatar: ''
@@ -140,7 +152,9 @@ export default {
       agreementChecked: false,
       agreementVisible: false,
       // 自定义金额
-      customAmount: ''
+      customAmount: '',
+      // 支付方式类型
+      paymentType: PAYMENT_TYPE
     }
   },
   computed: {
@@ -149,7 +163,11 @@ export default {
     },
     // 显示列表 = 产品列表 + 自定义
     rechargeOptionsWithCustom() {
-      return [...(this.rechargeOptions || []), { isCustom: true }]
+      if (ALI_CUSTOM && this.paymentType === 'alipay') {
+        return [...(this.rechargeOptions || []), { isCustom: true }]
+      } else {
+        return [...(this.rechargeOptions || [])]
+      }
     },
     // 是否选择了自定义
     isCustomSelected() {
@@ -159,15 +177,20 @@ export default {
   created() {
     // 获取用户信息
     this.initUserInfo()
-
     // 获取产品列表
     this.fetchProductList()
+    if (this.paymentType === 'wechat') {
+      this.listenWeixinBridge() // 监听桥梁加载
+    }
   },
   methods: {
     // 初始化用户信息
     async initUserInfo() {
       // 从路由参数获取用户信息
       const { id, nickname, avatar } = this.$route.query
+      if (this.paymentType === 'wechat') {
+        this.userCode = this.$route.query.userCode
+      }
       if (id) {
         // 如果路由参数中有用户ID,直接使用
         this.userInfo.id = id
@@ -195,7 +218,7 @@ export default {
           }
         } else {
           // 没有用户ID,返回搜索页面
-          this.$toast('请先搜索用户')
+          this.$toast('请先登录')
           this.$router.replace('/')
         }
       }
@@ -205,6 +228,20 @@ export default {
         localStorage.setItem('lastUserId', this.userInfo.id)
       }
     },
+    // 监听 weixinJSBridge 加载
+    listenWeixinBridge() {
+      if (window.WeixinJSBridge) {
+        this.onWeixinBridgeReady()
+      } else {
+        const listener = () => this.onWeixinBridgeReady()
+        document.addEventListener('WeixinJSBridgeReady', listener, false)
+      }
+    },
+    // weixinJSBridge 加载成功回调
+    onWeixinBridgeReady() {
+      this.bridgeReady = true
+      console.log('weixinJSBridge 加载成功')
+    },
     // 获取产品列表
     async fetchProductList() {
       try {
@@ -289,7 +326,11 @@ export default {
         allowHtml: true
       }).then(() => {
         // 调用支付接口
-        this.requestAliPay(selectedOption)
+        if (this.paymentType === 'wechat') {
+          this.requestWechatPay(selectedOption)
+        } else {
+          this.requestAliPay(selectedOption)
+        }
       }).catch(() => {
         // 取消支付
       })
@@ -371,6 +412,83 @@ export default {
       }
     },
 
+    // 请求微信支付
+    async requestWechatPay(product) {
+      // 显示加载提示
+      this.isLoading = true
+      this.$toast.loading({
+        message: '正在发起支付...',
+        forbidClick: true,
+        duration: 0
+      })
+
+      try {
+        // 构建支付参数
+        const payWayId = getDevicePayWayId() // 获取设备对应的支付方式ID
+        const payData = {
+          "productName": "一号房间",
+          openId: localStorage.getItem('userOpenId'),
+          userId: this.userInfo.id,
+          productId: product.id,
+          amount: product.price,
+          orderNo: Date.now(),
+          payWayId: payWayId // 添加支付方式ID
+        }
+
+        // 调用后端支付接口
+        const res = await wxPay(payData)
+        console.log(res, 9999)
+        this.$toast.clear()
+        this.isLoading = false
+
+        // 处理支付结果
+        if (res.status == 200) {
+          try {
+            let signData = JSON.parse(res.data.outputJSON)
+            this.resultDataMess = signData
+            console.log(signData, 'signData')
+            let wxJsapiParam = signData.wxJsapiParam
+            if (signData.returnCode == '0000') {
+              // 5. 调用 weixinJSBridge 支付
+              this.invokeWeixinBridgePayment(wxJsapiParam)
+            } else {
+              this.$toast.fail(this.resultDataMess.returnMsg || '获取支付链接失败')
+            }
+          } catch {
+            this.$toast.fail(this.resultDataMess.returnMsg || '获取支付链接失败')
+          }
+        } else {
+          this.$toast.fail(this.resultDataMess.returnMsg || '获取支付链接失败')
+        }
+      } catch (error) {
+        this.$toast.clear()
+        this.isLoading = false
+        console.error('支付请求失败:', error)
+        this.$toast.fail('支付请求失败,请重试')
+      }
+    },
+    // 调用 weixinJSBridge 支付
+    invokeWeixinBridgePayment(payParams) {
+      window.WeixinJSBridge.invoke(
+        'getBrandWCPayRequest',
+        payParams,
+        this.handleWeixinPayResult
+      )
+    },
+    // 处理支付结果
+    handleWeixinPayResult(res) {
+      if (res.err_msg === "get_brand_wcpay_request:ok") {
+        // 支付成功
+        this.handlePaymentSuccess(res)
+      } else if (res.err_msg === "get_brand_wcpay_request:cancel") {
+        // 支付取消
+        this.handlePaymentCancel()
+      } else {
+        // 支付失败
+        this.handlePaymentFailure(res)
+      }
+    },
+
     // 处理支付成功
     handlePaymentSuccess() {
       console.log('支付成功')
@@ -656,7 +774,8 @@ export default {
   margin-right: 12px;
 }
 
-.alipay-icon {
+.alipay-icon,
+.wechat-icon {
   width: 28px;
   height: 28px;
   object-fit: contain;

+ 51 - 3
src/views/Search.vue

@@ -81,7 +81,8 @@
       <div class="tips-content">
         <div class="tip-item">1. 充值前请确定您已满18周岁并具有完全民事行为能力。</div>
         <div class="tip-item">2. 安全账号转账、理赔转账、刷单、代充均为骗局,请认真核实并确认</div>
-        <div class="tip-item">3. 大额充值,请确保支付宝账户余额充足</div>
+        <div class="tip-item" v-if="paymentType === 'wechat'">3. 大额充值,支付方式可选择"零钱通"</div>
+        <div class="tip-item" v-else>3. 大额充值,请确保支付宝账户余额充足</div>
         <div class="tip-item">4. 如有疑问,请联系服务号客服</div>
       </div>
 
@@ -115,7 +116,8 @@
 <script>
 import { getProductList } from '@/api/product'
 import { getUserInfo } from '@/api/user'
-import { getPlatformType, getDevicePayWayId } from '@/utils/config'
+import { ahtuCodeApi } from '@/api/pay'
+import { getPlatformType, getDevicePayWayId, ALI_CUSTOM, PAYMENT_TYPE } from '@/utils/config'
 
 export default {
   name: 'SearchPage',
@@ -132,6 +134,8 @@ export default {
       agreementVisible: false,
       // 自定义金额
       customAmount: '',
+      // 支付方式类型
+      paymentType: PAYMENT_TYPE,
       // 登录状态
       isLoggedIn: false
     }
@@ -139,6 +143,9 @@ export default {
   created() {
     // 获取产品列表
     this.fetchProductList()
+    if (this.paymentType === 'wechat') {
+      this.getUserCode()
+    }
   },
   computed: {
     selectedRechargeOption() {
@@ -146,7 +153,11 @@ export default {
     },
     // 显示列表 = 产品列表 + 自定义
     coinOptionsWithCustom() {
-      return [...(this.coinOptions || []), { isCustom: true }]
+      if (ALI_CUSTOM) {
+        return [...(this.coinOptions || []), { isCustom: true }]
+      } else {
+        return [...(this.coinOptions || [])]
+      }
     },
     // 是否选择了自定义
     isCustomSelected() {
@@ -154,6 +165,42 @@ export default {
     }
   },
   methods: {
+    // (微信支付)获取用户code
+    getUserCode() {
+      console.log('微信支付getUserCode')
+      let url = window.location.href
+      this.tianyongchao = window.location.href
+      const strictMatch = url.match(/[?&]code=([^&]+)/);
+      const strictCode = strictMatch ? strictMatch[1] : null;
+      if (!strictCode) {
+        // 记录当前页面URL作为重定向目标
+        const redirectUrl = `https%3A%2F%2Fgbyy91.com%2Fpay`
+
+        // 构建微信授权URL
+        const authUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxa25eb9f7ebd39219&redirect_uri=${redirectUrl}&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect`
+        setTimeout(() => {
+          window.location.href = authUrl
+        }, 300)
+
+      } else {
+        let url = window.location.href
+        const strictMatch = url.match(/[?&]code=([^&]+)/);
+        const strictCode = strictMatch ? strictMatch[1] : null;
+        this.userCode = strictCode
+        this.$toast.loading({
+          message: '加载中...',
+          forbidClick: true,
+          duration: 0
+        })
+        ahtuCodeApi(this.userCode).then((res) => {
+          if (res.data.openid) {
+            localStorage.setItem('userOpenId', res.data.openid)
+          }
+        }).finally(() => {
+          this.$toast.clear()
+        })
+      }
+    },
     // 获取产品列表
     async fetchProductList() {
       try {
@@ -201,6 +248,7 @@ export default {
           this.$router.push({
             path: '/recharge',
             query: {
+              userCode: this.paymentType === 'wechat' ? this.userCode : undefined,
               id: res.data.userId,
               nickname: res.data.userName,
               avatar: res.data.avatar