Authorization SDK Specification
vv3.1
Authorization SDK Specification (v3
Basis:
ps-help/v3/doc/售卖方式与授权购买链路_v3.mdHelp Center LICENSE_API_DOC (v3). Objective: Consistent behavior of the Node/Python/Java SDKS (machine code, signature, interface, cache, error code, purchase page redirect).
Machine code algorithm (Consistent across languages)
The three language SDKS on the same machine must generate the same one machineCode.
Fingerprint source pressPrioritySelect, stop when a valid value is reached:
fingerprint = 硬件序列号 → 系统机器 ID → hostname | os | arch(兜底)
Priority 1: Hardware serial number (BIOS SN, unchanged after reinstalling the system)
| System | Source | Acquisition method | Permission |
|---|---|---|---|
| Windows | BIOS SerialNumber | wmic bios get serialnumberDowngrade PowerShell Get-CimInstance Win32_BIOS) |
Ordinary user |
| macOS | Hardware serial number | system_profiler SPHardwareDataType "Extract" Serial Number |
Ordinary user |
| Linux | Product serial number | read /sys/class/dmi/id/product_serial"Demotion dmidecode -s system-serial-number) |
root required |
Priority 2: System machine ID (generated during installation, unchanged on the same machine)
| System | Source | Acquisition method | Permission |
|---|---|---|---|
| Windows | MachineGuid | Registration form HKLM\SOFTWARE\Microsoft\Cryptography |
Ordinary user |
| macOS | IOPlatformUUID | ioreg -d2 -c IOPlatformPlatformDevice |
Ordinary user |
| Linux | machine-id | read /etc/machine-id"Demotion /var/lib/dbus/machine-id) |
All users |
Priority 3: Fallback (hostname | os | "arch"
It is used when both the hardware serial number and the system machine ID fail to be obtained.
| Field | Node | Python | Java |
|---|---|---|---|
| hostname | os.hostname() |
socket.gethostname() |
InetAddress.getLocalHost().getHostName() |
| os | os.platform() |
sys.platform |
System.getProperty("os.name") |
| arch | os.arch() |
platform.machine() |
System.getProperty("os.arch") |
Unified processing
- Remove the first and last Spaces from all fields and convert them to lowercase.
- Filter manufacturer placeholder value
To be filled by O.E.M./None/0/Default/Not Available/Not Specified";" - The concatenation characters are unified as
|Overall againtoLowerCase().
machineCode = 'M' + base64url( sha256( fingerprint ) ).slice(0, 32)
machineCode At least 8 bits, unique across all platforms, and internally cached in the SDK (within the process).
2. Signature Rules (Mandatory for software/generate and software/upgrade)
The signature string is in a fixed order and separated by line breaks (default blank value:edition Empty stringexpiryDays "0licenseCode Empty string:
productUniqueCode \n machineCode \n edition \n expiryDays \n clientOrderId \n licenseCode \n timestamp
signature = base64url( HMAC-SHA256( licenseApiSecret, 签名串 ) );timestamp It is in milliseconds. The time difference between the platform verification and the server is no more than 5 minutes (anti-replay).
3. Interface list
Prefixhttps://www.powersoftware.app/frontApi(Can be passed baseUrl "Cover".
| Interface | "Path" | Authentication | SDK method |
|---|---|---|---|
| Activate | POST /license/activate |
no | activate(licenseCode, machineCode) |
| Verification | POST /license/verify |
no | verify(licenseCode, machineCode, activationToken) |
| Unbind | POST /license/deactivate |
Log in (browser scene) | deactivate(licenseCode, machineCode) |
| The code is sent within the software | POST /license/software/generate |
HMAC signature | generateForSoftware({...}) |
| Software in-app upgrade/renewal | POST /license/software/upgrade |
HMAC signature | upgradeForSoftware({...}) |
| Claim a trial | POST /license/trial/claim |
no | claimTrial(machineCode) |
generateForSoftware / upgradeForSoftware Automatic supplementation timestamp + signature;claimTrial The product requires payment after use.
4. Local credentials and verification cache
- "LocalOnly remaining:
licenseCode,activationTokenThe most recent verify result{ valid, edition, expiryTime, trialExpiryTime }+ Timestamp.trialExpiryTimeis the trial expiry snapshot (ISO8601,nullwhen not upgraded from a trial) and can be used as a grace window for top-tier features. - No longer existDecryptable complete authorization information (anti-reverse engineering is meaningless, only used for caching).
- Verify the cache TTL for 60 seconds: When clicking on the payment function, check the cache first. Use it directly if it has not expired. Call the server again if it has expired or failed
verify. - Server-side revocation, refund or upgrade will actively invalidate the cache (the platform side has already implemented this), and the SDK does not need to be aware of it.
5. Paid function interception and purchase page redirection
Click the paid menu button:
verifyCached(licenseCode, machineCode, activationToken)Return valid and not expired → Pass;- Return invalid/Expired/unactivated → Pop-up prompt "Activation authorization needs to be purchased";
- "Generated
machineCodeJump to the purchase page (the product identification is.productUniqueCode(Carry the machine code)
https://www.powersoftware.app/product/license/purchase?productUniqueCode={productUniqueCode}&machineCode={machineCode}
Multilingual sites add a language prefix before the path, such as /en-US/product/license/purchase;productUniqueCode Passed in by the constructor."
5.1 Purchase Station Selection:.app(International Station) vs .cn(Domestic Station
Powerstack has two sites, one with SDK purchaseUrl() "Through base Parameter switching
powersoftware.app(International Station |
powersoftware.cn(Domestic Station |
|
|---|---|---|
| Payment method | Alipay + PayPal | Only Alipay |
| Country/Currency | Cloudflare automatically identifies by IP (CN→CNY, rest →USD) | Fixed country=CNRMB |
| "Language" | Press the URL prefix / Accept-Language Automatic detection |
Fixed zh-CN |
| Applicable users | International users/overseas | Users in Chinese mainland |
SDK default .appNo automatic judgment is made. The client software needs to decide which one to upload by itself base.
Judgment method
Method One: By system language (recommended
import locale
def get_purchase_base():
sys_lang = locale.getdefaultlocale()[0] or ""
if sys_lang.startswith("zh"):
return "https://www.powersoftware.cn"
return "https://www.powersoftware.app"
function getPurchaseBase() {
const lang = process.env.LANG || "";
return lang.toLowerCase().startsWith("zh")
? "https://www.powersoftware.cn"
: "https://www.powersoftware.app";
}
String getPurchaseBase() {
return "zh".equals(Locale.getDefault().getLanguage())
? "https://www.powersoftware.cn"
: "https://www.powersoftware.app";
}
Method Two: User Settings items The Settings interface offers a "Region" option, which users can choose by themselves.
Method Three: Hard coding Software that is only targeted at domestic users is directly hardcoded base="https://www.powersoftware.cn".
For details, please refer to 语言与国家逻辑 Section 2.4
6. Error Code (SDK throws errors uniformly carry errorCode)
codeNotFound,revoked,expired,machineLimit,tooManyAttempts,signatureInvalid,apiSecretMissing,productNotEnabled,trialNotEnabled,trialAlreadyPurchased,trialAlreadyPurchased,trialAlreadyPurchased,trialAlreadyPurchased,machineCodeInvalid,orderAlreadyUsed,editionRequired,productNotFound,trialFirstRequired,alreadyOwned Etc. Network/timeout errors are unified as NETWORK_ERROR.
7. Package structure
ps-sdk/
node/ @mizhanchengxi/ps-license-sdk(ESM,零依赖)
python/ ps-license-sdk(py3,零依赖)
java/ com.powersoftware:sdk(Java 8+,JDK 自带 HTTP/加密)
All three packages are provided:machineCode(),sign(),LicenseClient(The above 6 methods + verifyCached + purchaseUrl"