6da6964451
- Go/Gin/GORM + 纯 Go SQLite(无 cgo) - Channel 多渠道接口:支付宝当面付(precreate)/电脑网站支付(page.pay) 已实现,微信占位 - 多商户 merchants 表,回调验签+金额核对+幂等+查单兜底 - 收款页/结果页/二维码端点;docs/ 设计文档与部署 Runbook - 密钥走环境变量/Bitwarden,不入库 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
172 lines
14 KiB
HTML
172 lines
14 KiB
HTML
<!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{--bg:#0d1117;--card:#161b22;--card-2:#1c2330;--border:#283041;--fg:#e6edf3;--fg-soft:#aeb9c7;--muted:#7d8896;--accent:#58a6ff;--green:#3fb950;--orange:#d29922;--red:#f85149;--radius:14px}
|
||
*{box-sizing:border-box}
|
||
body{margin:0;background:radial-gradient(1200px 600px at 80% -10%,rgba(88,166,255,.08),transparent 60%),var(--bg);color:var(--fg);font:15px/1.7 -apple-system,BlinkMacSystemFont,"PingFang SC","Microsoft YaHei",sans-serif;-webkit-font-smoothing:antialiased}
|
||
.wrap{max-width:980px;margin:0 auto;padding:44px 22px 90px}
|
||
.eyebrow{color:var(--accent);font-weight:600;letter-spacing:.12em;font-size:12px;text-transform:uppercase}
|
||
h1{font-size:28px;margin:10px 0 8px}
|
||
.lead{color:var(--fg-soft);margin:0 0 26px}
|
||
h2{font-size:19px;margin:38px 0 12px;color:var(--accent);border-bottom:1px solid var(--border);padding-bottom:8px}
|
||
h3{font-size:16px;margin:22px 0 8px;color:var(--fg)}
|
||
p{color:var(--fg-soft)}
|
||
code{background:var(--card-2);border:1px solid var(--border);border-radius:5px;padding:1px 6px;font-size:13px;color:#e6edf3;font-family:"SF Mono",Menlo,Consolas,monospace}
|
||
pre{background:var(--card-2);border:1px solid var(--border);border-radius:10px;padding:14px 16px;overflow-x:auto;font-size:13px;line-height:1.55}
|
||
pre code{background:none;border:0;padding:0}
|
||
a{color:var(--accent);text-decoration:none}a:hover{text-decoration:underline}
|
||
table{width:100%;border-collapse:collapse;margin:14px 0;font-size:14px}
|
||
th,td{border:1px solid var(--border);padding:9px 11px;text-align:left;vertical-align:top}
|
||
th{background:var(--card-2);color:var(--fg);font-weight:600}
|
||
td{color:var(--fg-soft)}
|
||
.callout{border-left:3px solid var(--accent);background:var(--card-2);border-radius:0 8px 8px 0;padding:12px 16px;margin:16px 0;color:var(--fg-soft)}
|
||
.callout.warn{border-left-color:var(--orange)}
|
||
.callout.ok{border-left-color:var(--green)}
|
||
.callout.bad{border-left-color:var(--red)}
|
||
.step{display:flex;gap:14px;margin:14px 0;background:var(--card);border:1px solid var(--border);border-radius:var(--radius);padding:16px 18px}
|
||
.step .n{flex:0 0 30px;height:30px;border-radius:50%;background:var(--accent);color:#04122b;font-weight:700;display:flex;align-items:center;justify-content:center}
|
||
.step .body{flex:1}
|
||
.step .body h3{margin:2px 0 6px}
|
||
.pill{font-size:12px;font-weight:600;padding:2px 9px;border-radius:6px}
|
||
.pill.sand{background:rgba(63,185,80,.15);color:var(--green)}
|
||
.pill.prod{background:rgba(210,153,34,.15);color:var(--orange)}
|
||
.yes{color:var(--green);font-weight:600}.no{color:var(--red);font-weight:600}
|
||
ul{color:var(--fg-soft)}
|
||
svg{display:block;margin:8px auto;max-width:100%}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="wrap">
|
||
<div class="eyebrow">pay · Onboarding</div>
|
||
<h1>支付宝密钥申请与备案依赖关系</h1>
|
||
<p class="lead">沙箱 vs 生产两阶段分别需要什么、密钥怎么拿、备案到底卡在哪一步。配套独立支付服务 <code>pay</code>(PC 网页支付 <code>alipay.trade.page.pay</code>)。</p>
|
||
|
||
<h2>一、两阶段总览</h2>
|
||
<table>
|
||
<thead><tr><th style="width:24%"></th><th><span class="pill sand">沙箱(现在就能做)</span></th><th><span class="pill prod">生产(收真钱)</span></th></tr></thead>
|
||
<tbody>
|
||
<tr><td><strong>企业实名</strong></td><td class="no">不需要</td><td class="yes">需要(营业执照/对公/法人)</td></tr>
|
||
<tr><td><strong>产品签约</strong></td><td class="no">不需要</td><td class="yes">需签约「电脑网站支付」</td></tr>
|
||
<tr><td><strong>域名</strong></td><td class="no">不需要</td><td>签约审核基本要备案域名</td></tr>
|
||
<tr><td><strong>ICP 备案</strong></td><td class="no">不需要</td><td>基本绕不开(见第二节)</td></tr>
|
||
<tr><td><strong>HTTPS</strong></td><td class="no">不需要(localhost 即可)</td><td class="yes">需要(域名证书)</td></tr>
|
||
<tr><td><strong>能验证什么</strong></td><td>下单→跳收银台→扫码付→(查单兜底)全链路</td><td>真实到账 + 异步回调 notify</td></tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<h2>二、不用域名 = 不用备案?</h2>
|
||
<p>技术层面:<strong>不绑域名就不触发 ICP 备案</strong>(备案=域名+大陆服务器对外提供服务)。而且有个对支付宝有利的事实:</p>
|
||
<div class="callout ok">
|
||
<strong>支付宝电脑网站支付的 <code>notify_url</code> / <code>return_url</code> 支付宝不校验是否备案</strong>——只要能 POST 回调到你的地址就行。这点和微信不同(微信 JSAPI/H5 要在后台填「已备案授权域名」)。所以单从回调技术看,甚至能用服务器公网 IP 当 notify_url 把真实支付跑通。
|
||
</div>
|
||
<p>但「想正经收真钱」时,备案基本还是绕不开,卡在这三处:</p>
|
||
<table>
|
||
<thead><tr><th style="width:26%">卡点</th><th>说明</th></tr></thead>
|
||
<tbody>
|
||
<tr><td><strong>商户签约审核</strong></td><td>申请生产「电脑网站支付」要提交<strong>网站地址</strong>,支付宝审核要求网站可正常访问且合规,实践中基本要备案域名(裸 IP 网站过审很难)</td></tr>
|
||
<tr><td><strong>HTTPS</strong></td><td>给纯 IP 签受信任 HTTPS 证书极难(Let's Encrypt 不给 IP 发证),无 HTTPS 收款页显示「不安全」</td></tr>
|
||
<tr><td><strong>微信支付</strong></td><td>微信必须填备案授权域名,完全绕不开</td></tr>
|
||
</tbody>
|
||
</table>
|
||
<div class="callout bad">
|
||
<strong>结论:</strong>沙箱阶段不用域名/备案/实名;真实收款备案是刚需。<strong>但你不必等备案</strong>就能先把支付宝沙箱联调全做完,备案/签约和联调可并行。
|
||
</div>
|
||
<div class="callout">
|
||
完全不备案也想收真钱的旁路:支付宝<strong>「当面付」(扫码)</strong>签约不依赖网站,或用<strong>收款链接 / 第三方托管收银台</strong>——但那不是自研网页收款页这条路。
|
||
</div>
|
||
|
||
<h2>三、沙箱密钥获取(4 步 · 现在就能做)</h2>
|
||
<div class="step"><div class="n">1</div><div class="body">
|
||
<h3>进沙箱控制台</h3>
|
||
<p>支付宝账号登录 → <a href="https://open.alipay.com/develop/sandbox/app">https://open.alipay.com/develop/sandbox/app</a>。页面直接给你 <strong>沙箱 APPID</strong>(形如 <code>9021000xxxxxxxxx</code>)。</p>
|
||
</div></div>
|
||
<div class="step"><div class="n">2</div><div class="body">
|
||
<h3>选「公钥模式」+ 生成密钥</h3>
|
||
<p>加签方式选 <strong>公钥模式</strong>(对应代码 <code>LoadAliPayPublicKey</code>)。下载官方<a href="https://opendocs.alipay.com/common/02kipl">密钥生成工具</a>(有 Mac 版)→ 格式 <strong>PKCS8</strong>、长度 <strong>2048</strong> → 生成得到 <strong>应用私钥</strong> 和 <strong>应用公钥</strong>。</p>
|
||
</div></div>
|
||
<div class="step"><div class="n">3</div><div class="body">
|
||
<h3>上传应用公钥 → 换回支付宝公钥</h3>
|
||
<p>把<strong>应用公钥</strong>粘贴到沙箱「公钥模式」处保存,页面会生成一串 <strong>支付宝公钥</strong>。</p>
|
||
<div class="callout warn" style="margin:8px 0 0">别搞混:你<strong>上传</strong>的是「应用公钥」;要<strong>复制回配置</strong>的是支付宝生成的「支付宝公钥」。</div>
|
||
</div></div>
|
||
<div class="step"><div class="n">4</div><div class="body">
|
||
<h3>拿沙箱买家账号</h3>
|
||
<p>沙箱页「<strong>沙箱账号</strong>」标签提供买家账号(邮箱)+ 登录密码 + 支付密码(假钱)。扫码付需装<strong>沙箱版支付宝 App</strong>(同页二维码),或用沙箱网页登录买家付款。</p>
|
||
</div></div>
|
||
|
||
<h2>四、生产密钥申请(5 步 · 收真钱)</h2>
|
||
<div class="step"><div class="n">1</div><div class="body">
|
||
<h3>企业实名</h3>
|
||
<p>登录 <a href="https://open.alipay.com">open.alipay.com</a> → 用企业支付宝账号完成企业实名认证(营业执照、法人/对公信息)。个体户用对应类型亦可。</p>
|
||
</div></div>
|
||
<div class="step"><div class="n">2</div><div class="body">
|
||
<h3>创建生产应用</h3>
|
||
<p>控制台 → 创建应用 → 选「<strong>网页 & 移动应用</strong>」→ 得到 <strong>正式 APPID</strong>。</p>
|
||
</div></div>
|
||
<div class="step"><div class="n">3</div><div class="body">
|
||
<h3>签约「电脑网站支付」</h3>
|
||
<p>应用里「添加能力/产品签约」→ 签约「<strong>电脑网站支付</strong>」(对应 <code>alipay.trade.page.pay</code>)。需提交企业资质、<strong>网站地址(基本要备案域名)</strong>、经营信息。审核约 1–3 个工作日。</p>
|
||
</div></div>
|
||
<div class="step"><div class="n">4</div><div class="body">
|
||
<h3>配置生产密钥(同沙箱操作)</h3>
|
||
<p>密钥工具生成应用私钥/公钥 → 应用「接口加签方式 → 公钥模式」上传应用公钥 → 复制返回的「支付宝公钥」。</p>
|
||
</div></div>
|
||
<div class="step"><div class="n">5</div><div class="body">
|
||
<h3>切到生产</h3>
|
||
<p>把正式 APPID/应用私钥/支付宝公钥写入商户配置,<code>production: true</code>(代码走正式网关),<code>base_url</code> 用正式 HTTPS 备案域名。</p>
|
||
</div></div>
|
||
|
||
<h2>五、三样东西 → 配置对应</h2>
|
||
<table>
|
||
<thead><tr><th style="width:24%">拿到的</th><th style="width:34%">来源</th><th>填到哪</th></tr></thead>
|
||
<tbody>
|
||
<tr><td>APPID</td><td>沙箱页面 / 生产应用页直接给</td><td><code>config.yaml → alipay_sandbox.app_id</code>(或 merchants 表)</td></tr>
|
||
<tr><td>应用私钥</td><td>你用密钥工具生成,自己保管</td><td>环境变量 <code>ALIPAY_APP_PRIVATE_KEY</code></td></tr>
|
||
<tr><td>支付宝公钥</td><td>上传应用公钥后支付宝生成</td><td>环境变量 <code>ALIPAY_PUBLIC_KEY</code></td></tr>
|
||
</tbody>
|
||
</table>
|
||
<pre><code>cd /Users/wangjia/code/pay
|
||
export ALIPAY_APP_PRIVATE_KEY="MIIEv...应用私钥..."
|
||
export ALIPAY_PUBLIC_KEY="MIIBIj...支付宝公钥..."
|
||
# config.yaml 里 alipay_sandbox.enabled=true、填上 app_id
|
||
go run .
|
||
# 浏览器开 http://localhost:8080 选套餐 → 跳沙箱收银台 → 沙箱买家账号付款</code></pre>
|
||
<div class="callout warn">
|
||
本机能测「下单 → 跳收银台 → 扫码付成功」整条链路;唯一测不到的是<strong>异步回调 notify</strong>(支付宝回调不到本机)。但服务内置的 <code>query_sync</code> 主动查单兜底会在 30 秒内把订单补成「已支付」,结果页照样变 ✅。要完整验证 notify 需内网穿透或部署到公网服务器。
|
||
</div>
|
||
|
||
<h2>六、推进路线(两线并行,互不等待)</h2>
|
||
<svg viewBox="0 0 900 230" xmlns="http://www.w3.org/2000/svg" font-family="-apple-system,PingFang SC,sans-serif" font-size="13">
|
||
<defs><marker id="ar" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto"><path d="M0,0 L9,3 L0,6 Z" fill="#58a6ff"/></marker></defs>
|
||
<!-- line A -->
|
||
<text x="20" y="46" fill="#3fb950" font-weight="600">A · 联调线(现在)</text>
|
||
<rect x="20" y="58" width="170" height="44" rx="8" fill="#161b22" stroke="#3fb950"/><text x="105" y="84" fill="#e6edf3" text-anchor="middle">拿沙箱密钥</text>
|
||
<line x1="190" y1="80" x2="232" y2="80" stroke="#58a6ff" stroke-width="2" marker-end="url(#ar)"/>
|
||
<rect x="234" y="58" width="200" height="44" rx="8" fill="#161b22" stroke="#3fb950"/><text x="334" y="84" fill="#e6edf3" text-anchor="middle">本机跑通支付宝沙箱</text>
|
||
<line x1="434" y1="80" x2="476" y2="80" stroke="#58a6ff" stroke-width="2" marker-end="url(#ar)"/>
|
||
<rect x="478" y="58" width="200" height="44" rx="8" fill="#161b22" stroke="#283041"/><text x="578" y="84" fill="#aeb9c7" text-anchor="middle">代码就绪 · 等生产</text>
|
||
<!-- line B -->
|
||
<text x="20" y="150" fill="#d29922" font-weight="600">B · 上线线(并行)</text>
|
||
<rect x="20" y="162" width="150" height="44" rx="8" fill="#161b22" stroke="#d29922"/><text x="95" y="188" fill="#e6edf3" text-anchor="middle">域名转入</text>
|
||
<line x1="170" y1="184" x2="208" y2="184" stroke="#58a6ff" stroke-width="2" marker-end="url(#ar)"/>
|
||
<rect x="210" y="162" width="120" height="44" rx="8" fill="#161b22" stroke="#d29922"/><text x="270" y="188" fill="#e6edf3" text-anchor="middle">ICP 备案</text>
|
||
<line x1="330" y1="184" x2="368" y2="184" stroke="#58a6ff" stroke-width="2" marker-end="url(#ar)"/>
|
||
<rect x="370" y="162" width="170" height="44" rx="8" fill="#161b22" stroke="#d29922"/><text x="455" y="188" fill="#e6edf3" text-anchor="middle">企业实名+签约</text>
|
||
<line x1="540" y1="184" x2="578" y2="184" stroke="#58a6ff" stroke-width="2" marker-end="url(#ar)"/>
|
||
<rect x="580" y="162" width="150" height="44" rx="8" fill="#161b22" stroke="#d29922"/><text x="655" y="188" fill="#e6edf3" text-anchor="middle">生产密钥</text>
|
||
<!-- merge -->
|
||
<line x1="655" y1="102" x2="655" y2="160" stroke="#7d8896" stroke-width="1.5" stroke-dasharray="4 4"/>
|
||
<rect x="740" y="110" width="140" height="46" rx="8" fill="#1c2330" stroke="#58a6ff"/><text x="810" y="130" fill="#e6edf3" text-anchor="middle" font-weight="600">换密钥+域名</text><text x="810" y="146" fill="#58a6ff" text-anchor="middle">→ 上线收真钱</text>
|
||
<line x1="678" y1="80" x2="738" y2="120" stroke="#58a6ff" stroke-width="2" marker-end="url(#ar)"/>
|
||
<line x1="730" y1="184" x2="800" y2="158" stroke="#58a6ff" stroke-width="2" marker-end="url(#ar)"/>
|
||
</svg>
|
||
<p>两条线独立推进:A 线现在就能把代码全跑通,B 线(域名/备案/签约)慢慢走;B 线齐了,只需「换生产密钥 + 换备案域名」即可上线,主流程一行不改(<code>Merchant.Production</code> + <code>base_url</code>)。</p>
|
||
|
||
</div>
|
||
</body>
|
||
</html>
|