Files
daycard-app/卡密导入激活鉴权流程.md
2026-07-26 12:43:59 +08:00

11 KiB
Raw Permalink Blame History

卡密-导入-激活-鉴权 完整流程文档

一、整体流程概览

┌─────────────────────────────────────────────────────────────────────┐
│                        一次性前置准备                                 │
│  ① 导入卡密    ② 配置橘视厅平台参数    ③ 注册设备                     │
└─────────────────────────────────────────────────────────────────────┘
                                  ↓
┌─────────────────────────────────────────────────────────────────────┐
│                        用户运行时流程                                 │
│  ④ 点击播放 → ⑤ 创建订单 → ⑥ 支付 → ⑦ 支付回调触发异步激活             │
│                                  ↓                                    │
│  ⑧ 橘视厅API激活卡密(3步HTTP调用)                                    │
│                                  ↓                                    │
│  ⑨ 查询权益获取thirdCardNo → ⑩ SDK初始化 → ⑪ 获取视频地址 → ⑫ 播放    │
└─────────────────────────────────────────────────────────────────────┘

二、各环节详解

① 卡密导入

项目 内容
执行位置 as-daycard-openapi 后端
触发方式 管理员调用 POST /openapi/daycard/pool/import
代码位置 DayCardPoolServiceImpl.importCards()
输入 橘视厅真实激活码(cardCode),如 ASXXXXXX
处理 为每个cardCode自动生成 thirdCardNo(随机数字+字母串),写入 day_card_pool 表,status=UNUSED
产出 day_card_pool 表新增记录:cardCode + thirdCardNo + status=UNUSED
关键 cardCode必须是橘视厅平台真实有效的激活码,否则后续激活会失败

② 配置橘视厅平台参数

项目 内容
执行位置 as-daycard-openapi 后端数据库
存储位置 sys_config 表,param_key=JST_PLATFORM_CONFIG
配置内容 jushitingBaseUrl / jushitingAccesser / jushitingBusinessLine / jushitingLoginRsaPublicKey / jushitingActivateSignKey / vipQueryBaseUrl
来源 从生产环境 as-partner-backend 的 sys_config 表复制
作用 后端调用橘视厅API时的鉴权参数

③ 设备注册

项目 内容
执行位置 as-daycard-openapi 后端 + MediaApp
触发方式 管理后台 POST /manage/device/save 或自动创建
代码位置 DeviceController.save() → DeviceServiceImpl
产出 device 表新增记录,deviceId=1(当前测试设备)
App引用 DayCardConfig.DEVICE_ID = 1L(硬编码)

④ 点击播放

项目 内容
执行位置 MediaApp(Android端)
代码位置 DetailActivity.btnPlay.onClick → startPaymentFlow()
动作 调用天卡后端 GET /openapi/media/play-permission/{mediaId}?deviceId=1
目的 检查设备是否已有播放权限(是否已支付过且未过期)

⑤ 创建订单

项目 内容
执行位置 as-daycard-openapi 后端
触发方式 App调用 POST /openapi/daycard/create
代码位置 DayCardOrderServiceImpl.createOrder()
处理 1. Redis防重锁 2. 从 day_card_pool 中 SELECT...FOR UPDATE SKIP LOCKED 抢一张UNUSED的卡 3. 卡状态 UNUSED→RESERVED 4. 创建订单 status=CREATED
产出 day_card_order 表新增订单 + 卡状态变为RESERVED

⑥ 支付

项目 内容
执行位置 MediaApp + as-daycard-openapi 后端
测试方式 App调用 POST /openapi/payment/mock-pay/{orderNo}
生产方式 微信扫码支付 POST /openapi/payment/native/create
代码位置 DayCardOrderServiceImpl.mockPay() 或微信支付回调

⑦ 支付回调触发异步激活

项目 内容
执行位置 as-daycard-openapi 后端
代码位置 DayCardOrderServiceImpl.payCallback()
处理 1. 订单 status→PAID 2. 卡状态 RESERVED→USED 3. 设置初始expire_at(24h兜底) 4. 触发 @Async asyncActivateCard(order)
关键 异步激活不阻塞支付回调返回,App此时已收到支付成功

⑧ 橘视厅API激活卡密(3步HTTP调用)

项目 内容
执行位置 as-daycard-openapi 后端(异步线程池 thirdPartyActivateExecutor)
代码位置 DayCardOrderServiceImpl.asyncActivateCard() → JushitingApiServiceImpl

Step 1: 免密登录获取Token

JushitingApiServiceImpl.getToken(device, thirdCardNo)
  → POST {jushitingBaseUrl}/ums_api/api/v1/third/login
  → 参数: uid=thirdCardNo, mac={thirdCardNo}_bul_{businessLine}, accesser, businessLine, nonce, timestamp, serviceComboCode
  → 签名: RSA加密(用jushitingLoginRsaPublicKey)
  → 返回: token + memberCode

Step 2: 卡密激活

JushitingApiServiceImpl.activateCard(deviceId, cardCode, memberCode, token)
  → POST {jushitingBaseUrl}/ccms_api/hswj/api/card/activate?sign=xxx
  → 参数: activateCode=cardCode, memberCode, timestamp, serviceComboCode
  → 签名: MD5(activateCode&memberCode&timestamp&key={jushitingActivateSignKey}).toUpperCase()
  → 返回: status=true + expireTime
  → 此时橘视厅平台建立了 thirdCardNo → 用户 → 订购关系

