Go 签名 SDK 接入指南

功能说明

Go 签名 SDK 用于为美图开放平台 API 请求生成 AK/SK 签名。SDK 根据请求方法、URL、请求头和 body 生成 Authorization,并返回可直接发送的 *http.Request

SDK 负责签名和创建请求;网络请求由业务代码通过 http.Client.Do 发送。

环境要求

  • Go 1.20 或更高版本
  • 已获取开放平台 Access Key(AK)和 Secret Key(SK)
  • 服务端可通过 HTTPS 访问 openapi.meitu.com
  • SK 应仅保存在服务端,不得下发到客户端

下载与引入

SDK 版本:1.0.3

下载 AIGCP-API-go-sdk-1.0.3.zip

解压后的主要文件:

AIGCP-API-go-sdk-1.0.3/
├── demo.go
├── go.mod
└── signer/
    └── sign.go

压缩包的模块名为 github.com/mtlab/api,示例中的引入方式为:

import "github.com/mtlab/api/signer"

直接运行示例时,将代码保存为解压目录中的 demo.go,然后执行 go run .。集成到已有 Go 项目时,将 signer 目录复制到项目中,并将 import 改为该项目对应的模块路径。

接口说明

创建签名器

signer.NewSigner(accessKey, secretKey) 返回 *signer.Signer

参数类型说明
accessKeystring开放平台 AK
secretKeystring开放平台 SK

签名请求

Sign 方法定义:

func (s *Signer) Sign(url, method string, headers http.Header, body string) (*http.Request, error)
参数类型说明
urlstring完整请求 URL,包含路径和查询参数
methodstringHTTP 方法,如 http.MethodPosthttp.MethodGet
headershttp.Header待签请求头;必须包含与 URL 一致的 Host
bodystring最终发送的请求 body;GET 通常传空字符串
返回值说明
*http.Request已写入 X-Sdk-DateAuthorization 的请求,可直接发送
errorURL、请求或手动设置的签名时间格式无效时返回错误

Sign 会修改传入的 headers。签名完成后,应直接发送返回的 request。

POST 完整调用示例

以下示例调用正式同步任务提交地址:

https://openapi.meitu.com/api/v1/sdk/sync/push

请求 body 包含 tasktask_typeinit_imagesparamssync_timeout 五个顶层字段。params 的值是 JSON 字符串。示例中的 task、图片地址、params 和超时时间应替换为目标能力 API 文档规定的值。

package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"time"

	"github.com/mtlab/api/signer"
)

func main() {
	accessKey := os.Getenv("AIGCP_ACCESS_KEY")
	secretKey := os.Getenv("AIGCP_SECRET_KEY")
	if accessKey == "" || secretKey == "" {
		fmt.Fprintln(os.Stderr, "AIGCP_ACCESS_KEY and AIGCP_SECRET_KEY are required")
		os.Exit(1)
	}

	endpoint := "https://openapi.meitu.com/api/v1/sdk/sync/push"
	body := `{"task":"/v1/replace-with-product-task","task_type":"formula","init_images":[{"url":"https://example.com/input.jpg","profile":{"media_profiles":{"media_data_type":"url"},"version":"v1"}}],"params":"{\"parameter\":{\"rsp_media_type\":\"url\"}}","sync_timeout":30}`
	headers := make(http.Header)
	headers.Set(signer.HeaderHost, "openapi.meitu.com")
	headers.Set("Content-Type", "application/json")

	sign := signer.NewSigner(accessKey, secretKey)
	req, err := sign.Sign(endpoint, http.MethodPost, headers, body)
	if err != nil {
		fmt.Fprintln(os.Stderr, "sign request:", err)
		os.Exit(1)
	}

	client := &http.Client{Timeout: 60 * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		fmt.Fprintln(os.Stderr, "send request:", err)
		os.Exit(1)
	}
	defer resp.Body.Close()

	responseBody, err := io.ReadAll(resp.Body)
	if err != nil {
		fmt.Fprintln(os.Stderr, "read response:", err)
		os.Exit(1)
	}

	fmt.Printf("status=%s\n%s\n", resp.Status, responseBody)
	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
		os.Exit(1)
	}
}

运行:

export AIGCP_ACCESS_KEY='<your-access-key>'
export AIGCP_SECRET_KEY='<your-secret-key>'
go run .

GET 调用示例

GET 接口应使用对应能力文档提供的真实 URL。以下函数在签名前添加查询参数,并使用空 body 创建已签请求:

func buildSignedGetRequest(sign *signer.Signer, endpoint, taskID string) (*http.Request, error) {
	parsedURL, err := url.Parse(endpoint)
	if err != nil {
		return nil, err
	}

	query := parsedURL.Query()
	query.Set("task_id", taskID)
	parsedURL.RawQuery = query.Encode()

	headers := make(http.Header)
	headers.Set(signer.HeaderHost, parsedURL.Host)

	return sign.Sign(parsedURL.String(), http.MethodGet, headers, "")
}

该函数需要引入 net/url。调用时,endpoint 应为目标 GET 接口的完整 HTTPS 地址;task_id 参数名以对应接口文档为准。返回的 request 通过 http.Client.Do 发送。

注意事项

  • Host 必须与请求 URL 的主机一致。URL 含非默认端口时,Host 也应包含该端口。
  • URL、HTTP 方法、查询参数、请求头和 body 必须在调用 Sign 前确定;签名后不得修改。
  • JSON body 应只序列化一次。传给 Sign 的字符串必须与实际发送的字节完全一致。
  • GET 通常使用空字符串 body;POST 应传入最终 body。
  • 系统时间应保持同步。未设置 X-Sdk-Date 时,SDK 会自动写入当前 UTC 时间。
  • 默认情况下 SDK 会计算 body 的 SHA-256。仅当目标接口明确支持时,才可在签名前设置以下请求头:
headers.Set(signer.HeaderContentSha256, "UNSIGNED-PAYLOAD")
  • AK/SK 鉴权支持的 body 大小以平台和目标接口文档为准;现有签名说明规定为 12M 以内。

常见错误

现象处理方式
401、签名错误或鉴权失败确认 AK/SK、HTTP 方法、完整 URL、Host、查询参数、请求头和 body 与签名时一致。
时间校验失败同步服务器时间,并让 SDK 自动生成 X-Sdk-Date
POST body 验签失败确认 body 在签名后未被重新序列化、压缩、转码或修改。
查询参数验签失败使用 url.Values 在签名前构造最终查询字符串,签名后不再修改 URL。
UNSIGNED-PAYLOAD 请求失败确认目标接口支持该方式,并确认请求头名称和值完全一致。
网络超时或连接失败检查 HTTPS 地址、DNS、代理、出站网络和客户端超时配置。
返回非 2xx读取响应 body,并按目标能力 API 文档中的错误码处理。