Distromate Docs

Go 接入

使用 Go 语言集成 DistroMate SDK

准备工作

  1. 获取 dm_api.dlldm_api.go 文件
  2. 将 DLL 文件放置在程序运行目录
  3. dm_api.go 添加到项目中

依赖

  • Go 1.18 或更高版本
  • Windows 平台(使用 syscall 调用 DLL)

导入包

import "your_project/dmapi"

快速开始

package main

import (
    "fmt"
    "your_project/dmapi"
)

const publicKey = `
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
-----END PUBLIC KEY-----
`

func main() {
    // 创建 API 实例
    api, err := dmapi.New(publicKey, "dm_api.dll")
    if err != nil {
        fmt.Println("Failed to initialize:", err)
        return
    }

    // 1. 检查是否由 Launcher 启动
    if api.RestartAppIfNecessary() {
        // Launcher 已启动,退出当前进程
        return
    }

    // 2. 连接到 Launcher
    if !api.Connect(`\\.\pipe\distromate_pipe`, 5000) {
        fmt.Println("Connection failed")
        return
    }
    defer api.Close()

    // 3. 验证许可证
    data := api.Verify()
    if data == nil {
        fmt.Println("Verification failed")
        return
    }

    fmt.Println("License verified!")

    // 访问许可证数据
    if licenseKey, ok := data["license_key"].(string); ok {
        fmt.Println("License:", licenseKey)
    }

    if expiresAt, ok := data["expires_at"].(string); ok {
        fmt.Println("Expires:", expiresAt)
    }

    // 4. 通知初始化完成
    if !api.Initiated() {
        fmt.Println("Failed to notify initiated")
    }

    // 应用主逻辑...
    fmt.Println("Application running...")
}

API 参考

New

创建新的 DmApi 实例。

func New(publicKeyPEM string, dllPath string) (*DmApi, error)

参数:

参数类型描述
publicKeyPEMstringPEM 格式的 RSA 公钥
dllPathstringDLL 文件路径,空字符串表示使用默认路径 dm_api.dll

返回值:

  • 成功: *DmApi 实例
  • 失败: nil 和错误信息

RestartAppIfNecessary

检查程序是否由 Launcher 启动,如果不是则通过 Launcher 重启。

func (api *DmApi) RestartAppIfNecessary() bool

返回值:

  • true: 已启动 Launcher,当前进程应退出
  • false: 程序由 Launcher 启动,无需重启

Connect

连接到 Launcher。

func (api *DmApi) Connect(pipe string, timeout uint32) bool

参数:

参数类型描述
pipestringPipe 名称,格式: \\.\pipe\<name>
timeoutuint32超时时间(毫秒)

返回值: 连接是否成功

Close

关闭与 Launcher 的连接。

func (api *DmApi) Close()

Verify

验证许可证。自动生成 nonce 并验证响应签名。

func (api *DmApi) Verify() map[string]interface{}

返回值:

  • 成功: 包含许可证数据的 map
  • 失败: nil

Activate

激活许可证。自动生成 nonce 并验证响应签名。

func (api *DmApi) Activate() map[string]interface{}

返回值:Verify

Initiated

通知 Launcher 程序初始化完成。

func (api *DmApi) Initiated() bool

返回值: 操作是否成功

完整示例

package main

import (
    "fmt"
    "os"
    "your_project/dmapi"
)

const publicKey = `
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
-----END PUBLIC KEY-----
`

func main() {
    if err := run(); err != nil {
        fmt.Fprintln(os.Stderr, "Error:", err)
        os.Exit(1)
    }
}

func run() error {
    // 初始化 API
    api, err := dmapi.New(publicKey, "")
    if err != nil {
        return fmt.Errorf("init failed: %w", err)
    }

    // 检查启动方式
    if api.RestartAppIfNecessary() {
        fmt.Println("Restarting via launcher...")
        return nil
    }

    // 连接
    if !api.Connect(`\\.\pipe\distromate_pipe`, 5000) {
        return fmt.Errorf("connection failed")
    }
    defer api.Close()

    fmt.Println("Connected to launcher")

    // 验证
    data := api.Verify()
    if data == nil {
        return fmt.Errorf("verification failed")
    }

    // 解析许可证信息
    fmt.Println("License verified!")
    printLicenseInfo(data)

    // 通知完成
    if !api.Initiated() {
        fmt.Println("Warning: failed to notify initiated")
    }

    // 应用主逻辑...
    fmt.Println("Application running...")

    return nil
}

func printLicenseInfo(data map[string]interface{}) {
    if userName, ok := data["user_name"].(string); ok {
        fmt.Println("User:", userName)
    }

    if productId, ok := data["product_id"].(string); ok {
        fmt.Println("Product:", productId)
    }

    if expiresAt, ok := data["expires_at"].(string); ok {
        fmt.Println("Expires:", expiresAt)
    }

    if features, ok := data["features"].([]interface{}); ok {
        fmt.Println("Features:")
        for _, feature := range features {
            fmt.Printf("  - %v\n", feature)
        }
    }
}

项目结构

myapp/
├── main.go
├── dmapi/
│   └── dm_api.go
└── dm_api.dll

编译

# 编译 Windows 可执行文件
go build -o myapp.exe

# 交叉编译(从其他平台编译 Windows 程序)
GOOS=windows GOARCH=amd64 go build -o myapp.exe

Go Modules

// go.mod
module myapp

go 1.18

类型断言

由于 Go 是静态类型语言,从 map[string]interface{} 中获取值时需要进行类型断言:

data := api.Verify()
if data == nil {
    return
}

// 获取字符串
if licenseKey, ok := data["license_key"].(string); ok {
    fmt.Println("License:", licenseKey)
}

// 获取数字
if maxUsers, ok := data["max_users"].(float64); ok {
    fmt.Println("Max users:", int(maxUsers))
}

// 获取布尔值
if isActive, ok := data["is_active"].(bool); ok {
    fmt.Println("Active:", isActive)
}

// 获取数组
if features, ok := data["features"].([]interface{}); ok {
    for _, f := range features {
        if feature, ok := f.(string); ok {
            fmt.Println("Feature:", feature)
        }
    }
}

// 获取嵌套对象
if metadata, ok := data["metadata"].(map[string]interface{}); ok {
    if version, ok := metadata["version"].(string); ok {
        fmt.Println("Version:", version)
    }
}

注意事项

  1. Go SDK 内置了 RSA 签名验证功能
  2. DLL 只能在 Windows 平台上加载
  3. 所有 API 调用都是同步的
  4. 使用 defer api.Close() 确保连接被正确关闭
  5. JSON 数字默认解析为 float64 类型

On this page