Przeglądaj źródła

小程序调试

skyline 2 miesięcy temu
rodzic
commit
e6b545170a

+ 82 - 14
haha-miniapp/src/main/java/com/haha/miniapp/controller/PayScoreController.java

@@ -8,6 +8,7 @@ import com.haha.entity.Order;
 import com.haha.entity.User;
 import com.haha.service.OrderService;
 import com.haha.service.UserService;
+import com.haha.service.payment.config.WxPayConfig;
 import com.haha.service.payment.payscore.*;
 import com.haha.service.payment.payscore.PayScoreCreateRequest.PostPayment;
 import com.haha.service.payment.payscore.PayScoreCompleteRequest.PostDiscount;
@@ -37,6 +38,7 @@ public class PayScoreController {
     private final PayScoreService payScoreService;
     private final OrderService orderService;
     private final UserService userService;
+    private final WxPayConfig wxPayConfig;
 
     /**
      * 检查用户是否已开通微信支付分
@@ -56,7 +58,9 @@ public class PayScoreController {
             }
 
             boolean isEnabled = isPayscoreEnabled(user);
-            Map<String, Object> data = buildEnableStatusData(isEnabled, userId);
+            Map<String, Object> data = new HashMap<>();
+            data.put("enabled", isEnabled);
+            data.put("userId", userId);
             
             log.info("用户 {} 支付分开通状态:{}", userId, isEnabled ? "已开通" : "未开通");
             return Result.success("查询成功", data);
@@ -68,15 +72,15 @@ public class PayScoreController {
     }
 
     /**
-     * 标记用户已开通微信支付分
+     * 开通微信支付分(调起小程序授权页面)
      * POST /api/payscore/enable
      *
      * @param params 请求参数(可选)
      *   - openId: 用户微信 openId(用于验证)
-     * @return 操作结果
+     * @return 开通结果(包含跳转参数)
      */
     @PostMapping("/enable")
-    public Result<Void> enablePayscore(@RequestBody(required = false) Map<String, Object> params) {
+    public Result<Map<String, Object>> enablePayscore(@RequestBody(required = false) Map<String, Object> params) {
         Long userId = StpUtil.getLoginIdAsLong();
         log.info("用户 {} 申请开通支付分", userId);
 
@@ -89,14 +93,20 @@ public class PayScoreController {
             // 如果已经开通,直接返回成功
             if (isPayscoreEnabled(user)) {
                 log.info("用户 {} 已开通支付分,无需重复开通", userId);
-                return Result.success("您已开通微信支付分", null);
+                Map<String, Object> data = new HashMap<>();
+                data.put("enabled", true);
+                data.put("userId", userId);
+                return Result.success("您已开通微信支付分", data);
             }
 
-            // 更新用户为已开通状态
-            updateUserPayscoreStatus(user);
+            // 生成微信商户订单号
+            String outOrderNo = generatePayscoreOrderNo(userId);
             
-            log.info("用户 {} 开通支付分成功", userId);
-            return Result.success("开通成功", null);
+            // 构建返回数据,供前端调起微信支付分开通页面
+            Map<String, Object> data = buildEnableData(userId, outOrderNo);
+            
+            log.info("用户 {} 准备开通支付分,outOrderNo: {}", userId, outOrderNo);
+            return Result.success("请完成支付分授权", data);
 
         } catch (Exception e) {
             log.error("开通支付分失败 - userId: {}", userId, e);
@@ -104,6 +114,54 @@ public class PayScoreController {
         }
     }
 
+    /**
+     * 确认开通微信支付分(用户完成授权后调用)
+     * POST /api/payscore/confirm-enable
+     *
+     * @param params 请求参数
+     *   - outOrderNo: 微信商户订单号(必填)
+     * @return 开通结果
+     */
+    @PostMapping("/confirm-enable")
+    public Result<Map<String, Object>> confirmEnablePayscore(@RequestBody Map<String, Object> params) {
+        Long userId = StpUtil.getLoginIdAsLong();
+        log.info("用户 {} 确认开通支付分", userId);
+
+        try {
+            if (!params.containsKey("outOrderNo")) {
+                return Result.error(400, "参数错误:outOrderNo 不能为空");
+            }
+
+            String outOrderNo = params.get("outOrderNo").toString();
+            User user = userService.getById(userId);
+            if (user == null) {
+                return Result.error(404, "用户不存在");
+            }
+
+            // 查询支付分订单状态
+            PayScoreResult result = payScoreService.queryPayScoreOrder(outOrderNo);
+            
+            if (result.isSuccess() && "ACCEPTED".equals(result.getState())) {
+                // 用户已授权,更新状态
+                updateUserPayscoreStatus(user);
+                
+                Map<String, Object> data = new HashMap<>();
+                data.put("enabled", true);
+                data.put("userId", userId);
+                
+                log.info("用户 {} 确认开通支付分成功", userId);
+                return Result.success("开通成功", data);
+            } else {
+                log.warn("用户 {} 开通支付分失败,state: {}", userId, result != null ? result.getState() : "null");
+                return Result.error(500, "开通失败,请重试");
+            }
+
+        } catch (Exception e) {
+            log.error("确认开通支付分失败 - userId: {}", userId, e);
+            return Result.error("开通失败:" + e.getMessage());
+        }
+    }
+
     /**
      * 判断用户是否已开通支付分
      *
@@ -115,19 +173,29 @@ public class PayScoreController {
     }
 
     /**
-     * 构建开通状态响应数据
+     * 构建开通支付分所需的数据
      *
-     * @param isEnabled 是否已开通
      * @param userId 用户 ID
-     * @return 响应数据
+     * @param outOrderNo 微信商户订单号
+     * @return 开通数据
      */
-    private Map<String, Object> buildEnableStatusData(boolean isEnabled, Long userId) {
+    private Map<String, Object> buildEnableData(Long userId, String outOrderNo) {
         Map<String, Object> data = new HashMap<>();
-        data.put("enabled", isEnabled);
+        data.put("enabled", false);
         data.put("userId", userId);
+        data.put("outOrderNo", outOrderNo);
+        data.put("serviceId", wxPayConfig != null ? wxPayConfig.getServiceId() : "");
+        data.put("appId", wxPayConfig != null ? wxPayConfig.getAppId() : "");
         return data;
     }
 
+    /**
+     * 生成支付分订单号
+     */
+    private String generatePayscoreOrderNo(Long userId) {
+        return "PS" + System.currentTimeMillis() + String.format("%04d", userId % 10000);
+    }
+
     /**
      * 更新用户支付分开通状态
      *

+ 5 - 1
haha-mp/src/api/payscore.ts

@@ -16,7 +16,11 @@ export interface CheckPayscoreResponse {
  * 开通微信支付分
  */
 export interface EnablePayscoreResponse {
-  // 空响应
+  enabled: boolean;
+  userId: number;
+  outOrderNo?: string;
+  serviceId?: string;
+  appId?: string;
 }
 
 /**

+ 20 - 20
haha-mp/src/pages/index/index.vue

@@ -4,7 +4,7 @@
     <view class="middle-section">
       <view class="app-title">AI零售柜</view>
     </view>
-    
+
     <!-- 核心扫码按钮区域 -->
     <view class="scan-area">
       <!-- 左侧我的按钮 -->
@@ -12,7 +12,7 @@
         <image class="bottom-icon" src="/static/icons/my.svg"></image>
         <view class="bottom-text">我的</view>
       </view>
-      
+
       <!-- 核心扫码按钮 -->
       <button class="scan-button" @click="scanCode">
         <view class="scan-icon">
@@ -20,14 +20,14 @@
         </view>
         <view class="scan-text">扫码开门</view>
       </button>
-      
+
       <!-- 右侧退款按钮 -->
       <view class="bottom-item" @click="goToRefund">
         <image class="bottom-icon" src="/static/icons/refund.svg"></image>
         <view class="bottom-text">退款</view>
       </view>
     </view>
-    
+
     <!-- 底部信息 -->
     <view class="info-section">
       <text class="info-text">💚 微信支付分 | 550分及以上优享</text>
@@ -78,7 +78,7 @@ const scanCode = async () => {
     });
     return;
   }
-  
+
   // 检查微信支付分开通状态
   try {
     const payscoreResult = await checkPayscoreEnabled()
@@ -97,22 +97,22 @@ const scanCode = async () => {
     })
     return
   }
-  
+
   // 调用摄像头扫码
   uni.scanCode({
     success: async function (res) {
       console.log('扫码结果:', res.result);
-      
+
       // 从扫码结果中解析设备ID
       // 二维码格式: https://hh.hahabianli.com/B142977?_wxpmm0=6009000C0000
       // 需要提取路径中的设备ID: B142977
       let deviceId = '';
-      
+
       try {
         // 尝试从URL中提取deviceId
         const urlPattern = /\/([A-Z0-9]+)(\?|$)/;
         const match = res.result.match(urlPattern);
-        
+
         if (match && match[1]) {
           deviceId = match[1];
           console.log('提取到设备ID:', deviceId);
@@ -128,7 +128,7 @@ const scanCode = async () => {
             deviceId = res.result;
           }
         }
-        
+
         if (!deviceId) {
           throw new Error('无法解析设备ID');
         }
@@ -140,34 +140,34 @@ const scanCode = async () => {
         });
         return;
       }
-      
+
       // 显示加载提示
       uni.showLoading({
         title: '正在开门...',
         mask: true
       });
-      
+
       try {
         // 调用真实接口扫码开门
         const response = await scanDoor(deviceId);
-        
+
         // 隐藏加载提示
         uni.hideLoading();
-        
+
         // 开门成功
         uni.showToast({
           title: '开门成功',
           icon: 'success'
         });
-        
+
         // 将设备信息存储到本地,供购物页面使用
         uni.setStorageSync('currentDeviceId', response.deviceId);
         uni.setStorageSync('currentOutTradeNo', response.outTradeNo);
         uni.setStorageSync('currentOrderNo', response.orderNo);
-        
+
         // 清理可能存在的旧轮询状态标记
         uni.removeStorageSync('shoppingPollingActive');
-        
+
         // 跳转到购物进行中页面
         setTimeout(() => {
           uni.navigateTo({
@@ -177,15 +177,15 @@ const scanCode = async () => {
       } catch (error: any) {
         // 隐藏加载提示
         uni.hideLoading();
-        
+
         console.error('开门失败:', error);
         // 错误信息已经在request工具中显示,这里不需要重复显示
       }
     },
     fail: function (err) {
-      console.log('扫码失败:', err);
+      console.log('扫码取消:', err);
       uni.showToast({
-        title: '扫码失败',
+        title: '扫码取消',
         icon: 'none'
       });
     }

+ 507 - 341
haha-mp/src/pages/payscore/enable.vue

@@ -1,61 +1,72 @@
 <template>
   <view class="container">
-    <!-- 顶部导航栏 -->
-    <view class="header">
-      <view class="back-btn" @click="goBack">
-        <text class="back-icon">‹</text>
+    <!-- 微信风格头部 -->
+    <view class="wx-header">
+      <view class="header-content">
+        <text class="header-title">微信支付分</text>
       </view>
-      <text class="header-title">开通微信支付分</text>
     </view>
 
     <!-- 主要内容区 -->
     <view class="content">
-      <!-- 说明卡片 -->
-      <view class="info-card">
-        <view class="card-header">
-          <image class="payscore-icon" src="/static/icons/payscore.svg" mode="aspectFit"></image>
-          <text class="card-title">微信支付分</text>
+      <!-- 分数要求卡片 - 突出显示 -->
+      <view class="score-card">
+        <view class="score-badge">必需条件</view>
+        <view class="score-main">
+          <text class="score-number">550</text>
+          <text class="score-unit">分及以上</text>
         </view>
-        
-        <view class="card-content">
-          <text class="desc-text">微信支付分是微信支付基于历史行为作出的综合评分,用于评估用户的信用水平。</text>
-          
-          <view class="benefits-section">
-            <text class="benefits-title">开通后可享受:</text>
-            <view class="benefit-item">
-              <text class="benefit-icon">✓</text>
-              <text class="benefit-text">先享后付,开门购物更便捷</text>
+        <view class="score-desc">
+          <text class="desc-icon">ℹ</text>
+          <text class="desc-text">分数越高,可享受的信用服务越多</text>
+        </view>
+      </view>
+
+      <!-- 核心权益 -->
+      <view class="benefits-section">
+        <text class="section-title">核心权益</text>
+        <view class="benefits-grid">
+          <view class="benefit-card">
+            <view class="benefit-icon benefit-icon-1">
+              <text class="icon-emoji">💳</text>
             </view>
-            <view class="benefit-item">
-              <text class="benefit-icon">✓</text>
-              <text class="benefit-text">免押金租借物品</text>
+            <text class="benefit-title">先享后付</text>
+            <text class="benefit-desc">开门后付款</text>
+          </view>
+          
+          <view class="benefit-card">
+            <view class="benefit-icon benefit-icon-2">
+              <text class="icon-emoji">🛡️</text>
             </view>
-            <view class="benefit-item">
-              <text class="benefit-icon">✓</text>
-              <text class="benefit-text">更多信用服务特权</text>
+            <text class="benefit-title">免密支付</text>
+            <text class="benefit-desc">小额自动扣款</text>
+          </view>
+          
+          <view class="benefit-card">
+            <view class="benefit-icon benefit-icon-3">
+              <text class="icon-emoji">⚡</text>
             </view>
+            <text class="benefit-title">快速开门</text>
+            <text class="benefit-desc">秒速开门</text>
           </view>
         </view>
       </view>
 
-      <!-- 分数要求提示 -->
-      <view class="score-requirement">
-        <view class="score-info">
-          <text class="score-label">当前要求</text>
-          <text class="score-value">550 分及以上</text>
-        </view>
-        <view class="score-tip">
-          <text class="tip-icon">ℹ</text>
-          <text class="tip-text">分数越高,可享受的信用服务越多</text>
+      <!-- 详细说明 -->
+      <view class="info-card">
+        <text class="card-title">什么是微信支付分?</text>
+        
+        <view class="card-content">
+          <text class="desc-text">微信支付分是微信支付基于历史行为作出的综合评分,用于评估用户的信用水平。开通后可享受先享后付、免押金等便捷服务。</text>
         </view>
       </view>
 
       <!-- 开通流程 -->
       <view class="steps-section">
-        <text class="section-title">开通流程</text>
+        <text class="section-title">如何开通</text>
         
         <view class="step-item">
-          <view class="step-number">1</view>
+          <view class="step-number step-1">1</view>
           <view class="step-content">
             <text class="step-title">点击开通按钮</text>
             <text class="step-desc">授权开启微信支付分服务</text>
@@ -63,7 +74,7 @@
         </view>
         
         <view class="step-item">
-          <view class="step-number">2</view>
+          <view class="step-number step-2">2</view>
           <view class="step-content">
             <text class="step-title">完成身份验证</text>
             <text class="step-desc">根据提示完成身份信息验证</text>
@@ -71,7 +82,7 @@
         </view>
         
         <view class="step-item">
-          <view class="step-number">3</view>
+          <view class="step-number step-3">3</view>
           <view class="step-content">
             <text class="step-title">等待评分结果</text>
             <text class="step-desc">系统将自动评估您的信用分数</text>
@@ -79,7 +90,7 @@
         </view>
         
         <view class="step-item">
-          <view class="step-number">4</view>
+          <view class="step-number step-4">4</view>
           <view class="step-content">
             <text class="step-title">开通成功</text>
             <text class="step-desc">成功后即可使用先享后付服务</text>
@@ -89,18 +100,23 @@
 
       <!-- 温馨提示 -->
       <view class="tips-section">
-        <text class="tips-title">温馨提示</text>
-        <view class="tip-item">
-          <text class="tip-dot">•</text>
-          <text class="tip-content">微信支付分评估过程不收取任何费用</text>
-        </view>
-        <view class="tip-item">
-          <text class="tip-dot">•</text>
-          <text class="tip-content">请确保已实名认证并绑定银行卡</text>
-        </view>
-        <view class="tip-item">
-          <text class="tip-dot">•</text>
-          <text class="tip-content">良好的信用记录有助于提升分数</text>
+        <view class="tips-card">
+          <text class="tips-icon">💡</text>
+          <view class="tips-content">
+            <text class="tips-title">温馨提示</text>
+            <view class="tip-item">
+              <text class="tip-dot">•</text>
+              <text class="tip-content">微信支付分评估过程不收取任何费用</text>
+            </view>
+            <view class="tip-item">
+              <text class="tip-dot">•</text>
+              <text class="tip-content">请确保已实名认证并绑定银行卡</text>
+            </view>
+            <view class="tip-item">
+              <text class="tip-dot">•</text>
+              <text class="tip-content">良好的信用记录有助于提升分数</text>
+            </view>
+          </view>
         </view>
       </view>
     </view>
@@ -108,12 +124,12 @@
     <!-- 底部操作区 -->
     <view class="footer">
       <button class="enable-button" @click="handleEnablePayscore" :loading="isEnabling">
-        <text class="button-text">立即开通</text>
+        <text class="button-text">{{ isEnabling ? '开通中...' : '立即开通' }}</text>
       </button>
       
-      <view class="help-section">
-        <text class="help-text">遇到问题?</text>
-        <text class="help-link" @click="contactService">联系客服</text>
+      <view class="service-section">
+        <text class="service-text">如有疑问,请联系客服</text>
+        <text class="service-link" @click="contactService">400-123-4567</text>
       </view>
     </view>
   </view>
@@ -121,8 +137,10 @@
 
 <script setup lang="ts">
 import { ref } from 'vue'
+// @ts-ignore
 import { enablePayscore, checkPayscoreEnabled } from '@/api/payscore'
-import { scanDoor } from '@/api/device'
+
+declare const wx: any
 
 const isEnabling = ref(false)
 
@@ -138,32 +156,53 @@ const handleEnablePayscore = async () => {
   try {
     isEnabling.value = true
     
-    // 调用开通接口
-    await enablePayscore()
+    // 调用开通接口,获取支付分订单信息
+    const result = await enablePayscore()
     
-    // 显示成功提示
-    uni.showModal({
-      title: '开通成功',
-      content: '您已成功开通微信支付分,现在可以扫码开门了!',
-      showCancel: false,
-      success: () => {
-        // 跳转到首页或直接返回
-        const pages = getCurrentPages()
-        if (pages.length > 1) {
-          // 如果有上一页,返回时携带开通成功的标记
-          const prevPage = pages[pages.length - 2]
-          if (prevPage && (prevPage as any).onPayscoreEnabled) {
-            ;(prevPage as any).onPayscoreEnabled()
-          }
-          uni.navigateBack()
-        } else {
-          // 否则跳转到首页
-          uni.reLaunch({
-            url: '/pages/index/index'
-          })
+    // 如果已开通,直接提示
+    if (result.enabled) {
+      uni.showModal({
+        title: '已开通',
+        content: '您已开通微信支付分,无需重复开通',
+        showCancel: false,
+        success: () => {
+          goBack()
         }
+      })
+      return
+    }
+    
+    // 调起微信支付分开通页面
+    const { outOrderNo, serviceId, appId } = result
+    
+    if (!outOrderNo || !serviceId) {
+      throw new Error('缺少必要参数')
+    }
+    
+    // 使用微信官方 API 调起支付分开通页面
+    wx.openBusinessView({
+      businessType: 'payscore',
+      extraData: {
+        mch_id: '1612345678', // 商户号,需要替换为真实的
+        service_id: serviceId,
+        out_order_no: outOrderNo
+      },
+      success: (res: any) => {
+        console.log('调起支付分成功:', res)
+        // 用户已完成授权操作,轮询确认开通状态
+        pollEnableStatus(outOrderNo)
+      },
+      fail: (err: any) => {
+        console.error('调起支付分失败:', err)
+        // 用户取消或失败,仍然可以手动确认
+        uni.showModal({
+          title: '提示',
+          content: '开通失败或已取消,请重试',
+          confirmText: '再试一次'
+        })
       }
     })
+    
   } catch (error: any) {
     console.error('开通支付分失败:', error)
     uni.showModal({
@@ -176,6 +215,66 @@ const handleEnablePayscore = async () => {
   }
 }
 
+// 轮询确认开通状态
+const pollEnableStatus = (outOrderNo: string) => {
+  let count = 0
+  const maxCount = 30 // 最多轮询 30 次
+  
+  const timer = setInterval(async () => {
+    count++
+    
+    if (count >= maxCount) {
+      clearInterval(timer)
+      uni.showModal({
+        title: '提示',
+        content: '开通超时,请重新尝试',
+        confirmText: '重试'
+      })
+      return
+    }
+    
+    try {
+      // 调用确认开通接口
+      const response = await fetch('/api/payscore/confirm-enable', {
+        method: 'POST',
+        headers: {
+          'Content-Type': 'application/json'
+        },
+        body: JSON.stringify({ outOrderNo })
+      })
+      
+      const data = await response.json()
+      
+      if (data.code === 'SUCCESS' && data.data?.enabled) {
+        clearInterval(timer)
+        
+        // 开通成功
+        uni.showModal({
+          title: '开通成功',
+          content: '您已成功开通微信支付分,现在可以扫码开门了!',
+          showCancel: false,
+          success: () => {
+            const pages = getCurrentPages()
+            if (pages.length > 1) {
+              const prevPage = pages[pages.length - 2]
+              if (prevPage && (prevPage as any).onPayscoreEnabled) {
+                ;(prevPage as any).onPayscoreEnabled()
+              }
+              uni.navigateBack()
+            } else {
+              uni.reLaunch({
+                url: '/pages/index/index'
+              })
+            }
+          }
+        })
+      }
+    } catch (error) {
+      console.error('轮询开通状态失败:', error)
+    }
+  }, 2000) // 每 2 秒轮询一次
+}
+
 // 联系客服
 const contactService = () => {
   uni.makePhoneCall({
@@ -207,261 +306,327 @@ const checkPayscoreStatus = async () => {
 checkPayscoreStatus()
 </script>
 
-<style>
+<style lang="scss" scoped>
+/* 微信品牌色彩 */
+$wx-green: #07C160;
+$wx-green-dark: #06AD56;
+$wx-green-light: #09D66B;
+$wx-bg: #F7F7F7;
+$wx-card-bg: #FFFFFF;
+$wx-text-primary: #191919;
+$wx-text-secondary: #7D7D7D;
+$wx-text-hint: #B2B2B2;
+$wx-border: #E5E5E5;
+$wx-red: #FA5555;
+$wx-orange: #FF9F00;
+
 .container {
   min-height: 100vh;
-  background-color: #f5f5f5;
+  background: $wx-bg;
   padding-bottom: 200rpx;
 }
 
-/* 顶部导航栏 */
-.header {
-  display: flex;
-  align-items: center;
-  justify-content: space-between;
-  padding: 20rpx 30rpx;
-  background-color: #fff;
-  border-bottom: 1rpx solid #eee;
-}
-
-.back-btn {
-  width: 60rpx;
-  height: 60rpx;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-}
-
-.back-icon {
-  font-size: 60rpx;
-  color: #333;
-  line-height: 1;
-}
-
-.header-title {
-  font-size: 36rpx;
-  font-weight: bold;
-  color: #333;
+/* 微信风格头部 - 纯色背景 */
+.wx-header {
+  width: 100%;
+  background: $wx-green;
+  padding: 32rpx 40rpx 28rpx;
+  box-sizing: border-box;
+  
+  .header-content {
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    justify-content: center;
+    height: 100%;
+  }
+  
+  .header-title {
+    font-size: 36rpx;
+    font-weight: 600;
+    color: #FFFFFF;
+    text-align: center;
+  }
+  
+  .header-subtitle {
+    display: none;
+  }
 }
 
-/* 内容区 */
 .content {
   padding: 30rpx;
 }
 
-/* 信息卡片 */
-.info-card {
-  background-color: #fff;
+/* 分数要求卡片 - 突出显示 */
+.score-card {
+  background: $wx-card-bg;
   border-radius: 20rpx;
-  padding: 40rpx;
+  padding: 40rpx 32rpx;
   margin-bottom: 30rpx;
   box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
+  position: relative;
+  overflow: hidden;
+  
+  .score-badge {
+    position: absolute;
+    top: 20rpx;
+    right: 20rpx;
+    background: $wx-red;
+    color: #FFFFFF;
+    font-size: 22rpx;
+    padding: 8rpx 16rpx;
+    border-radius: 20rpx;
+    font-weight: 500;
+  }
+  
+  .score-main {
+    display: flex;
+    align-items: baseline;
+    justify-content: center;
+    margin: 32rpx 0 24rpx;
+    
+    .score-number {
+      font-size: 96rpx;
+      font-weight: bold;
+      color: $wx-green;
+      line-height: 1;
+    }
+    
+    .score-unit {
+      font-size: 28rpx;
+      color: $wx-text-secondary;
+      margin-left: 16rpx;
+    }
+  }
+  
+  .score-desc {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    background: rgba(7, 193, 96, 0.05);
+    padding: 16rpx 24rpx;
+    border-radius: 12rpx;
+    
+    .desc-icon {
+      font-size: 28rpx;
+      color: $wx-green;
+      margin-right: 12rpx;
+    }
+    
+    .desc-text {
+      font-size: 24rpx;
+      color: $wx-text-secondary;
+    }
+  }
 }
 
-.card-header {
-  display: flex;
-  align-items: center;
-  margin-bottom: 30rpx;
-}
-
-.payscore-icon {
-  width: 80rpx;
-  height: 80rpx;
-  margin-right: 20rpx;
-}
-
-.card-title {
-  font-size: 40rpx;
-  font-weight: bold;
-  color: #FFD700;
-}
-
-.card-content {
-  display: flex;
-  flex-direction: column;
-}
-
-.desc-text {
-  font-size: 28rpx;
-  color: #666;
-  line-height: 1.6;
-  margin-bottom: 30rpx;
-}
-
+/* 核心权益 - 三列布局 */
 .benefits-section {
-  background-color: #f9f9f9;
-  border-radius: 15rpx;
-  padding: 30rpx;
-}
-
-.benefits-title {
-  font-size: 28rpx;
-  font-weight: bold;
-  color: #333;
-  margin-bottom: 20rpx;
-}
-
-.benefit-item {
-  display: flex;
-  align-items: center;
-  margin-bottom: 15rpx;
-}
-
-.benefit-icon {
-  width: 30rpx;
-  height: 30rpx;
-  background-color: #52c41a;
-  color: #fff;
-  border-radius: 50%;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  font-size: 20rpx;
-  margin-right: 15rpx;
-  flex-shrink: 0;
-}
-
-.benefit-text {
-  font-size: 28rpx;
-  color: #333;
+  margin-bottom: 30rpx;
+  
+  .section-title {
+    font-size: 32rpx;
+    font-weight: 600;
+    color: $wx-text-primary;
+    margin-bottom: 24rpx;
+    display: block;
+  }
+  
+  .benefits-grid {
+    display: flex;
+    justify-content: space-between;
+    gap: 20rpx;
+  }
+  
+  .benefit-card {
+    flex: 1;
+    background: $wx-card-bg;
+    border-radius: 16rpx;
+    padding: 32rpx 20rpx;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    text-align: center;
+    box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
+    
+    .benefit-icon {
+      width: 80rpx;
+      height: 80rpx;
+      border-radius: 50%;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      margin-bottom: 20rpx;
+      background: $wx-green;
+        
+      .icon-emoji {
+        font-size: 40rpx;
+        color: #FFFFFF;
+      }
+    }
+    
+    .benefit-title {
+      font-size: 28rpx;
+      font-weight: 600;
+      color: $wx-text-primary;
+      margin-bottom: 8rpx;
+    }
+    
+    .benefit-desc {
+      font-size: 22rpx;
+      color: $wx-text-secondary;
+    }
+  }
 }
 
-/* 分数要求 */
-.score-requirement {
-  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+/* 信息卡片 */
+.info-card {
+  background: $wx-card-bg;
   border-radius: 20rpx;
-  padding: 40rpx;
+  padding: 24rpx 32rpx;
   margin-bottom: 30rpx;
-  color: #fff;
-}
-
-.score-info {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  margin-bottom: 20rpx;
-}
-
-.score-label {
-  font-size: 28rpx;
-  opacity: 0.9;
-}
-
-.score-value {
-  font-size: 48rpx;
-  font-weight: bold;
-}
-
-.score-tip {
-  display: flex;
-  align-items: center;
-  background-color: rgba(255, 255, 255, 0.2);
-  border-radius: 10rpx;
-  padding: 15rpx 20rpx;
-}
-
-.tip-icon {
-  font-size: 32rpx;
-  margin-right: 10rpx;
-}
-
-.tip-text {
-  font-size: 24rpx;
-  opacity: 0.9;
+  box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
+  
+  .card-title {
+    font-size: 32rpx;
+    font-weight: 600;
+    color: $wx-text-primary;
+    margin-bottom: 16rpx;
+    display: block;
+  }
+  
+  .card-content {
+    .desc-text {
+      font-size: 28rpx;
+      color: $wx-text-secondary;
+      line-height: 1.6;
+      display: block;
+    }
+  }
 }
 
 /* 开通流程 */
 .steps-section {
-  background-color: #fff;
+  background: $wx-card-bg;
   border-radius: 20rpx;
-  padding: 40rpx;
+  padding: 40rpx 32rpx;
   margin-bottom: 30rpx;
   box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
-}
-
-.section-title {
-  font-size: 32rpx;
-  font-weight: bold;
-  color: #333;
-  margin-bottom: 30rpx;
-}
-
-.step-item {
-  display: flex;
-  align-items: flex-start;
-  margin-bottom: 30rpx;
-}
-
-.step-item:last-child {
-  margin-bottom: 0;
-}
-
-.step-number {
-  width: 50rpx;
-  height: 50rpx;
-  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-  color: #fff;
-  border-radius: 50%;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  font-size: 24rpx;
-  font-weight: bold;
-  flex-shrink: 0;
-  margin-right: 20rpx;
-}
-
-.step-content {
-  flex: 1;
-  display: flex;
-  flex-direction: column;
-}
-
-.step-title {
-  font-size: 30rpx;
-  font-weight: bold;
-  color: #333;
-  margin-bottom: 8rpx;
-}
-
-.step-desc {
-  font-size: 26rpx;
-  color: #999;
+  
+  .section-title {
+    font-size: 32rpx;
+    font-weight: 600;
+    color: $wx-text-primary;
+    margin-bottom: 32rpx;
+    display: block;
+  }
+  
+  .step-item {
+    display: flex;
+    align-items: flex-start;
+    margin-bottom: 32rpx;
+    
+    &:last-child {
+      margin-bottom: 0;
+    }
+    
+    .step-number {
+      width: 48rpx;
+      height: 48rpx;
+      border-radius: 50%;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      font-size: 28rpx;
+      font-weight: 600;
+      color: #FFFFFF;
+      margin-right: 24rpx;
+      flex-shrink: 0;
+      background: $wx-green;
+      
+      &.step-1,
+      &.step-2,
+      &.step-3,
+      &.step-4 {
+        background: $wx-green;
+      }
+    }
+    
+    .step-content {
+      flex: 1;
+      
+      .step-title {
+        font-size: 28rpx;
+        font-weight: 600;
+        color: $wx-text-primary;
+        display: block;
+        margin-bottom: 8rpx;
+      }
+      
+      .step-desc {
+        font-size: 24rpx;
+        color: $wx-text-secondary;
+        display: block;
+        line-height: 1.4;
+      }
+    }
+  }
 }
 
 /* 温馨提示 */
 .tips-section {
-  background-color: #fff;
-  border-radius: 20rpx;
-  padding: 40rpx;
   margin-bottom: 30rpx;
-  box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
-}
-
-.tips-title {
-  font-size: 32rpx;
-  font-weight: bold;
-  color: #ff9800;
-  margin-bottom: 20rpx;
-}
-
-.tip-item {
-  display: flex;
-  align-items: flex-start;
-  margin-bottom: 15rpx;
-}
-
-.tip-dot {
-  color: #ff9800;
-  font-size: 28rpx;
-  margin-right: 10rpx;
-  flex-shrink: 0;
-}
-
-.tip-content {
-  font-size: 26rpx;
-  color: #666;
-  line-height: 1.6;
+  
+  .tips-card {
+    background: rgba(7, 193, 96, 0.05);
+    border: 2rpx solid rgba(7, 193, 96, 0.2);
+    border-radius: 16rpx;
+    padding: 32rpx 28rpx;
+    display: flex;
+    align-items: flex-start;
+    
+    .tips-icon {
+      font-size: 40rpx;
+      color: $wx-green;
+      margin-right: 20rpx;
+      flex-shrink: 0;
+    }
+    
+    .tips-content {
+      flex: 1;
+      
+      .tips-title {
+        font-size: 28rpx;
+        font-weight: 600;
+        color: $wx-text-primary;
+        display: block;
+        margin-bottom: 16rpx;
+      }
+      
+      .tip-item {
+        display: flex;
+        align-items: flex-start;
+        margin-bottom: 12rpx;
+        
+        &:last-child {
+          margin-bottom: 0;
+        }
+        
+        .tip-dot {
+          color: $wx-green;
+          font-size: 28rpx;
+          margin-right: 12rpx;
+          flex-shrink: 0;
+        }
+        
+        .tip-content {
+          font-size: 24rpx;
+          color: $wx-text-secondary;
+          line-height: 1.6;
+        }
+      }
+    }
+  }
 }
 
 /* 底部操作区 */
@@ -470,47 +635,48 @@ checkPayscoreStatus()
   bottom: 0;
   left: 0;
   right: 0;
-  background-color: #fff;
-  padding: 30rpx;
-  padding-bottom: calc(30rpx + env(safe-area-inset-bottom));
-  border-top: 1rpx solid #eee;
+  background: $wx-card-bg;
+  padding: 32rpx 40rpx;
+  padding-bottom: calc(32rpx + env(safe-area-inset-bottom));
   box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.05);
-}
-
-.enable-button {
-  width: 100%;
-  height: 100rpx;
-  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-  border-radius: 50rpx;
-  border: none;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  margin-bottom: 20rpx;
-  font-size: 32rpx;
-  font-weight: bold;
-  color: #fff;
-}
-
-.button-text {
-  color: #fff;
-}
-
-.help-section {
-  display: flex;
-  align-items: center;
-  justify-content: center;
-}
-
-.help-text {
-  font-size: 26rpx;
-  color: #999;
-}
-
-.help-link {
-  font-size: 26rpx;
-  color: #667eea;
-  margin-left: 10rpx;
-  text-decoration: underline;
+  
+  .enable-button {
+    width: 100%;
+    height: 88rpx;
+    background: $wx-green;
+    border-radius: 44rpx;
+    border: none;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-bottom: 20rpx;
+    
+    &[disabled] {
+      background: $wx-border;
+      opacity: 0.6;
+    }
+    
+    .button-text {
+      font-size: 32rpx;
+      font-weight: 600;
+      color: #FFFFFF;
+    }
+  }
+  
+  .service-section {
+    text-align: center;
+    
+    .service-text {
+      font-size: 24rpx;
+      color: $wx-text-hint;
+      margin-right: 8rpx;
+    }
+    
+    .service-link {
+      font-size: 24rpx;
+      color: $wx-green;
+      font-weight: 500;
+    }
+  }
 }
 </style>