document/营销系统下线迁移方案-会议版.html

599 lines
43 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>营销系统下线与易码通迁移方案</title>
<style>
:root {
--primary: #1a3a6b;
--accent: #2b6cb0;
--bg: #f5f7fa;
--card: #ffffff;
--text: #1f2937;
--muted: #6b7280;
--green: #0e9f6e;
--green-bg: #e6f7f0;
--orange: #d97706;
--orange-bg: #fdf3e3;
--blue: #2563eb;
--blue-bg: #e8effc;
--red: #dc2626;
--red-bg: #fdecec;
--border: #e5e7eb;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: "PingFang SC","Microsoft YaHei","Helvetica Neue",Arial,sans-serif; background: var(--bg); color: var(--text); line-height: 1.65; font-size: 15px; }
.wrap { max-width: 1180px; margin: 0 auto; padding: 0 24px 80px; }
/* ===== 顶部横幅 ===== */
.hero { background: linear-gradient(135deg, #0f2a52 0%, #1a3a6b 55%, #2b6cb0 100%); color: #fff; padding: 52px 0 44px; margin-bottom: 36px; }
.hero .wrap { padding-bottom: 0; }
.hero h1 { font-size: 34px; font-weight: 700; letter-spacing: 1px; }
.hero .sub { margin-top: 10px; font-size: 16px; opacity: .92; }
.hero .meta { margin-top: 18px; display: flex; gap: 10px; flex-wrap: wrap; }
.hero .meta span { background: rgba(255,255,255,.14); border: 1px solid rgba(255,255,255,.25); padding: 4px 14px; border-radius: 20px; font-size: 13px; }
/* ===== 导航 ===== */
.nav { position: sticky; top: 0; z-index: 50; background: rgba(255,255,255,.96); backdrop-filter: blur(6px); border-bottom: 1px solid var(--border); }
.nav .wrap { display: flex; gap: 4px; flex-wrap: wrap; padding-top: 0; padding-bottom: 0; }
.nav a { display: block; padding: 14px 14px; font-size: 14px; color: var(--primary); text-decoration: none; border-bottom: 3px solid transparent; font-weight: 500; }
.nav a:hover { border-bottom-color: var(--accent); color: var(--accent); }
/* ===== 章节 ===== */
section { margin-top: 40px; }
.sec-title { display: flex; align-items: center; gap: 12px; font-size: 24px; font-weight: 700; color: var(--primary); padding-bottom: 12px; border-bottom: 2px solid var(--accent); margin-bottom: 20px; }
.sec-title .num { background: var(--primary); color: #fff; width: 34px; height: 34px; border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 16px; flex-shrink: 0; }
h3 { font-size: 17px; color: var(--primary); margin: 26px 0 12px; }
h4 { font-size: 15px; margin: 18px 0 8px; }
.card { background: var(--card); border: 1px solid var(--border); border-radius: 10px; padding: 22px 26px; margin-bottom: 18px; box-shadow: 0 1px 3px rgba(0,0,0,.04); }
/* ===== 表格 ===== */
table { width: 100%; border-collapse: collapse; margin: 12px 0; font-size: 14px; background: #fff; }
th { background: #f0f4f9; color: var(--primary); font-weight: 600; text-align: left; padding: 10px 12px; border: 1px solid var(--border); white-space: nowrap; }
td { padding: 9px 12px; border: 1px solid var(--border); vertical-align: top; }
tr:nth-child(even) td { background: #fafbfd; }
td.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* ===== 标签 ===== */
.tag { display: inline-block; padding: 2px 10px; border-radius: 12px; font-size: 12px; font-weight: 600; white-space: nowrap; }
.tag.ok { background: var(--green-bg); color: var(--green); }
.tag.dev { background: var(--orange-bg); color: var(--orange); }
.tag.relay { background: var(--blue-bg); color: var(--blue); }
.tag.keep { background: #f3f4f6; color: var(--muted); }
.tag.warn { background: var(--red-bg); color: var(--red); }
/* ===== 高亮框 ===== */
.notice { border-left: 4px solid var(--accent); background: #eef4fc; padding: 12px 16px; border-radius: 0 8px 8px 0; margin: 14px 0; font-size: 14px; }
.notice.red { border-left-color: var(--red); background: var(--red-bg); }
.notice.green { border-left-color: var(--green); background: var(--green-bg); }
/* ===== 指标卡 ===== */
.metrics { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin: 16px 0; }
.metric { background: var(--card); border: 1px solid var(--border); border-radius: 10px; padding: 16px 18px; text-align: center; box-shadow: 0 1px 3px rgba(0,0,0,.04); }
.metric .m-num { font-size: 30px; font-weight: 800; color: var(--primary); font-variant-numeric: tabular-nums; line-height: 1.1; }
.metric .m-label { font-size: 13px; color: var(--muted); margin-top: 4px; }
.metric.hot { border-top: 3px solid var(--orange); }
.metric.warn { border-top: 3px solid var(--red); }
/* ===== 客户方案矩阵 ===== */
.client-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin: 14px 0; }
.client-cell { border-radius: 10px; padding: 14px 16px; border: 1px solid var(--border); background: #fff; }
.client-cell h4 { margin: 0 0 6px; font-size: 14px; color: var(--primary); }
.client-cell ul { padding-left: 16px; margin: 0; font-size: 13px; }
.client-cell li { margin: 3px 0; }
.client-cell.green { border-top: 3px solid var(--green); }
.client-cell.orange { border-top: 3px solid var(--orange); }
.client-cell.blue { border-top: 3px solid var(--blue); }
.client-cell.gray { border-top: 3px solid var(--muted); }
/* ===== 时间轴 ===== */
.timeline { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0; margin: 18px 0; }
.tl-step { position: relative; padding: 0 14px; text-align: center; }
.tl-step:not(:last-child)::after { content: ""; position: absolute; top: 16px; left: 50%; width: 100%; height: 3px; background: var(--accent); opacity: .35; }
.tl-dot { position: relative; z-index: 1; width: 34px; height: 34px; margin: 0 auto 8px; border-radius: 50%; background: var(--primary); color: #fff; font-weight: 700; display: flex; align-items: center; justify-content: center; }
.tl-title { font-weight: 700; color: var(--primary); font-size: 15px; }
.tl-desc { font-size: 12px; color: var(--muted); margin-top: 4px; line-height: 1.5; }
@media (max-width: 900px) { .metrics, .client-grid { grid-template-columns: repeat(2, 1fr); } .timeline { grid-template-columns: 1fr 1fr; gap: 14px; } }
/* ===== 架构图 ===== */
.flow { display: flex; flex-direction: column; align-items: stretch; gap: 0; margin: 18px 0; }
.flow-row { display: flex; justify-content: center; gap: 16px; flex-wrap: wrap; }
.node { background: #fff; border: 2px solid var(--accent); border-radius: 10px; padding: 14px 22px; min-width: 150px; text-align: center; font-weight: 600; color: var(--primary); }
.node.solid { background: var(--accent); color: #fff; }
.node.gray { border-color: var(--muted); color: var(--muted); background: #f9fafb; }
.node.green { border-color: var(--green); color: var(--green); background: var(--green-bg); }
.arrow-down { text-align: center; font-size: 22px; color: var(--accent); line-height: 1; padding: 6px 0; }
.arrow { text-align: center; font-size: 15px; color: var(--accent); padding: 6px 0; }
/* ===== 列表 ===== */
ul.tick, ol.tick { padding-left: 22px; margin: 10px 0; }
ul.tick li, ol.tick li { margin: 6px 0; }
ul.tick li::marker { color: var(--accent); }
b.hl { color: var(--primary); }
/* ===== 结论页 ===== */
.summary { background: linear-gradient(135deg, #0f2a52, #1a3a6b); color: #fff; border-radius: 12px; padding: 36px 40px; }
.summary h2 { font-size: 22px; margin-bottom: 18px; border-bottom: 1px solid rgba(255,255,255,.25); padding-bottom: 12px; }
.summary .big { font-size: 17px; line-height: 1.8; }
.summary .grid { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; margin-top: 18px; }
.summary .box { background: rgba(255,255,255,.08); border: 1px solid rgba(255,255,255,.18); border-radius: 10px; padding: 16px 20px; }
.summary .box h3 { color: #ffd166; margin: 0 0 10px; font-size: 15px; }
.summary ul { padding-left: 20px; }
.summary li { margin: 5px 0; font-size: 14px; }
.footer { text-align: center; color: var(--muted); font-size: 12px; margin-top: 40px; }
@media (max-width: 768px) { .summary .grid { grid-template-columns: 1fr; } .hero h1 { font-size: 26px; } }
</style>
</head>
<body>
<!-- ================= 总 ================= -->
<div class="hero">
<div class="wrap">
<h1>营销系统下线与易码通迁移方案</h1>
<div class="sub">关停创建入口 · 能力对比 · 客户分类 · 中转网关 · 回调处理 · 执行路线</div>
<div class="meta">
<span>存量数据快照:2026-09-07(主库 market 只读副本)</span>
<span>文档时间:2026-09-16</span>
<span>75 张表 / ≈1.1TB</span>
</div>
</div>
</div>
<div class="nav">
<div class="wrap">
<a href="#s1">1. 总 · 关停与对比</a>
<a href="#s2">2. 系统现状</a>
<a href="#s3">3. 客户对接分析</a>
<a href="#s4">4. OpenAPI 中转</a>
<a href="#s5">5. 回调处理</a>
<a href="#s6">6. 后台创建能力</a>
<a href="#s7">7. 执行路线</a>
<a href="#s8">8. 总结</a>
</div>
</div>
<div class="wrap">
<!-- ================= 一、总:关停与能力对比 ================= -->
<section id="s1">
<div class="sec-title"><span class="num">01</span>关停与能力对比</div>
<div class="card">
<h3>1.1 既定目标(基调)</h3>
<ul class="tick">
<li><b class="hl">新的业务不再接入当前系统</b> —— 关闭营销系统所有<b>创建入口</b>(后台新建计划/批次、OpenAPI 发码写接口、分销商后台入口)。</li>
<li><b class="hl">老业务继续跑,服务不停</b> —— 只停入口,不停服务:存量计划的核销、C 端访问、立减金发放、回调接收、财务对账全部保留。</li>
<li><b class="hl">涉及对接的客户迁往易码通</b>;若用户不愿迁移,由我们开发<b>中转项目反向对接用户</b>。</li>
<li><b class="hl">易码通需支持营销系统后台的创建能力</b>:创建分销商、应用、计划、批次、key 码。</li>
</ul>
</div>
<div class="card">
<h3>1.2 能力全景对比(易码通 vs 营销系统)</h3>
<table>
<tr>
<th style="width:24%">能力域</th>
<th style="width:14%">结论</th>
<th style="width:62%">说明</th>
</tr>
<tr>
<td><b>后台 · 创建分销商 / 客户</b></td>
<td><span class="tag ok">✅ 已覆盖</span></td>
<td>易码通 <code>POST /admin/v1/merchant/create</code>。注意:易码通 <b>merchant = 营销系统的分销商(reseller)</b>,自带余额/授信/冻结账户,并保留 <code>direct_reseller_id</code> 老系统映射。</td>
</tr>
<tr>
<td><b>后台 · 创建应用(app_id)</b></td>
<td><span class="tag ok">✅ 已覆盖</span></td>
<td>易码通 <code>POST /admin/v1/merchant/app/create</code>,含 app_id、商户RSA公钥、notify_url、sign_type,支持事件订阅与密钥重置。</td>
</tr>
<tr>
<td><b>后台 · 创建计划</b></td>
<td><span class="tag ok">✅ 已覆盖</span></td>
<td>易码通 <code>POST /admin/v1/activity/create</code>(计划≈活动 activity),含 key 总量、有效期、结算方式、绑定客户。⚠️ 需过钉钉审批才能生效、生效后才能建批次(见 6.2)。</td>
</tr>
<tr>
<td><b>后台 · 创建批次 / key 码</b></td>
<td><span class="tag ok">✅ 已覆盖</span></td>
<td>易码通 <code>POST /admin/v1/key_batch/create</code>(导码任务,单次 ≤10 万),生成 zip+密码,可下载/邮件。key 作废/延时/核销/统计均有接口。</td>
</tr>
<tr>
<td><b>OpenAPI · A 类 券包下单</b></td>
<td><span class="tag ok">✅ 已覆盖</span></td>
<td>营销系统 <code>/openapi/v1/market/AlipayCoupon/*</code>(无验签)→ 易码通 <code>key/order</code>、<code>key/query</code>,<b>协议需更换</b>。</td>
</tr>
<tr>
<td><b>OpenAPI · B 类 key 发码</b></td>
<td><span class="tag ok">✅ 已覆盖</span></td>
<td>营销系统 <code>send/discard/query</code> → 易码通 <code>order/batch_order/discard/query/batch_query/renew/exchange</code>,<b>验签体系需转换</b>。</td>
</tr>
<tr>
<td><b>OpenAPI · B 类 批量生成+文件回传</b></td>
<td><span class="tag dev">🔧 需开发</span></td>
<td>营销系统 <code>generate/postbank</code>、<code>lock/postbank</code>、<code>pushDataFile</code>(邮储批量生成 key 文件回传)——易码通 openapi <b>无对应接口</b>(内部有导码能力,缺开放通道),需开发或中转层补齐。</td>
</tr>
<tr>
<td><b>立减金(券)体系</b><br><span style="font-weight:400;color:#6b7280">主体/商品/批次/订单/核销</span></td>
<td><span class="tag ok">✅ 已覆盖</span></td>
<td>易码通具备完整立减金能力:券主体(<b>支付宝/微信/云闪付</b>)、券商品与批次(activity/goods/voucher)、券订单(order/voucher),接口普遍标注 <code>[迁移来源] 老系统 Order.OrderVoucher.*</code>;后台管理 <code>/admin/v1/coupon/*</code>。详见 5.1。</td>
</tr>
<tr>
<td><b>OpenAPI · C 类 立减金核销回调</b></td>
<td><span class="tag keep">✅ 存量留守</span></td>
<td>C 类 = 行方把<b>支付宝立减金核销通知</b>推给我们、更新券码状态。该链路只改存量券状态、不触发新创建 → <b>留守老系统,接口不动</b>。易码通已具备同等能力(<code>/v1/order/voucher/notify</code>,含 NotifyVoucher/Used/Expired/Refunded),仅当<b>新业务改在易码通发立减金券</b>时才需迁移,届时把行方报文适配到该统一入口。</td>
</tr>
<tr>
<td><b>OpenAPI · D 类 主动通知</b></td>
<td><span class="tag relay">🔄 需中转</span></td>
<td>易码通已具备事件订阅与通知重试能力(merchant_notify list/retry),但向行方推送的<b>报文结构 / 签名(国密)/ 幂等语义与老系统差异大</b>,且行方不改造接收端 → 由中转层把易码通事件翻译成行方既有格式再推送。</td>
</tr>
<tr>
<td><b>验签体系</b></td>
<td><span class="tag relay">🔄 中转 + 需开发</span></td>
<td>易码通现有统一 <b>RSA-SHA256 + AES-256-ECB-PKCS7</b>(每商户一套密钥)。<b>银行渠道</b>(兴业/邮储国密)走中转层国密↔RSA 转换;<b>分销商/普通客户</b>因易码通客户来自 CRM、与营销系统分销商不对齐,考虑在易码通<b>新增 basic_auth 验签类型</b>统一承接新接入方(其 reseller_api_setting 表已预留 secret_key/sign/IP 白名单/接口授权等分销商级鉴权模型)。</td>
</tr>
<tr>
<td><b>资金账户 / 结算</b></td>
<td><span class="tag ok">✅ 无需迁移余额</span></td>
<td><b>已查实(2026-09-16 连库核对)</b>:营销系统内<b>没有分销商预充值余额池</b> —— 无余额表、无充值流水,发码表 <code>merchant_key_send</code> 无任何金额字段(<b>发码不扣款</b>)。结算链路大部分<b>已废弃</b>:结算导出 <code>settlement_export_record</code> 停更 2024-12、月度对账 <code>summaryresellerorder</code> 停更 2024-07、<code>settlement_order</code> 99.9%(272 万条)停在 2024-12-31,<b>仅邮储一家</b>(type=5,约 704 条/月)仍活跃。计价规则在 <code>key_batch.key_cost_price/key_official_price</code>;易码通已有更完整体系(成本价/合同价/官方价 + 4 种结算方式)。</td>
</tr>
</table>
<div class="notice green"><b>重要背景:</b>易码通并非"另一套系统",而是营销系统的<b>重构承接平台</b> —— 其代码中大量接口标注 <code>[迁移来源] Order.OrderVoucher.*</code> 等老系统方法名,老系统能力正按模块迁移到易码通。本次工作的实质是<b>加速并收口这条既定迁移线</b>。</div>
<div class="notice"><b>一句话结论:</b>易码通<b>后台创建能力、立减金(券)体系、发码主链路均已覆盖</b>,C 类核销回调<b>留守老系统不动</b>;需补齐三块 —— ① <b>邮储批量生成文件回传</b>(开发开放通道)、② <b>银行国密验签</b>(走中转)、③ <b>分销商 basic_auth 验签</b>(易码通新增验签类型)。</div>
</div>
</section>
<!-- ================= 二、系统现状 ================= -->
<section id="s2">
<div class="sec-title"><span class="num">02</span>系统现状(存量盘点)</div>
<div class="metrics">
<div class="metric"><div class="m-num">75</div><div class="m-label">数据表</div></div>
<div class="metric"><div class="m-num">1.1<span style="font-size:16px">TB</span></div><div class="m-label">磁盘占用</div></div>
<div class="metric"><div class="m-num">9130</div><div class="m-label">计划总数</div></div>
<div class="metric hot"><div class="m-num">1394</div><div class="m-label">未结束计划</div></div>
<div class="metric hot"><div class="m-num">9008</div><div class="m-label">未结束 key 批次</div></div>
<div class="metric hot"><div class="m-num">2224<span style="font-size:16px">万</span></div><div class="m-label">待发 key 库存</div></div>
<div class="metric"><div class="m-num">137</div><div class="m-label">活跃分销商(180 天)</div></div>
<div class="metric warn"><div class="m-num">6</div><div class="m-label">API 对接客户</div></div>
</div>
<div class="card">
<table>
<tr><th style="width:30%">维度</th><th style="width:20%">数值</th><th>说明</th></tr>
<tr><td>表数量 / 磁盘占用</td><td class="num">75 张 / ≈1.1TB</td><td>主库 market(阿里云成都 RDS 只读副本,MySQL 5.7.28)</td></tr>
<tr><td>计划总数</td><td class="num">9130</td><td>未删除 8893,<b>未结束 1394</b></td></tr>
<tr><td>未结束 key 批次</td><td class="num">9008</td><td>近 180 天新建 4100+</td></tr>
<tr><td>待发 key 库存</td><td class="num"><b>2224 万</b></td><td>计划生成 key 总量 2230 万</td></tr>
<tr><td>活跃分销商(180 天)</td><td class="num">137 家</td><td>银行 30+ 家 / 商业地产约 40 家 / 普通企业若干 / 测试约 10 家</td></tr>
<tr><td>对接客户 merchant_id</td><td class="num">全库 12 个 / <b>活跃 6 家</b></td><td>4 家 key 类 + 2 家券包类(详见第 3 章)</td></tr>
<tr><td>服务状态</td><td colspan="2"><span class="tag warn">仍在活跃运行</span> 核心表分钟级写入:发码、事件通知、券批次、审批、结算</td></tr>
<tr><td>超大表 Top5</td><td colspan="2">order_detail 468GB · order_voucher 255GB · event_notify 197GB · order 62GB · key_period_recharge 16GB</td></tr>
</table>
<div class="notice red"><b>关键风险:</b>兴业银行有 <b>568 个未结束计划</b>,最晚到期 <b>2031-12-31</b>。若不处理,老系统至少要再运行 5 年 —— 这决定了"存量消化"阶段的时间下限。</div>
</div>
</section>
<!-- ================= 三、客户对接分析 ================= -->
<section id="s3">
<div class="sec-title"><span class="num">03</span>客户对接分析与分类方案</div>
<div class="card">
<h3>3.1 角色层级(先分清两种客户)</h3>
<table>
<tr><th style="width:22%">层级</th><th style="width:26%">定义</th><th style="width:16%">数量</th><th>与迁移的关系</th></tr>
<tr>
<td><b>reseller(分销商)</b></td>
<td>签合同/开账号的上游客户,用<b>后台 + C 端</b>建计划、批次、导 key</td>
<td class="num">137 家活跃</td>
<td>绝大多数不走开放 API。<b>迁移动作 = 新分销商直接在易码通开通</b>(basic_auth 接入);存量分销商因易码通客户来自 CRM、与营销系统不对齐,需先建 <b>映射表(营销 reseller ↔ CRM/易码通客户)</b> 或按 CRM 重新开通。</td>
</tr>
<tr>
<td><b>merchant(API 对接商户)</b></td>
<td>通过<b>开放 API</b> 发码/作废/查询 + 收事件推送的系统级对接方</td>
<td class="num">全库 12 / 活跃 6</td>
<td><b>迁移 / 中转的真实对象</b>,即本文重点。</td>
</tr>
</table>
<div class="notice">137 家分销商与 6 家对接客户<b>不是同一件事</b>:前者 90% 以上只是用后台建活动,停掉入口后自然流向易码通;真正需要技术处理的是 6 家 API 对接方。</div>
</div>
<div class="card">
<h3>3.2 API 对接客户清单与分类(6 家)</h3>
<table>
<tr>
<th>客户</th><th>merchant_id</th><th>归属分销商</th><th>接口类型</th><th>发码量 / 事件量</th><th>活跃度</th><th>方案</th>
</tr>
<tr>
<td><b>蓝星严选</b>(连续包月)</td><td>—</td><td>—</td><td>A 券包下单</td><td>券包订单(同日见 openapi_order 与 order)</td><td>🟢</td>
<td><span class="tag relay">存量中转 + 新业务直连</span><br>存量业务中转层代签兜底;新业务直接对接易码通(免中转)</td>
</tr>
<tr>
<td><b>阅璟</b></td><td>—</td><td>—</td><td>A 券包下单</td><td>券包订单</td><td>🟢</td>
<td><span class="tag relay">存量中转 + 新业务直连</span><br>同上</td>
</tr>
<tr>
<td><b>四川天府银行</b></td><td><code>TFYH00001</code></td><td>924 四川天府</td><td>B key 发码</td><td>8583 张</td><td>🟡 较活跃<br>(2026-07)</td>
<td><span class="tag relay">中转(首个试点)</span><br>量小、风险低,作为中转网关首批灰度对象</td>
</tr>
<tr>
<td><b>兴业银行</b></td><td><code>LSXD001</code></td><td>500 兴业</td><td>B key 发码 + 推送</td><td>发码 93 万 / 事件 8.6 万</td><td>🟢</td>
<td><span class="tag relay">中转</span><br>国密证书+独立加解密;老系统已有实现,可复用</td>
</tr>
<tr>
<td><b>邮储银行总行</b></td><td><code>lansexiongdi666</code></td><td>606 邮储总行</td><td>B key 发码 + 推送 + 批量生成</td><td>发码 <b>700 万</b> / 事件 <b>3556 万</b></td><td>🟢</td>
<td><span class="tag relay">中转</span><br>量大 + 父子券/白调逻辑易码通暂未实现 + 批量 key 文件回传</td>
</tr>
<tr>
<td><b>邮储茶饮</b></td><td><code>YCCY001</code></td><td>714 邮储茶饮</td><td>B key 发码</td><td>5102 张</td><td>🟢 (2026-09)</td>
<td><span class="tag relay">中转</span><br>随邮储体系一并中转;不在事件推送表,但发码活跃</td>
</tr>
</table>
<div class="notice"><b>统一原则:</b>已对接客户(行方)对<b>稳定的业务不会再次改动对接</b> → 存量业务一律由<b>中转网关承接</b>(行方零改造);<b>新增业务</b>可直接对接易码通(重新对接即换用易码通协议,免中转)。</div>
<div class="notice green"><b>A 类特例:</b>蓝星/阅璟为<b>券包下单客户</b>(非银行强耦合),且新业务理论上均为<b>直接发券</b>——存量业务继续中转兜底,<b>新业务直接对接易码通</b>(其 openapi 发券主链路已就绪)。</div>
<div class="client-grid">
<div class="client-cell green">
<h4>新业务直连易码通</h4>
<ul><li><b>蓝星严选</b>(券包)</li><li><b>阅璟</b>(券包)</li></ul>
<div style="font-size:12px;color:#6b7280;margin-top:6px">无银行强耦合,换易码通协议免中转;存量仍走中转兜底</div>
</div>
<div class="client-cell orange">
<h4>中转 · 首个灰度</h4>
<ul><li><b>四川天府银行</b>(发码 8583)</li></ul>
<div style="font-size:12px;color:#6b7280;margin-top:6px">量小、风险低,先跑通全链路</div>
</div>
<div class="client-cell blue">
<h4>中转 · 国密验签</h4>
<ul><li><b>兴业银行</b>(发码 93 万 / 事件 8.6 万)</li></ul>
<div style="font-size:12px;color:#6b7280;margin-top:6px">国密证书 + 独立加解密,复用老系统实现</div>
</div>
<div class="client-cell gray">
<h4>中转 · 邮储专项</h4>
<ul><li><b>邮储总行</b>(发码 700 万 / 事件 3556 万)</li><li><b>邮储茶饮</b>(发码 5102)</li></ul>
<div style="font-size:12px;color:#6b7280;margin-top:6px">父子券 / 白调 / 批量文件回传 / 结算登记承接</div>
</div>
</div>
<div class="notice">另有 8 个 merchant_id 已停/测试(如 <code>LSXD000001/2</code>、<code>jianxingjinke</code> 等),无需处理,随老系统归档。</div>
</div>
<div class="card">
<h3>3.3 分销商(reseller)分类处置</h3>
<table>
<tr><th style="width:22%">分类</th><th style="width:14%">数量</th><th>处置方案</th></tr>
<tr><td><b>银行客户</b>(兴业/邮储/浙商/新网/众邦等)</td><td class="num">30+ 家</td><td>发通知函 + 基于 CRM 映射开通易码通账户;对接型银行(兴业/邮储)走中转,其余按计划自然到期</td></tr>
<tr><td><b>商业地产</b>(华润/万象系/亚奥等购物中心)</td><td class="num">约 40 家</td><td>通知函 + 开通引导(basic_auth),量级小、无 API 依赖</td></tr>
<tr><td><b>普通企业</b>(申朴/迈戈/淘天/oppo 等)</td><td class="num">若干</td><td>同上,按活跃度分批触达</td></tr>
<tr><td><b>测试账号</b></td><td class="num">约 10 家</td><td>直接停用/归档</td></tr>
</table>
</div>
</section>
<!-- ================= 四、OpenAPI 中转 ================= -->
<section id="s4">
<div class="sec-title"><span class="num">04</span>OpenAPI 中转方案</div>
<div class="card">
<h3>4.1 总体架构</h3>
<div class="flow">
<div class="flow-row">
<div class="node gray">银行 / 商户客户端<br><span style="font-weight:400;font-size:13px">保持原协议不变</span></div>
</div>
<div class="arrow-down">↓ 原协议(A 无验签 / B 国密)</div>
<div class="flow-row">
<div class="node solid">中转网关(新开发)<br><span style="font-weight:400;font-size:13px">验签转换 · 协议翻译 · 路由 · 幂等</span></div>
</div>
<div class="arrow-down">↓ 易码通统一协议(RSA-SHA256 + AES)</div>
<div class="flow-row">
<div class="node green">易码通 OpenAPI<br><span style="font-weight:400;font-size:13px">key/order · query · discard · batch · settlement</span></div>
</div>
</div>
<div class="notice"><b>定位:</b>中转网关是<b>存量老客户的专属通道</b>(保持老协议不变),<b>不是所有流量的必经之路</b> —— 新客户/新业务直连易码通(分销商用 basic_auth、A 类客户用标准协议)。</div>
<h4>中转网关核心职责</h4>
<ul class="tick">
<li><b>验签转换:</b>国密(SM2/SM4)↔ 易码通 RSA/AES。兴业/邮储国密实现老系统已有,可整体迁入中转层复用;A 类无验签客户由中转层代签。</li>
<li><b>app_id 映射:</b>维护 <code>老app_id → 易码通app_id</code> 映射表,老客户 app_id 不变、<b>客户端零改造</b>(行方接收端因此完全不用动)。</li>
<li><b>幂等透传:</b><code>out_biz_no</code> 原样透传给易码通(易码通有 Redis 幂等锁),保证中转重试不重复发码。</li>
<li><b>计划级路由:</b>复用老系统已有 <code>RequestRedirect</code> 中间件思路 —— 按计划编号分流:<b>老计划 → 老系统 DB(只读查询)</b>,<b>新计划 → 易码通</b>。老存量不动、新业务全进易码通。</li>
<li><b>通知/回调转换:</b>D 类事件通知由易码通事件 → 行方既有报文格式/签名/幂等语义转换后推送;C 类核销回调存量留守老系统(见第 5 章)。</li>
</ul>
</div>
<div class="card">
<h3>4.2 四类接口在中转层的处理</h3>
<table>
<tr><th style="width:14%">接口类</th><th style="width:30%">营销系统路由</th><th style="width:26%">易码通对应</th><th>中转层动作</th></tr>
<tr><td><b>A · 券包下单</b></td><td><code>/openapi/v1/market/AlipayCoupon/order、query</code></td><td><code>key/order、key/query</code></td><td>代签 + 字段翻译 + 幂等透传;老客户无感</td></tr>
<tr><td><b>B · key 发码</b></td><td><code>/openApi/v1/market/key/send、discard、query</code></td><td><code>order/batch_order、discard、query/batch_query、renew、exchange</code></td><td>国密验签 → 易码通验签转换;字段映射;out_biz_no 透传</td></tr>
<tr><td><b>B · 批量生成</b><span class="tag dev">需开发</span></td><td><code>generate/postbank、lock/postbank、pushDataFile</code></td><td>无对应</td><td>易码通内部有导码能力(key_batch 出 zip),缺开放通道 —— 中转层实现"客户文件交互"并桥接到易码通内部接口,或易码通补开放接口</td></tr>
<tr><td><b>C · 立减金回调</b><span class="tag keep">存量留守</span></td><td><code>/openApi/v1/callback/voucher/*</code>(4 家)</td><td>仅更新存量券状态,无新创建<br>(新业务可迁易码通 <code>/v1/order/voucher/notify</code>)</td><td>存量<b>留守老系统,不动</b>;仅当新业务在易码通发立减金券时再做渠道适配</td></tr>
<tr><td><b>D · 主动通知</b></td><td><code>/notify/industrialBank</code></td><td>merchant_app 事件订阅 + merchant_notify 重试</td><td>易码通事件 → <b>行方既有报文格式/国密签名/幂等语义</b>转换后推送,行方接收端不变</td></tr>
</table>
</div>
<div class="card">
<h3>4.3 密钥与安全注意点</h3>
<ul class="tick">
<li><b>一套协议、每商户一套密钥:</b>易码通每个 app 独立 <code>app_id/RSA/AES/notify_url</code>,新商户接入成本低,中转层为每个老客户申请独立 app,密钥隔离。</li>
<li><b>时间戳窗口:</b>易码通验签时间戳窗口默认 3 分钟,中转层转发需避免时钟偏差导致签名失效。</li>
<li><b>回滚能力:</b>中转层做灰度开关(按客户/按计划),出问题一键切回老系统。</li>
</ul>
</div>
</section>
<!-- ================= 五、回调处理 ================= -->
<section id="s5">
<div class="sec-title"><span class="num">05</span>回调与通知处理</div>
<div class="card">
<h3>5.1 两类回调的现状</h3>
<table>
<tr><th style="width:18%">类型</th><th style="width:32%">方向</th><th style="width:20%">数量</th><th>处理方案</th></tr>
<tr>
<td><b>C 类 · 立减金核销回调</b></td>
<td>银行/渠道 → 营销系统<br><code>/openApi/v1/callback/voucher/*</code></td>
<td>4 家</td>
<td>性质 = 行方把<b>支付宝立减金核销通知</b>推给我们,用于<b>更新券码状态</b>。只改存量券状态、不触发新创建 → <b>留守老系统,接口不动</b>。易码通虽具备同等能力(<code>NotifyVoucher/Used/Expired/Refunded</code>),但<b>无需为此迁移</b>;仅当新业务改在易码通发立减金券时才需把 4 家渠道适配过去。</td>
</tr>
<tr>
<td><b>D 类 · 主动事件通知</b></td>
<td>营销系统 → 银行<br><code>/notify/industrialBank</code></td>
<td>3 家<br>(邮储/兴业/天府)</td>
<td>易码通具备 merchant_app 事件订阅 + merchant_notify 通知重试(能力底子),但<b>报文结构 / 国密签名 / 幂等语义与行方既有接收端不一致</b>,行方不改 → 必须由<b>中转层转换后推送</b>,并复刻老系统补推工具(<code>pushKeySupplement</code> 类)。</td>
</tr>
</table>
<h3>5.2 关键量级提示</h3>
<table>
<tr><th>merchant</th><th>180 天事件量</th><th>最近通知</th><th>含义</th></tr>
<tr><td><code>lansexiongdi666</code>(邮储总行)</td><td class="num"><b>3556 万条</b></td><td>2026-09-07</td><td>分钟级推送峰值,中转层需具备高吞吐 + 幂等 + 失败重试队列,且<b>通知不能丢</b>(涉及银行侧积分到账)</td></tr>
<tr><td><code>LSXD001</code>(兴业)</td><td class="num">8.6 万条</td><td>2026-09-07</td><td>国密加密报文,中转层解/加密</td></tr>
<tr><td><code>TFYH00001</code>(天府)</td><td class="num">4043 条</td><td>2026-07-09</td><td>量小,作中转网关首个灰度对象;推送格式转换逻辑与兴业共用</td></tr>
</table>
</div>
</section>
<!-- ================= 六、后台创建能力 ================= -->
<section id="s6">
<div class="sec-title"><span class="num">06</span>后台创建能力对照与缺口</div>
<div class="card">
<h3>6.1 能力映射(易码通 admin 已具备)</h3>
<table>
<tr><th style="width:26%">营销系统(关闭的能力)</th><th style="width:34%">易码通对应接口</th><th>要点</th></tr>
<tr><td>创建分销商 reseller</td><td><code>POST /admin/v1/merchant/create</code></td><td>即易码通 merchant,带资金账户 + <code>direct_reseller_id</code> 老系统映射</td></tr>
<tr><td>创建应用(app_id/密钥)</td><td><code>POST /admin/v1/merchant/app/create</code></td><td>RSA 密钥、notify_url、事件订阅、密钥重置</td></tr>
<tr><td>创建计划</td><td><code>POST /admin/v1/activity/create</code></td><td>key 总量/有效期/结算方式/绑定客户</td></tr>
<tr><td>创建批次 / 导 key</td><td><code>POST /admin/v1/key_batch/create</code></td><td>单次 ≤10 万,zip+密码,可下载/邮件</td></tr>
<tr><td>key 管理</td><td><code>PUT /admin/v1/key/discard|delay|use</code></td><td>作废 / 延时 / 标记已使用 / 统计</td></tr>
</table>
</div>
<div class="card">
<h3>6.2 五个落地注意点</h3>
<table>
<tr><th style="width:16%">注意点</th><th style="width:44%">问题</th><th>建议</th></tr>
<tr><td><b>① 审批流</b></td><td>易码通活动创建后为"待审核",需钉钉审批,<b>生效后才能建批次</b></td><td>存量计划批量导入时走免审/直连通道,或确认审批流程可配置</td></tr>
<tr><td><b>② 资金账户</b></td><td>易码通 merchant 有余额/授信/冻结,营销系统 137 家分销商余额是否迁移</td><td>先定"余额是否平移",否则下游发码结算会断;建议迁移后按易码通账户体系重新授信</td></tr>
<tr><td><b>③ 批次上限</b></td><td>易码通单批次 ≤10 万且不超活动 <code>key_total_num</code>;老系统尚有 2224 万待发 key</td><td>新建活动时 <code>key_total_num</code> 按存量+新量规划,或按活动多次建批次</td></tr>
<tr><td><b>④ key 格式</b></td><td>易码通 key 有 <code>key_style(1/2/3)</code>、<code>key_unit</code>、区间导码参数</td><td>核对老系统 key 生成规则(前缀/长度/分段)能否用易码通参数配出,否则老客户依赖的 key 形态会变</td></tr>
<tr><td><b>⑤ 存量处置</b></td><td>1394 未结束计划、9008 未结束批次(2224 万 key)</td><td><b>不动存量</b>,按 end_time 自然到期;停入口后 C 端核销链路自闭环即可</td></tr>
</table>
</div>
</section>
<!-- ================= 七、执行路线 ================= -->
<section id="s7">
<div class="sec-title"><span class="num">07</span>执行路线(四阶段)</div>
<div class="card">
<table>
<tr><th style="width:14%">阶段</th><th style="width:30%">动作</th><th>判定完成标准</th></tr>
<tr>
<td><b>阶段 1<br>停入口</b></td>
<td>管理后台写接口(新建计划/批次)禁用<br>OpenAPI 写接口(send/discard/generate/lock/pushDataFile)停用<br>分销商后台登录入口关闭<br><b>保留</b>:查询接口、核销、C 端、回调接收、财务导出</td>
<td>每日新建 plan &lt; 1</td>
</tr>
<tr>
<td><b>阶段 2<br>存量消化</b></td>
<td>1394 个未结束计划自然到期;9008 批次消耗 2224 万待发 key<br>关键任务:<b>通知 137 家分销商 + 建立 CRM 映射,在易码通开通账户(basic_auth 接入)</b></td>
<td>存量计划全部过期 / 分销商完成引导</td>
</tr>
<tr>
<td><b>阶段 3<br>银行对接处理</b></td>
<td>统一由<b>中转网关</b>承接存量,行方零改造:<br>① 天府 → 首个灰度(量小);② 蓝星/阅璟 → 存量中转(代签),新业务直连易码通;③ 兴业 → 国密验签转换;④ 邮储总行/茶饮 → 大流量 + 父子券/白调 + 批量文件回传 + <b>结算登记(settlement_order type=5)承接</b>;⑤ D 类推送格式转换<br>易码通侧并行:新增 <b>basic_auth 验签类型</b>、建立分销商 <b>CRM 映射</b></td>
<td>6 家对接客户全部切换完成,行方无改造</td>
</tr>
<tr>
<td><b>阶段 4<br>下线归档</b></td>
<td>老系统保留查询与 <b>C 类核销回调接收</b>(存量券生命周期走完);1.1TB 归档冷存储(OSS 冷归档)<br>保留财务对账所需表</td>
<td>停服验收通过</td>
</tr>
</table>
<h3>工作量与复杂度评估(技术侧)</h3>
<table>
<tr><th>工作项</th><th style="width:14%">工作量</th><th style="width:14%">复杂度</th></tr>
<tr><td>停入口(前后端双禁用)</td><td class="num">小</td><td class="num">低</td></tr>
<tr><td>分销商通知 + CRM 映射开通(137 家)</td><td class="num">中</td><td class="num">中</td></tr>
<tr><td><b>中转网关</b>(验签/协议转换 · app_id 映射 · 幂等 · D 类推送格式转换)</td><td class="num"><b>大</b></td><td class="num"><b>高</b></td></tr>
<tr><td>易码通新增 basic_auth 验签类型(复用 reseller_api_setting 模型)</td><td class="num">小</td><td class="num">低</td></tr>
<tr><td><b>邮储专项</b>(父子券/白调/批量 key 文件回传/3556万事件/结算登记承接)</td><td class="num"><b>大</b></td><td class="num"><b>高</b></td></tr>
<tr><td>老系统数据归档(1.1TB)</td><td class="num">中</td><td class="num">中</td></tr>
</table>
</div>
</section>
<!-- ================= 八、总结 ================= -->
<section id="s8">
<div class="sec-title"><span class="num">08</span>总结</div>
<div class="summary">
<h2>核心结论(一句话)</h2>
<p class="big"><b>停入口、留服务、存量自然消化;6 家已对接客户的存量业务一律由中转网关承接(行方零改造),新业务直连易码通(A 类券包客户可直接对接);137 家分销商经 CRM 映射迁入易码通(basic_auth 接入)。C 类核销回调留守老系统不动。</b></p>
<div class="grid">
<div class="box">
<h3>✔ 已就绪</h3>
<ul>
<li>易码通后台创建能力:分销商 / 应用 / 计划 / 批次 / key —— 全部已覆盖</li>
<li>OpenAPI 发码主链路(A 券包 + B key send/discard/query)—— 已覆盖,协议/验签由中转层转换</li>
<li>立减金(券)体系:主体(支付宝/微信/云闪付)+ 券商品/批次/订单 + 核销状态更新 —— 已覆盖(存量回调留守老系统即可)</li>
<li>D 类事件订阅 + 通知重试(merchant_notify)—— 能力底子已具备,对外推送格式由中转层转换</li>
</ul>
</div>
<div class="box">
<h3>🔧 需开发 / 决策</h3>
<ul>
<li><b>中转网关</b>(核心工程):验签/协议转换 · app_id 映射 · 幂等透传 · 计划级路由 · D 类推送格式转换</li>
<li>易码通新增 <b>basic_auth 验签类型</b>(可复用 reseller_api_setting 的分销商鉴权模型)</li>
<li>邮储批量生成 + 文件回传(generate/lock/pushDataFile)开放通道</li>
<li>分销商 <b>CRM 映射表</b>(营销 reseller ↔ 易码通/CRM 客户)</li>
<li>历史结算数据归档(供财务对账):结算导出/月度对账均已停用,仅需保留查询能力</li>
<li>存量计划导入的审批免审通道</li>
</ul>
</div>
<div class="box">
<h3>🔄 必须中转(存量业务)</h3>
<ul>
<li>蓝星 / 阅璟:存量中转(代签兜底),<b>新业务直连易码通</b></li>
<li>天府:首个灰度试点(量小、风险低)</li>
<li>兴业:国密验签 + 独立加解密</li>
<li>邮储总行 / 茶饮:大流量(700万发码 / 3556万事件)+ 父子券 / 白调 + 批量文件回传 + <b>结算登记承接</b></li>
<li>原则:<b>行方存量业务不改造任何对接</b>,中转层 100% 兼容老协议;<b>新业务直连易码通,不过中转</b></li>
</ul>
</div>
<div class="box">
<h3>⚠ 主要风险</h3>
<ul>
<li>兴业 568 个未结束计划最晚到期 2031-12-31 → 存量消化下限 5 年</li>
<li>邮储 3556 万事件通知不可丢(银行侧积分到账)</li>
<li>行方零改造 → 中转层必须完整复刻国密/报文/幂等语义,兼容性风险集中在中转层</li>
<li>2224 万待发 key 与易码通批次上限(≤10万)的承接规划</li>
<li>邮储结算登记(<code>settlement_order</code> type=5,704 条/月)已确认<b>纳入邮储中转范围</b>,落地时若漏项将导致邮储结算断档</li>
</ul>
</div>
<div class="box" style="grid-column: 1 / -1;">
<h3>📌 下一步行动项</h3>
<ul>
<li>1) 启动<b>中转网关</b>设计:验签转换、app_id 映射、幂等、D 类推送格式(复用老系统国密实现)</li>
<li>2) 天府作为<b>首个灰度</b>(量小、风险低),跑通"老协议 → 中转 → 易码通"全链路</li>
<li>3) 易码通新增 <b>basic_auth 验签</b> + 建分销商 CRM 映射表</li>
<li>4) 邮储专项:批量生成文件回传 + 结算登记(<code>settlement_order</code> type=5,704 条/月)承接(<b>已确认纳入中转范围</b>);历史结算数据存档供财务对账</li>
<li>5) A 类客户(蓝星/阅璟)新业务直连易码通 → 提供接入文档与联调支持</li>
<li>6) 通知 137 家分销商,按 CRM 映射开通易码通账户</li>
<li>7) 确认 C 类留守边界(存量券生命周期)与历史订单保留年限</li>
</ul>
</div>
</div>
</div>
<div class="footer">
数据来源:营销系统主库 market 只读副本(2026-09-07 快照)· 易码通源码(app/admin、app/openapi、grpc proto,2026-09-16 核对)<br>
本方案为会议讨论稿,涉及金额、合同、商务策略的内容需业务侧确认后修订。
</div>
</section>
</div>
</body>
</html>