小程序开发-服务端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

4.7 KiB

二维码加密的两种模式详解

问题背景

您提出的问题很关键:用户生成二维码时的token和门店核销时的token是否一样?

在实际业务场景中,这确实是个问题。我们提供了两种解决方案:

模式一:自包含模式(Self-Contained Mode)

特点

  • 二维码包含所有解密所需的信息
  • 扫码方无需额外的密钥或token
  • 适用于点对点的场景

工作流程

1. 用户生成二维码
   ↓
2. 系统生成随机token作为密钥
   ↓
3. 用token加密数据
   ↓
4. 二维码内容 = {token, 加密数据, 类型}
   ↓
5. 任何人扫码都能解密(因为token在二维码中)

二维码内容示例

{
  "token": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
  "data": "encrypted_data_here",
  "type": "encrypted"
}

使用场景

  • 临时分享链接
  • 个人信息展示
  • 一次性验证码

安全性

  • 数据加密保护
  • 支持过期时间
  • ⚠️ 任何人扫码都能解密
  • ⚠️ 二维码泄露 = 数据泄露

模式二:业务模式(Business Mode)

特点

  • 使用统一的业务密钥
  • 门店有预设的解密密钥
  • 支持防重复核销
  • 适用于商业核销场景

工作流程

1. 用户生成二维码
   ↓
2. 使用预设的业务密钥(如门店密钥)加密
   ↓
3. 生成唯一的二维码ID
   ↓
4. 二维码内容 = {二维码ID, 加密数据, 类型}
   ↓
5. 门店用相同的业务密钥解密
   ↓
6. 系统标记该二维码为已使用

二维码内容示例

{
  "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. 用户下单生成二维码

// 用户订单信息
String orderData = "orderId:12345,tableNo:8,amount:88.50";

// 使用餐厅的业务密钥
String restaurantKey = "restaurant_001_secret";

// 生成业务加密二维码
Map<String, Object> result = encryptedQrCodeUtil.generateBusinessEncryptedQrCode(
    orderData, 300, 300, restaurantKey, 60L
);

2. 服务员扫码核销

// 扫码得到的内容
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. 防重复核销

// 第二次扫同一个二维码
try {
    String orderInfo = encryptedQrCodeUtil.verifyAndDecryptQrCodeWithBusinessKey(
        qrContent, "restaurant_001_secret"
    );
} catch (RuntimeException e) {
    // 抛出异常:二维码已被使用
}

API接口对比

自包含模式

# 生成
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"}

业务模式

# 生成
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. 业务模式:门店有预设的业务密钥,用户生成时用这个密钥加密

推荐使用业务模式,因为它更符合实际的商业应用需求,安全性更高,且支持防重复核销。