# 二维码加密的两种模式详解 ## 问题背景 您提出的问题很关键:**用户生成二维码时的token和门店核销时的token是否一样?** 在实际业务场景中,这确实是个问题。我们提供了两种解决方案: ## 模式一:自包含模式(Self-Contained Mode) ### 特点 - 二维码**包含所有解密所需的信息** - 扫码方**无需额外的密钥或token** - 适用于**点对点**的场景 ### 工作流程 ``` 1. 用户生成二维码 ↓ 2. 系统生成随机token作为密钥 ↓ 3. 用token加密数据 ↓ 4. 二维码内容 = {token, 加密数据, 类型} ↓ 5. 任何人扫码都能解密(因为token在二维码中) ``` ### 二维码内容示例 ```json { "token": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6", "data": "encrypted_data_here", "type": "encrypted" } ``` ### 使用场景 - 临时分享链接 - 个人信息展示 - 一次性验证码 ### 安全性 - ✅ 数据加密保护 - ✅ 支持过期时间 - ⚠️ 任何人扫码都能解密 - ⚠️ 二维码泄露 = 数据泄露 --- ## 模式二:业务模式(Business Mode) ### 特点 - 使用**统一的业务密钥** - 门店有**预设的解密密钥** - 支持**防重复核销** - 适用于**商业核销**场景 ### 工作流程 ``` 1. 用户生成二维码 ↓ 2. 使用预设的业务密钥(如门店密钥)加密 ↓ 3. 生成唯一的二维码ID ↓ 4. 二维码内容 = {二维码ID, 加密数据, 类型} ↓ 5. 门店用相同的业务密钥解密 ↓ 6. 系统标记该二维码为已使用 ``` ### 二维码内容示例 ```json { "qrId": "abc123def456", "data": "encrypted_data_here", "type": "business_encrypted", "expire": "1692345678000" } ``` ### 密钥管理 ``` 门店A: businessKey = "store_001_secret_key" 门店B: businessKey = "store_002_secret_key" 门店C: businessKey = "store_003_secret_key" ``` ### 使用场景 - 🎫 **优惠券核销** - 🍔 **餐厅点餐码** - 🎬 **电影票验证** - 🚗 **停车场进出** - 💊 **药品溯源** ### 安全性 - ✅ 数据加密保护 - ✅ 防重复核销 - ✅ 门店权限控制 - ✅ 即使二维码泄露,没有密钥也无法解密 --- ## 实际应用示例 ### 场景:餐厅点餐系统 #### 1. 用户下单生成二维码 ```java // 用户订单信息 String orderData = "orderId:12345,tableNo:8,amount:88.50"; // 使用餐厅的业务密钥 String restaurantKey = "restaurant_001_secret"; // 生成业务加密二维码 Map result = encryptedQrCodeUtil.generateBusinessEncryptedQrCode( orderData, 300, 300, restaurantKey, 60L ); ``` #### 2. 服务员扫码核销 ```java // 扫码得到的内容 String qrContent = "{\"qrId\":\"abc123\",\"data\":\"encrypted...\",\"type\":\"business_encrypted\"}"; // 使用餐厅密钥解密 String orderInfo = encryptedQrCodeUtil.verifyAndDecryptQrCodeWithBusinessKey( qrContent, "restaurant_001_secret" ); // 结果:orderId:12345,tableNo:8,amount:88.50 ``` #### 3. 防重复核销 ```java // 第二次扫同一个二维码 try { String orderInfo = encryptedQrCodeUtil.verifyAndDecryptQrCodeWithBusinessKey( qrContent, "restaurant_001_secret" ); } catch (RuntimeException e) { // 抛出异常:二维码已被使用 } ``` --- ## API接口对比 ### 自包含模式 ```http # 生成 POST /api/qr-code/create-encrypted-qr-code data=user_info&width=200&height=200&expireMinutes=30 # 解密(任何人都可以) POST /api/qr-code/verify-and-decrypt-qr qrContent={"token":"...","data":"...","type":"encrypted"} ``` ### 业务模式 ```http # 生成 POST /api/qr-code/create-business-encrypted-qr-code data=order_info&businessKey=store_001_key&width=200&height=200&expireMinutes=60 # 核销(需要对应的业务密钥) POST /api/qr-code/verify-business-qr qrContent={"qrId":"...","data":"...","type":"business_encrypted"}&businessKey=store_001_key ``` --- ## 选择建议 | 场景 | 推荐模式 | 原因 | |------|----------|------| | 个人信息分享 | 自包含模式 | 简单方便,无需额外配置 | | 临时链接分享 | 自包含模式 | 接收方无需特殊权限 | | 商业核销 | 业务模式 | 安全性高,防重复使用 | | 门店验证 | 业务模式 | 权限控制,业务流程完整 | | 支付码 | 业务模式 | 安全要求高 | | 会员卡 | 业务模式 | 需要权限验证 | --- ## 总结 **您的疑问是对的!** 在门店核销场景中: 1. **自包含模式**:token在二维码中,门店直接扫码即可解密 2. **业务模式**:门店有预设的业务密钥,用户生成时用这个密钥加密 **推荐使用业务模式**,因为它更符合实际的商业应用需求,安全性更高,且支持防重复核销。