Step 3: 查询VIP到期时间(仅Step2未返回expireTime时)

JushitingApiServiceImpl.queryVipExpireTime(deviceId, thirdCardNo)
  → POST {vipQueryBaseUrl}/ums_api/member/uid/queryVipInfo
  → 参数: uid=thirdCardNo, businessLine, requestTime, sign
  → 签名: MD5(businessLine + requestTime + uid + key).toUpperCase(), key="c25svtwbTyCE"
  → 返回: vipExpireTime

激活完成后更新数据库

day_card_pool: activate_status=SUCCESS, activated_at=now, expire_at=真实到期时间

⑨ 查询权益获取thirdCardNo

项目 内容
执行位置 as-daycard-openapi 后端
触发方式 App调用 GET /openapi/daycard/benefits/{deviceId}
代码位置 DayCardOrderController.benefits() → DayCardOrderServiceImpl.getDeviceBenefits()
SQL SELECT...FROM day_card_pool WHERE device_id=? AND status='USED' AND expire_at > NOW() ORDER BY used_at DESC LIMIT 1
返回 { hasBenefits: true, thirdCardNo: "xxx", cardCode: "xxx", expireAt: "xxx" }

⑩ SDK初始化

项目 内容
执行位置 MediaApp(Android端)
代码位置 DetailActivity.fetchVideoUrlAndPlay() → JetsenxSdkUtil.init(ctx, thirdCardNo, ...)
参数 uid=thirdCardNo, utype=2(第三方ID), agcode, tenant, secret, accesser
SDK内部 JetsenxSdk向捷成平台注册用户身份,获取memberCode
关键 此时橘视厅平台已有该thirdCardNo的订购关系(⑧步已建立)

⑪ 获取视频地址

项目 内容
执行位置 MediaApp(Android端)→ JetsenxSdk → 橘视厅平台
代码位置 JetsenxSdkUtil.getAllVideoUrl()
流程 1. getAllAssetPrices() 获取productCode 2. 根据parentContentType判断免费/付费 3. getVideoUrls() 或 getFreeVideoUrls()
返回 VideoInfo[]: videoUrl(1080p/720p), format, movieCode
前提 SDK已用有效thirdCardNo初始化 + 平台有订购关系

⑫ 播放

项目 内容
执行位置 MediaApp(Android端)
代码位置 VideoPlayerActivity → ExoPlayer
动作 用获取到的视频URL播放

三、当前阻滞点

① 卡密导入 → ❌ 导入的是mock卡密 DAYCARD-TEST-003,不是橘视厅真实激活码
② 平台配置 → ❌ sys_config中JST_PLATFORM_CONFIG可能未配置
     ↓
⑧ 激活卡密 → ❌ getToken()返回null(baseUrl为空) 或 activateCard()失败(卡密无效)
     ↓
橘视厅平台无 thirdCardNo 的订购关系
     ↓
⑩ SDK初始化 → ✅ 成功(允许任意uid登录)
⑪ 获取视频地址 → ❌ -110未订购 / 604身份无效

四、打通链路的前置条件

  1. 从生产环境获取真实的橘视厅卡密(cardCode)
  2. 从生产环境 sys_config 表复制 JST_PLATFORM_CONFIG 配置值
  3. 清除当前mock卡密,用真实卡密重新导入天卡池

五、关键代码文件索引

MediaApp(Android端)

文件 作用
MediaApp/.../ui/DetailActivity.kt 详情页,播放流程入口
MediaApp/.../sdk/JetsenxSdkUtil.kt JetsenxSdk封装,SDK初始化+获取视频地址
MediaApp/.../ui/VideoPlayerActivity.kt ExoPlayer播放器
MediaApp/.../network/DayCardApiService.kt 天卡API接口定义
MediaApp/.../viewmodel/PaymentViewModel.kt 天卡支付流程
MediaApp/.../config/DayCardConfig.kt 天卡配置(设备ID、金额等)
MediaApp/.../config/ApiConfig.kt 媒资API配置

as-daycard-openapi(本项目后端)

文件 作用
.../daycard/controller/DayCardOrderController.java 天卡订单Controller(创建/状态/权益)
.../daycard/service/impl/DayCardOrderServiceImpl.java 订单核心逻辑(createOrder/payCallback/asyncActivateCard/getDeviceBenefits)
.../daycard/service/impl/DayCardPoolServiceImpl.java 天卡池管理(导入/抢卡)
.../jst/service/impl/JushitingApiServiceImpl.java 橘视厅API调用(getToken/activateCard/queryVipExpireTime)
.../jst/service/JstActivateCardResult.java 卡密激活结果
.../device/controller/DeviceController.java 设备管理
.../media/controller/MediaController.java 媒资/播放权限

生产环境参考代码

文件 作用
app/.../request/AsApiRequester.java 生产环境AS接口(init/check/checkBenefits/activate)
app/.../utils/JetsenxSdkUtil.java 生产环境SDK工具类
app/.../video/VideoDetailActivity.java 生产环境详情页(完整播放流程)
app/.../MainActivity.java 生产环境主页(SDK初始化入口)
app/.../config/AppConfiguration.java 生产环境配置(AS基础地址)