自动发货页面需要回答两个问题:当前完成到了哪一步,接下来该做什么。

以 ChatGPT Plus 的卡密交付为例,“付款成功”“卡密已发放”和“订阅已生效”分别对应不同结果。如果页面只放一段发货文本和一个网址,用户就需要自己判断操作顺序。

这份笔记来自我们维护 AIXiamo(AI夏末)自动发货页面时的整理,主要讨论状态提示、复制反馈和激活入口的衔接。

一、先区分业务状态和页面动作

付款、交付、激活可以分别记录状态。前端根据已经确认的结果展示下一步,避免用一个“成功”覆盖整条流程。

已确认的结果页面提示下一步动作
支付状态尚未确认原订单正在核对付款情况查看订单状态
付款已确认,发货处理中卡密尚未就绪查看发货进度
卡密已交付可以领取本单卡密复制卡密,打开对应激活入口
激活请求处理中当前兑换请求正在处理查看请求进度
激活页面返回完成结果可以核验目标账号套餐查看账号订阅状态
账号显示与预期不一致需要核对账号与处理结果返回原订单排查

复制成功、打开新页面和刷新浏览器属于页面动作。例如,writeText() 执行成功后可以显示“已复制”,但不能据此把业务状态更新为“已激活”。

同样,支付页面是否成功跳回,只能说明浏览器导航的结果。订单的支付状态仍要根据服务端确认的信息展示。

二、把发卡后的操作串起来

卡密交付后的操作可以按四步安排:

  1. 查看原订单。 展示支付状态、发货进度和本单交付内容。用户刷新或重新进入时,仍能找到已经确认的结果。
  2. 复制完整卡密。 把卡密与商品名称、说明文字分开显示,提供复制按钮,也保留手动选择文本的方式。
  3. 打开对应激活入口。 在卡密区域附近说明这个入口对应什么操作,用户核对后再打开。不同商品的入口应与本单交付信息对应。
  4. 核验目标账号。 激活处理完成后,确认登录的是本次操作对应的 ChatGPT 账号,再查看订阅状态。首次开通关注套餐是否更新;续费还需要有效期证据,不能只看已有的 Plus 标识。

账号核对方法可参考 OpenAI 的 ChatGPT Plus 说明

复制按钮和激活入口可以相邻放置,但保持为两个独立动作。这样,复制失败时用户可以继续手动处理,也能在离开当前页面前核对目标。

三、复制按钮要有成功和失败两条路径

下面用一个无效的示例卡密演示交互。真实系统应先在服务端完成订单归属和访问权限校验,再向有权限的用户返回交付内容。

<label for="cdk">本单卡密</label>
<input id="cdk" value="DEMO-CDK-NOT-FOR-REDEMPTION" readonly>
<button id="copy-cdk" type="button">复制卡密</button>
<p id="copy-status" role="status" aria-live="polite"></p>

<script>
  const field = document.querySelector('#cdk');
  const button = document.querySelector('#copy-cdk');
  const status = document.querySelector('#copy-status');

  button.addEventListener('click', async () => {
    const cdk = field.value;
    if (!cdk.trim()) {
      status.textContent = '卡密尚未就绪,请查看订单发货状态。';
      return;
    }

    button.disabled = true;
    status.textContent = '正在复制……';
    try {
      await navigator.clipboard.writeText(cdk);
      status.textContent = '已复制。下一步:打开本单充值入口。';
    } catch {
      field.focus();
      field.select();
      status.textContent = '请长按卡密,或选中完整内容后手动复制。';
    } finally {
      button.disabled = false;
    }
  });
</script>

这里有几个实现细节:

  • writeText() 的 Promise 完成后,再提示“已复制”。
  • 在复制过程中临时禁用按钮,完成后恢复,避免连续触发。
  • 剪贴板写入失败时选中文本,并提示手动复制;不要只弹一个“操作失败”。
  • 使用原生 buttonaria-live 状态区域,保留键盘操作及辅助技术的反馈。

Clipboard.writeText() 需要安全上下文,线上通常使用 HTTPS。浏览器也可能拒绝剪贴板写入,所以代码需要处理异常。MDN 文档说明了返回值和拒绝行为。

卡密文本只用于当前交互,不应拼到网址参数、统计事件或控制台日志里。页面可以统计“复制按钮被点击”,但不需要记录被复制的内容。

四、验收时检查这些边界

场景预期表现
卡密还未返回提示查看发货状态,不显示复制成功
正常写入剪贴板显示已复制,并说明下一步
浏览器拒绝写入保留完整卡密,允许手动选择复制
浏览器没有 Clipboard API进入手动复制路径,不中断页面其他操作
连续点击复制按钮当前操作期间不重复发起复制
打开激活页后返回可以重新查看原订单和交付信息
激活页提示完成,账号状态未更新核对目标账号和处理结果,不把页面提示当作最终套餐证据

刷新页面时,可以重新获取有权限查看的订单状态。复制成功提示属于临时界面反馈,不需要持久化成订单状态,也不应让刷新页面自动重复提交激活请求。

五、相关示例

gpt-daichong 资料仓库中的 examples/subscription-reconciliation 目录提供了可离线运行的 SQLite 示例,用构造数据演示付款、交付和套餐观察结果的分别核对。它适合用来理解上面的状态区分;本文的 HTML 片段则单独演示复制按钮的交互。

Logo

AtomGit AI 社区提供模型库、数据集、Agent、Token等资源

更多推荐