授權碼License 開發調試上線全流程指南
v1.0.0
客戶端軟件開發 → 調試 → 上線全流程指南(v4)
適用於:在幂棧網發佈客戶端軟件並接入授權碼體系的開發者。 本文覆蓋從「創建產品」到「真實用戶購買」的完整生命週期,重點是 v4 新增的雙環境調試能力:上線前用真實支付鏈路(Waffo Test 環境)把自己的電腦當調試機走通全流程。
一、全流程總覽
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ ① 開發階段 │ → │ ② 調試階段 │ → │ ③ 上線階段 │ → │ ④ 上線後運營 │
│ │ │ │ │ │ │ │
│ 創建產品草稿 │ │ 註冊調試機 │ │ 提交審核 │ │ 查看訂單 │
│ 集成授權 SDK │ │ 走通真實鏈路 │ │ 審核通過 │ │ 解綁/退款 │
│ 保存草稿 │ │ (Test 環境)│ │ 同步生產環境 │ │ 版本迭代 │
└──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘
| 階段 | 產品狀態 | 授權/訂單落在哪 | 會產生真實收入嗎 |
|---|---|---|---|
| ① 開發 | 草稿(DRAFT) | — | 否 |
| ② 調試 | 草稿 / 審核中 | Test 表(授權碼帶 T- 前綴) |
否(測試支付通道) |
| ③ 上線 | 已發佈 | 生產表 | 是 |
核心規則:調試與生產完全隔離。 調試機上發生的一切(試用、下單、支付、發碼、激活、退款)只影響測試表,不進分潤、不進對賬、不影響任何真實用戶;非調試機的訪問永遠走生產鏈路。
二、開發階段
2.1 創建產品
- 登錄幂棧網開發者中心 → 發佈產品,產品形態選「客戶端軟件」
- 售賣方式選 先用後付,填寫試用天數(建議 7~14 天)
- 配置授權版本(edition):默認三檔
BASIC/PRO/ULTIMATE,可自定義 code、名稱、價格與功能清單 - 勾選「平台代收授權費」(先用後付強制勾選)
- 上傳軟件包與介紹素材
2.2 保存草稿(新增能力)
產品表單底部有兩個按鈕:
| 按鈕 | 行為 |
|---|---|
| 保存草稿 | 產品存為 DRAFT 狀態,不進審核佇列,可隨時繼續編輯 |
| 保存並提交審核 | 產品進入審核佇列(PENDING_RELEASE) |
草稿/提審保存後,平台會異步把商品同步到 Waffo Test 環境(失敗僅告警不阻塞保存),這是調試階段能下單的前提。因此建議:開發期先保存草稿即可開始調試,無需提審。
保存後記下 productUniqueCode(發佈頁可見,非密鑰)。
2.3 集成授權 SDK(兩種接入場景)
幂棧網為客戶端軟件提供兩種授權接入方式,開發者根據自身情況選擇:
| 場景 A:平台完整鏈路(先用後付) | 場景 B:訂單不在平台 | |
|---|---|---|
| 適用產品 | 客戶端軟件 + 先用後付售賣方式 | 僅推廣軟件(自行收款);或服務端軟件 / 客戶端軟件,先付後用(PAY_FIRST)售賣方式或 VIP 功能的自行收款 |
| 誰管收款 | 幂棧網平台(Waffo、支付寶、PayPal);調試環節使用 Waffo 測試環境作為支付通道 | 開發者自己(軟件內支付或其他渠道) |
| 誰管發碼 | 平台支付成功後自動發碼 | 軟件調平台 API 發碼(HMAC 簽名) |
需要授權密鑰 licenseApiSecret? |
❌ 不需要 | ✅ 需要(僅存服務端,不可存客戶端) |
| 需要服務端? | ❌ 不需要,純客戶端即可 | ✅ 需要(保管 licenseApiSecret,轉發發碼請求) |
| 試用授權 | ✅ 支持(claimTrial) |
❌ 無試用(試用僅支持先用後付產品) |
| 購買頁 | 平台提供,SDK 一行跳轉 | 無平台購買頁,開發者自行處理 |
關於版本配置:所有產品形態(客戶端/服務端/僅推廣)均可啟用授權碼並自定義版本(BASIC/PRO/ULTIMATE 等)。版本價格和功能清單僅在開發者勾選「平台代收授權費」(
licensePlatformPayment)時展示在購買頁;不勾選則開發者自行處理收款,平台僅提供授權碼發放與校驗能力。
如何選擇:
- 你是獨立開發者 / 小團隊,沒有自己的服務端 → 選 場景 A(本文第四、五章的流程即以場景 A 為主線)
- 你已有支付渠道(如微信/支付寶商戶),只想用平台發碼校驗 → 選 場景 B
2.3.1 SDK 安裝
三語言(Node.js / Python / Java)均為零依賴,直接拷貝源碼到你的項目中,無需任何包管理器。機器碼算法跨語言一致(同一台機器生成相同 machineCode)。SDK 倉庫:github.com/mizhanchengxi/powersoftware-license-sdk
2.3.2 場景 A:平台完整鏈路(先用後付)
前置條件:產品售賣方式為先用後付、已配置試用天數與授權版本、勾選「平台代收授權費」。不需要授權密鑰 licenseApiSecret:
# Python
from ps_license_sdk import LicenseClient, machine_code
client = LicenseClient(product_unique_code="PRO-2026-001", api_secret="") # api_secret 留空
mc = machine_code()
// Node.js
import { LicenseClient, machineCode } from './index.js';
const client = new LicenseClient({ productUniqueCode: 'PRO-2026-001', apiSecret: "" }); // 場景 A 密鑰留空
const mc = machineCode();
// Java
import com.powersoftware.sdk.LicenseClient;
LicenseClient client = new LicenseClient("PRO-2026-001", ""); // 場景 A 密鑰留空
String mc = LicenseClient.machineCode();
完整接入流程:
首次啟動
│
├─ claimTrial(machineCode) ────────────→ 獲取試用授權
│ ↓ 返回 { licenseCode, activationToken, licenseUpgradeMode }
│ ↓ 本地持久化存儲
│
├─ 試用期內:所有功能可用
│ │
│ └─ 點擊付費功能 → verifyCached() 60s 緩存校驗 → 放行
│
└─ 試用到期 / 未激活
│
├─ verifyCached() 返回 invalid/expired
├─ 彈窗提示"需要購買激活授權"
└─ purchaseUrl(machineCode) → 跳轉平台購買頁
│
↓ 用戶在平台支付 → 平台發碼 + 郵件送達
│
用戶回到軟件,輸入授權碼
│
├─ activate(licenseCode, machineCode)
│ ↓ 返回 { activationToken, licenseUpgradeMode },本地持久化存儲
│
└─ 後續使用 → verifyCached() 校驗 → 放行
需實現:claimTrial(首次啟動領取試用)→ verifyCached(付費功能校驗)→ purchaseUrl(未授權跳購買頁)→ activate(用戶輸入授權碼激活)→ 本地持久化 licenseCode + activationToken → LicenseError 錯誤碼處理。
核心代碼(Python):
import json
from pathlib import Path
from ps_license_sdk import LicenseClient, machine_code
# ---------- 初始化 ----------
client = LicenseClient(product_unique_code="PRO-2026-001", api_secret="")
CRED_FILE = Path.home() / ".myapp" / "license.json"
def load_cred():
if CRED_FILE.exists():
return json.loads(CRED_FILE.read_text())
return {}
def save_cred(d):
CRED_FILE.parent.mkdir(parents=True, exist_ok=True)
CRED_FILE.write_text(json.dumps(d, ensure_ascii=False))
# ---------- 首次啟動:領取試用 ----------
def claim_trial():
mc = machine_code()
try:
result = client.claim_trial(mc)
save_cred({
"licenseCode": result["licenseCode"],
"activationToken": result["activationToken"],
})
print(f"試用已激活,授權碼:{result['licenseCode']}")
except Exception as e:
print(f"領取試用失敗:{e}")
# ---------- 校驗授權(點擊付費功能時調用) ----------
def check_license(required_edition="PRO"):
cred = load_cred()
if not cred.get("licenseCode"):
return {"valid": False, "reason": "未激活"}
mc = machine_code()
try:
result = client.verify_cached(
cred["licenseCode"], mc, cred["activationToken"]
)
if not result.get("valid"):
return {"valid": False, "reason": "授權無效或已過期"}
user_edition = result.get("edition", "")
levels = {"BASIC": 0, "PRO": 1, "ULTIMATE": 2}
if levels.get(user_edition, 0) < levels.get(required_edition, 0):
return {"valid": False, "reason": f"需要 {required_edition} 及以上版本"}
return {"valid": True, "edition": user_edition,
"expiryTime": result.get("expiryTime"),
"trialExpiryTime": result.get("trialExpiryTime")}
except Exception as e:
return {"valid": False, "reason": str(e)}
# ---------- 激活授權碼(用戶購買後輸入) ----------
def activate(license_code):
mc = machine_code()
try:
result = client.activate(license_code, mc)
save_cred({
"licenseCode": license_code,
"activationToken": result["activationToken"],
})
return True
except Exception as e:
print(f"激活失敗:{e}")
return False
# ---------- 跳轉購買頁 ----------
def open_purchase_page():
mc = machine_code()
url = client.purchase_url(mc)
import webbrowser
webbrowser.open(url)
功能攔截示例:
# 定義功能版本要求
FEATURE_EDITION = {
"basic_feature": "BASIC",
"plus_feature": "PRO",
"ultimate_feature": "ULTIMATE",
}
def run_feature(feature_name):
required = FEATURE_EDITION.get(feature_name, "BASIC")
if required == "BASIC":
do_basic_feature()
return
result = check_license(required)
if result["valid"]:
do_paid_feature(feature_name)
else:
print(f"無法使用此功能:{result['reason']}")
open_purchase_page()
2.3.3 場景 B:訂單不在平台(自行收款)
適用產品:僅推廣軟件(自行收款),或服務端軟件 / 客戶端軟件中先付後用(PAY_FIRST)售賣方式、VIP 功能的自行收款。
前置條件:產品開啟 licenseEnabled;在開發者後台獲取 licenseApiSecret(僅存服務端,不可洩露到客戶端)。架構:
客戶端 你的服務端 幂棧網平台
│ │ │
│ 用戶付費(你的支付) │ │
├──────────────────────→│ │
│ │ generateForSoftware( │
│ │ machineCode, edition, │
│ │ clientOrderId) │
│ │ (HMAC 簽名 + timestamp) │
│ ├────────────────────────────────→│
│ │ ← 返回 licenseCode │
│ ← 返回 licenseCode │ │
│ │ │
│ activate(licenseCode, machineCode) │
├───────────────────────────────────────────────────────→│
│ ← 返回 activationToken │
│ │ │
│ verifyCached(...) │ │
├───────────────────────────────────────────────────────→│
│ ← { valid, edition, expiryTime } │
服務端(保管授權密鑰 licenseApiSecret,發碼):
from ps_license_sdk import LicenseClient, machine_code
server_client = LicenseClient(
product_unique_code="PRO-2026-001",
api_secret="你的發碼密鑰_FROM_DEVELOPER_CONSOLE",
)
def issue_license(user_machine_code, edition="PRO", order_id=""):
"""用戶付款後,服務端調平台發碼"""
result = server_client.generate_for_software(
machine_code_value=user_machine_code,
edition=edition,
expiry_days=365,
client_order_id=order_id,
)
return result["licenseCode"]
客戶端(不需要 licenseApiSecret,激活與校驗):
client = LicenseClient(product_unique_code="PRO-2026-001", api_secret="")
def activate(license_code):
mc = machine_code()
result = client.activate(license_code, mc)
save_cred({"licenseCode": license_code,
"activationToken": result["activationToken"]})
需實現:服務端 generateForSoftware(發碼)+ upgradeForSoftware(升級/續費);客戶端 activate / verifyCached + 本地憑證持久化 + LicenseError 錯誤碼處理。
2.3.4 SDK 方法速查
| 方法 | 場景 A | 場景 B | 簽名 | 說明 |
|---|---|---|---|---|
machine_code() |
✅ | ✅ | — | 生成機器碼(跨語言一致) |
claim_trial(mc) |
✅ | — | — | 領取試用授權(僅先用後付產品) |
activate(code, mc) |
✅ | ✅ | — | 激活授權碼,綁定機器 |
verify(code, mc, token) |
✅ | ✅ | — | 校驗授權狀態 |
verify_cached(code, mc, token) |
✅ | ✅ | — | 帶本地緩存(60s)的校驗 |
deactivate(code, mc) |
✅ | ✅ | — | 解綁機器(需登錄,瀏覽器場景) |
purchase_url(mc) |
✅ | — | — | 生成平台購買頁 URL |
generate_for_software(mc, edition, ...) |
— | ✅ | HMAC | 軟件內發碼(僅服務端) |
upgrade_for_software(code, edition, ...) |
— | ✅ | HMAC | 軟件內升級/續費(僅服務端) |
返回字段說明:
activate/verify/claimTrial三個接口的成功響應均附帶licenseUpgradeMode(產品升級策略:SAME_CODE原碼不變 /NEW_CODE原碼換綁)。客戶端據此決定是否展示「綁定授權碼」輸入框:SAME_CODE下授權碼始終不變,無需引導用戶重新輸入;NEW_CODE下升級/續費會簽發新碼,須以接口返回的新licenseCode覆蓋本地保存的授權碼。產品未配置時按SAME_CODE處理;verify結果緩存約 60 秒,配置變更最長 60 秒生效。同時,成功響應還附帶trialExpiryTime(試用到期時間快照,ISO 8601 字符串;授權非試用轉購買時為null)。客戶端可據此實現寬限:用戶先試用全功能、再購買較低版本時,高階功能可繼續放行至trialExpiryTime。同時,成功響應還附帶trialExpiryTime(試用到期時間快照,ISO 8601 字符串;授權非試用轉購買時為null)。客戶端可據此實現寬限:用戶先試用全功能、再購買較低版本時,高階功能可繼續放行至trialExpiryTime。同時,成功響應還附帶trialExpiryTime(試用到期時間快照,ISO 8601 字符串;授權非試用轉購買時為null)。客戶端可據此實現寬限:用戶先試用全功能、再購買較低版本時,高階功能可繼續放行至trialExpiryTime。同時,成功響應還附帶trialExpiryTime(試用到期時間快照,ISO 8601 字符串;授權非試用轉購買時為null)。客戶端可據此實現寬限:用戶先試用全功能、再購買較低版本時,高階功能可繼續放行至trialExpiryTime。
雙環境調試對兩種場景完全透明:
- 場景 A:調試機
claimTrial/ 平台購買頁支付全鏈路自動走 Test 環境(見第四章) - 場景 B:調試機調用
generateForSoftware時平台同樣按機器碼路由到 Test 環境,返回T-前綴授權碼;服務端代碼無需任何改動 - SDK 調用方式在調試期和上線後完全一致,無需任何環境參數或代碼分支,環境路由由平台服務端自動完成
三、授權集成細節(兩種場景通用)
3.1 本地憑證存儲規範
SDK 本身不負責持久化,由開發者自行實現。存儲內容:
{
"licenseCode": "XXXXXXXXXXXX",
"activationToken": "YYYYYYYYYYYY",
"lastVerify": {
"valid": true,
"edition": "ULTIMATE",
"expiryTime": 1735689600000,
"trialExpiryTime": 1735000000000,
"trialExpiryTime": 1735000000000,
"trialExpiryTime": 1735000000000,
"trialExpiryTime": 1735000000000,
"cachedAt": 1735689600000
}
}
原則:
- 只存
licenseCode+activationToken+ 最近一次 verify 結果 - 不存可解密的完整授權信息(防逆向無意義,只作緩存)
verifyCached的 60s 緩存在 SDK 進程內,重啟後失效,需重新調verify
3.2 版本層級對比(edition)
開發者自定義 edition code(如 BASIC / PRO / ULTIMATE),在平台發佈頁配置。所有產品形態(客戶端/服務端/僅推廣)啟用授權碼後均可自定義版本。客戶端校驗時按層級比較:
EDITION_LEVEL = {"BASIC": 0, "PRO": 1, "ULTIMATE": 2, "TRIAL": 99}
def edition_sufficient(user_edition, required_edition):
return EDITION_LEVEL.get(user_edition, 0) >= EDITION_LEVEL.get(required_edition, 0)
常見映射(參考):
| 功能檔位 | edition code | 層級 | 典型功能 |
|---|---|---|---|
| 基礎版 | BASIC |
0 | 基礎修圖、格式轉換 |
| 高階版 | PRO |
1 | 批量處理、高清放大 |
| 旗艦版 | ULTIMATE |
2 | AI 修復、封面助手 |
版本名稱和 code 由開發者在平台自定義,不強制叫 BASIC/PRO/ULTIMATE。版本價格和功能清單僅在勾選「平台代收授權費」時展示在購買頁。
3.3 錯誤碼處理(LicenseError)
SDK 抛出 LicenseError,攜帶 error_code 屬性:
from ps_license_sdk import LicenseError
try:
result = client.verify_cached(...)
except LicenseError as e:
if e.error_code == "expired":
open_purchase_page()
elif e.error_code == "revoked":
show_message("授權已被吊銷,請聯繫客服")
elif e.error_code == "machineLimit":
show_message("已達機器綁定上限,請在個人中心解綁舊設備")
elif e.error_code == "NETWORK_ERROR":
show_message("網絡異常,請檢查網絡後重試")
else:
show_message(f"校驗失敗:{e}")
| 錯誤碼 | 含義 | 客戶端建議處理 |
|---|---|---|
codeNotFound |
授權碼不存在 | 檢查輸入 |
revoked |
已吊銷 | 提示聯繫客服 |
expired |
已過期 | 引導購買/續費 |
machineLimit |
機器綁定數已滿 | 引導去個人中心解綁 |
tooManyAttempts |
觸發限流 | 提示稍後重試 |
trialNotEnabled |
產品未開啟試用 | 檢查平台配置 |
trialAlreadyPurchased |
已購買過該產品,無需再領取試用 | 提示已購並引導至購買頁 |
trialAlreadyPurchased |
已購買過該產品,無需再領取試用 | 提示已購並引導至購買頁 |
trialAlreadyPurchased |
已購買過該產品,無需再領取試用 | 提示已購並引導至購買頁 |
trialAlreadyPurchased |
已購買過該產品,無需再領取試用 | 提示已購並引導至購買頁 |
NETWORK_ERROR |
網絡/超時 | 離線寬限或提示重試 |
3.4 購買頁跳轉(僅場景 A)
3.4.1 購買頁 URL
https://www.powersoftware.app/product/license/purchase?productUniqueCode={productUniqueCode}&machineCode={machineCode}
SDK 方法:
url = client.purchase_url(mc)
調試機訪問該頁面時,頂部會出現「調試模式(測試環境)」徽標,支付走測試通道(見第四章)。 語言由購買頁按用戶瀏覽器自動檢測(URL 前綴 /
Accept-Language),SDK 無需關心。
3.4.2 站點:統一用國際站 .app,開發者無需選擇購買站
powersoftware.app(國際站) |
powersoftware.cn(國內站) |
|
|---|---|---|
| 支付方式 | Waffo(卡 / Apple Pay / Google Pay 等)+ PayPal + 支付寶 | 僅支付寶 |
| 國家/幣種 | Cloudflare 按 IP 自動識別(CN→CNY,其餘→USD) | 固定 country=CN,人民幣 |
| 語言 | 按 URL 前綴 / Accept-Language 自動檢測 |
固定 zh-CN |
| 定位 | 開發者唯一需要使用的購買入口 | 國際站支付寶支付的承接站 |
開發者無需做購買站選擇:purchaseUrl 統一指向國際站 .app。海外用戶在 .app 直接完成 Waffo / PayPal 支付;國內用戶在 .app 選擇支付寶時,平台會自動跳轉到國內站 .cn 完成支付寶付款(登錄狀態自動同步,無需重新登錄),支付成功後回到授權流程。整條鏈路對用戶和開發者都是透明的。
# 正確:固定使用國際站,不要按地區/語言切換 base
url = client.purchase_url(mc)
# 不建議:自行判斷地區傳 .cn base——支付寶跳轉已由平台處理,
# 且硬編碼 .cn 會丟失 Waffo / PayPal 支付方式
四、調試階段(雙環境,v4 新增)
上線前最穩妥的驗收方式:把自己日常開發用的電腦登記為「調試設備」,用真實支付鏈路走一遍完整流程。
4.1 登記機器碼
- 個人中心 →「我的機器碼」→ 登記調試電腦的機器碼
- 機器碼可用 SDK 的
machine_code()生成(同一台機器三語言結果一致)
- 機器碼可用 SDK 的
- 記下該機器碼
4.2 註冊調試設備
- 開發者中心 → 產品列表 → 目標產品的「調試設備」按鈕
- 在彈窗中從已登記機器碼中選擇,添加到本產品(可寫備註)
- 限制:每個產品最多 3 台調試設備;支持開關(臨時停用路由)與移除
4.3 調試機上會發生什麼
在已註冊且啟用中的調試機上,該產品的全鏈路自動切換到 Waffo Test 環境:
調試機(你的電腦) 幂棧網平台(服務端自動判定環境)
│ │
│ claimTrial(machineCode)
├─────────────────→│ 該機器是本產品調試機 → 走 Test 路徑
│ │
│ ← 試用授權(T- 前綴授權碼,寫測試授權表)
│ │
│ purchaseUrl(machineCode)
├─────────────────→│ 購買頁顯示「調試模式(測試環境)」徽標
│ │ → 用 Waffo Test 測試卡支付(不扣真錢)
│ │ → 訂單落測試訂單表,平台發測試碼(T- 碼)
│ ← 平台發碼(T- 碼)
│ │
│ activate(T-碼, machineCode)
├─────────────────→│ 按 T- 前綴直接定位測試表
│ ← activationToken│
│ │
│ verifyCached(...)
├─────────────────→│ 校驗通過
│ ← { valid, edition, expiryTime }
要點:
- 識別方式:授權碼帶
T-前綴即測試授權;購買頁頂部會出現「調試模式(測試環境)」徽標 - 支付:走 Waffo Test 收銀台,使用測試卡(如
4576 ... 0110)完成支付,不發生真實扣款 - 零代碼改動:客戶端不需要任何改動,同一份代碼在調試機和真實用戶機器上行為一致(只是後端落表不同)
4.4 建議的調試清單
- 調試機首次啟動 →
claimTrial成功,拿到T-前綴試用碼 - 試用期內
verifyCached返回valid,付費功能放行 -
purchaseUrl打開購買頁,確認出現「調試模式」徽標 - 測試卡完成支付 → 收到測試授權碼(郵件/頁面)
-
activate激活成功 →verifyCached通過 - 版本攔截正確(低版本碼訪問高版本功能被攔截)
- 機器綁定上限(
machineLimit)與解綁路徑正常 - (僅場景 B) 調試機調
generateForSoftware返回T-前綴授權碼,激活校驗正常;同一接口換未登記機器調用返回正式碼 - 換一台未登記的機器重複
claimTrial,確認走生產鏈路(對照驗證)
4.5 調試注意事項
| 事項 | 說明 |
|---|---|
| 測試數據清理 | 測試授權/訂單不影響生產,無需清理;如需重置可在調試設備面板移除後重新添加 |
| 調試開關 | 臨時不想走測試鏈路時,在調試設備面板關閉開關即可,無需刪設備 |
| 僅推廣產品 | 產品形態為「僅推廣」時不同步 Waffo 商品目錄,無調試購買鏈路 |
| 無有效價格 | 主/副價格與所有授權版本均無正價時,測試商品同步會失敗(釘釘告警),請至少配置一個版本價格 |
五、上線階段
5.1 提交審核
- 調試清單全部通過後,在產品表單點「保存並提交審核」
- 產品進入審核佇列(
PENDING_RELEASE)
調試期保存過草稿的產品,提審時內容即為最新草稿內容;審核期間再編輯會自動回退為草稿狀態(防止審核中內容變更),需重新提審。
5.2 審核通過 → 自動同步生產
平台運營審核通過後:
- 產品狀態變為已發佈、上架
- 平台自動把商品同步到 Waffo 生產環境(回寫
waffo_product_id),創建/恢復生產收銀台商品 - 產品詳情頁、搜索結果對全部用戶可見
5.3 真實用戶鏈路(生產)
真實用戶(非調試機)的鏈路與調試完全一致,只是全部落在生產表:
首次啟動 → claimTrial 領試用(正式授權碼,無 T- 前綴)
→ 試用到期 → purchaseUrl 跳購買頁(支付寶 / PayPal 真實支付)
→ 平台支付成功自動發碼 + 郵件送達
→ activate 激活 → verifyCached 校驗放行
場景 B(自行收款)的用戶不走平台購買頁:用戶在你的渠道付費後,由你的服務端調
generateForSoftware發正式授權碼,後續激活/校驗鏈路與場景 A 相同。
5.4 上線驗證清單
- 用一台未登記為調試機的電腦訪問產品詳情頁,確認正常展示
- 購買頁無「調試模式」徽標
- 真實小額支付 → 發碼 → 激活成功
- 開發者中心訂單列表能看到該筆訂單(測試訂單不會出現在此)
六、上線後運營
| 操作 | 入口 | 說明 |
|---|---|---|
| 查看訂單 | 開發者中心 → 我的訂單 | 僅生產訂單;測試訂單不參與分潤與對賬 |
| 用戶解綁 | 用戶個人中心 / 開發者人工授權 | 換綁配額:解綁後 30 天內不可再次解綁 |
| 版本迭代 | 產品編輯 → 保存草稿 / 提審 | 編輯會再次異步同步 Waffo Test,可持續用調試機驗證新版本 |
| 退款 | Waffo Dashboard | 買家發起工單、商家在 Dashboard 審核;測試訂單退款僅吊銷測試授權 |
| 下線調試 | 調試設備面板移除設備 | 建議版本穩定後移除調試機,避免誤用測試鏈路 |
七、常見問題(FAQ)
Q1:調試期需要修改客戶端代碼或配置嗎? 不需要。環境路由由平台服務端根據「機器碼是否在調試設備列表」自動判定,SDK 調用完全一致。
Q2:調試機上拿到的授權碼能給真實用戶用嗎?
不能也不建議。T- 碼只在測試表有效,且調試數據不參與任何生產邏輯;給真實用戶發測試碼會導致其無法通過正常校驗路徑獲得售後保障。
Q3:調試需要花錢嗎? 不需要。測試支付通道使用測試卡,不發生真實扣款;測試訂單不參與分潤/結算。
Q4:調試會影響我的產品審核嗎? 不會。調試數據與審核完全解耦;草稿狀態即可調試,提審與否由你決定。
Q5:多台電腦都想調試怎麼辦? 每個產品最多登記 3 台調試設備;在調試設備面板添加/移除即可。
Q6:產品形態是「僅推廣」或沒配置價格,能調試購買嗎? 不能。僅推廣產品不同步 Waffo 商品目錄;無有效價格時測試商品同步會失敗。此類產品只能調試試用與校驗鏈路。
Q7:忘記關調試開關就上線了會怎樣? 影響範圍僅限你登記的那台機器——它仍走測試鏈路;所有真實用戶不受影響。確認穩定後在調試設備面板移除即可。
八、集成清單(上線前逐項核對)
場景 A(平台完整鏈路)
- 在幂棧網發佈產品,售賣方式選「先用後付」
- 配置試用天數(建議 7~14 天)
- 配置授權版本(edition code + 名稱 + 價格 + 功能清單)
- 確認「平台代收授權費」已勾選(先用後付強制勾選)
- 記下
productUniqueCode - 拷貝 SDK 源碼到項目(見 2.3.1)
- 實現
claimTrial→ 首次啟動領取試用 - 實現
activate→ 用戶輸入授權碼激活 - 實現
verifyCached→ 點擊付費功能時校驗 - 實現
purchaseUrl→ 未授權跳轉購買頁(統一用國際站.app,無需選擇站點) - 實現本地憑證持久化(
licenseCode+activationToken) - 實現 edition 層級比較邏輯(見 3.2)
- 實現
LicenseError錯誤碼處理(見 3.3) - 登記調試機並走通雙環境調試清單(見 4.4)
- 提審 → 審核通過 → 上線驗證(見 5.4)
場景 B(訂單不在平台)
- 在幂棧網發佈產品,開啟
licenseEnabled - 配置授權版本(edition code + 名稱);如需平台代收,勾選「平台代收授權費」並填寫價格
- 在開發者後台獲取
licenseApiSecret - 記下
productUniqueCode - 搭建服務端保管授權密鑰
licenseApiSecret,實現發碼接口(密鑰不可下發到客戶端) - 客戶端拷貝 SDK 源碼到項目
- 服務端實現
generateForSoftware(發碼) - 服務端實現
upgradeForSoftware(升級/續費) - 客戶端實現
activate/verifyCached - 實現本地憑證持久化
- 實現 edition 層級比較邏輯(見 3.2)
- 實現
LicenseError錯誤碼處理(見 3.3) - 登記調試機驗證
T-碼鏈路(見 4.4) - 提審 → 審核通過 → 上線驗證(見 5.4)
附錄:SDK 倉庫(GitHub)
github.com/mizhanchengxi/powersoftware-license-sdk
├── node/ SDK 源碼(ESM, 零依賴, 單文件)
├── python/ SDK 源碼(py3, 零依賴, 3 個文件)
├── java/ SDK 源碼(Java 8+, 零依賴, 3 個文件)
└── docs/ SDK 規範文檔
三個包均提供:machineCode() / sign() / LicenseClient(含 activate / verify / deactivate / claimTrial / generateForSoftware / upgradeForSoftware / verifyCached / purchaseUrl)。
本文檔為 客戶端軟件授權接入指南(CLIENT_SOFTWARE_GUIDE) 的 v4 升級版,完整覆蓋其全部內容,並新增雙環境調試與草稿/提審能力。