Make SDK importable from module root
This commit is contained in:
@@ -0,0 +1,250 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.yuanzoo.cn/zhangzhengqiang/popi-zxl"
|
||||
)
|
||||
|
||||
// loadDotEnv 加载当前目录下的 .env,方便本地测试。
|
||||
func loadDotEnv(path string) {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
content, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 按行分割
|
||||
lines := strings.Split(string(content), "\n")
|
||||
|
||||
for i := 0; i < len(lines); i++ {
|
||||
line := strings.TrimSpace(lines[i])
|
||||
if line == "" || strings.HasPrefix(line, "#") || !strings.Contains(line, "=") {
|
||||
continue
|
||||
}
|
||||
|
||||
// 检查是否是多行值(以引号开始但不以引号结束)
|
||||
if strings.HasPrefix(line, `ZXCHAIN_PRIVATE_KEY="`) && !strings.HasSuffix(line, `"`) {
|
||||
// 收集多行私钥内容
|
||||
var privateKeyLines []string
|
||||
privateKeyLines = append(privateKeyLines, strings.TrimPrefix(line, `ZXCHAIN_PRIVATE_KEY="`))
|
||||
|
||||
// 继续读取后续行直到找到结束引号
|
||||
for i+1 < len(lines) && !strings.HasSuffix(strings.TrimSpace(lines[i+1]), `"`) {
|
||||
i++
|
||||
privateKeyLines = append(privateKeyLines, lines[i])
|
||||
}
|
||||
|
||||
// 添加最后一行(去掉结尾引号)
|
||||
if i+1 < len(lines) {
|
||||
i++
|
||||
lastLine := strings.TrimSpace(lines[i])
|
||||
if strings.HasSuffix(lastLine, `"`) {
|
||||
privateKeyLines = append(privateKeyLines, strings.TrimSuffix(lastLine, `"`))
|
||||
}
|
||||
}
|
||||
|
||||
privateKey := strings.Join(privateKeyLines, "\n")
|
||||
_ = os.Setenv("ZXCHAIN_PRIVATE_KEY", privateKey)
|
||||
continue
|
||||
}
|
||||
|
||||
// 处理普通单行配置
|
||||
key, value, ok := strings.Cut(line, "=")
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
key = strings.TrimSpace(key)
|
||||
value = strings.TrimSpace(value)
|
||||
if key == "" || os.Getenv(key) != "" {
|
||||
continue
|
||||
}
|
||||
|
||||
value = strings.Trim(value, `"'`)
|
||||
value = strings.ReplaceAll(value, `\n`, "\n")
|
||||
_ = os.Setenv(key, strings.TrimSpace(value))
|
||||
}
|
||||
}
|
||||
|
||||
// newClient 初始化至信链 SDK 客户端。
|
||||
func newClient() *zxchainsdk.SDKClient {
|
||||
privateKey := os.Getenv("ZXCHAIN_PRIVATE_KEY")
|
||||
|
||||
client, err := zxchainsdk.NewSDKClient(
|
||||
os.Getenv("ZXCHAIN_SECRET_ID"),
|
||||
os.Getenv("ZXCHAIN_SECRET_KEY"),
|
||||
privateKey,
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("初始化至信链客户端失败: %v", err)
|
||||
}
|
||||
|
||||
return client
|
||||
}
|
||||
|
||||
// h1 演示 Hash 上链。
|
||||
func h1() {
|
||||
client := newClient()
|
||||
|
||||
filePath := "/Users/ywlmac/Desktop/81520.jpeg"
|
||||
fileBytes, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
log.Fatalf("读取图片文件失败: %v", err)
|
||||
}
|
||||
|
||||
result, err := client.CreateHashAttestation(context.Background(), zxchainsdk.HashAttestationRequest{
|
||||
BizID: fmt.Sprintf("demo-image-%d", time.Now().Unix()),
|
||||
Scene: "sdk-image-hash-demo",
|
||||
ContentBytes: fileBytes,
|
||||
FileName: "81520.jpeg",
|
||||
FileSize: int64(len(fileBytes)),
|
||||
ContentType: "image/jpeg",
|
||||
StorageURI: filePath,
|
||||
Metadata: map[string]string{
|
||||
"source": "sdk-test",
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("Hash 上链失败: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println("Hash 上链成功")
|
||||
fmt.Println("evId:", result.ReceiptID)
|
||||
fmt.Println("txId:", result.RequestID)
|
||||
fmt.Println("sm3Hash:", result.SM3Hash)
|
||||
fmt.Println("blockHeight:", result.BlockHeight)
|
||||
fmt.Println("txTime:", result.TxTime)
|
||||
}
|
||||
|
||||
// h2 演示 Hash 证书查询。
|
||||
func h2(evID string) {
|
||||
client := newClient()
|
||||
|
||||
// 把这里替换成 h1 输出的 evId。
|
||||
// evID := "替换成你的evId"
|
||||
|
||||
result, err := client.GetHashCert(context.Background(), evID)
|
||||
if err != nil {
|
||||
log.Fatalf("查询 Hash 证书失败: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println("Hash 证书查询成功")
|
||||
fmt.Println("evId:", result.EvID)
|
||||
fmt.Println("certURL:", result.CertURL)
|
||||
}
|
||||
|
||||
// h3 演示 Hash 取证查询。
|
||||
func h3(evID string) {
|
||||
client := newClient()
|
||||
|
||||
// 至少填写一个查询条件:evId、sm3Hash 或 txId。
|
||||
req := zxchainsdk.HashAttestationQueryRequest{
|
||||
EvID: evID,
|
||||
// Hash: "也可以替换成 h1 输出的 sm3Hash",
|
||||
// TxID: "也可以替换成 h1 输出的 txId",
|
||||
}
|
||||
|
||||
var result *zxchainsdk.HashAttestationQueryResult
|
||||
var err error
|
||||
for attempt := 1; attempt <= 5; attempt++ {
|
||||
result, err = client.QueryHashAttestation(context.Background(), req)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
if attempt < 5 {
|
||||
log.Printf("Hash 取证查询暂未成功,第 %d 次失败:%v,等待后重试", attempt, err)
|
||||
time.Sleep(time.Duration(attempt*2) * time.Second)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
log.Fatalf("Hash 取证查询失败: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println("Hash 取证查询成功")
|
||||
fmt.Println("evId:", result.EvID)
|
||||
fmt.Println("txId:", result.TxID)
|
||||
fmt.Println("blockHeight:", result.BlockHeight)
|
||||
fmt.Println("txTime:", result.TxTime)
|
||||
fmt.Println("extendInfo:", result.ExtendInfo)
|
||||
}
|
||||
|
||||
// h4 演示简化的一站式证书生成(从 WorkPreviewURL 自动下载并计算哈希)。
|
||||
func h4() (string, error) {
|
||||
client := newClient()
|
||||
|
||||
result, err := client.CreateSimpleHashAttestationCertificate(context.Background(), zxchainsdk.SimpleHashAttestationCertificateRequest{
|
||||
UserName: "zzzzzq", // 申请用户名称
|
||||
UserID: "56142321", // 申请用户 ID
|
||||
WorkName: "测试作品", // 作品名称
|
||||
TaskID: "1231223", // 生成任务 ID
|
||||
CompletedAt: "2026.5.11 15:20:01", // 作品完成时间
|
||||
WorkPreviewURL: "https://popiart-public-1313913486.cos.ap-guangzhou.myqcloud.com/media/2026/0511/83218.jpg", // 作品预览图 URL
|
||||
// EvidenceHash 不传,SDK 会自动从 WorkPreviewURL 下载并计算 SM3 哈希
|
||||
|
||||
CertificateStorage: &zxchainsdk.COSCertificateStorage{
|
||||
BucketURL: os.Getenv("COS_BUCKET_URL"),
|
||||
PublicBaseURL: os.Getenv("COS_PUBLIC_BASE_URL"),
|
||||
SecretID: os.Getenv("COS_SECRET_ID"),
|
||||
SecretKey: os.Getenv("COS_SECRET_KEY"),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("简化证书生成失败: %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("简化证书生成成功")
|
||||
fmt.Println("UserName:", result.UserName)
|
||||
fmt.Println("UserID:", result.UserID)
|
||||
fmt.Println("WorkName:", result.WorkName)
|
||||
fmt.Println("TaskID:", result.TaskID)
|
||||
fmt.Println("CompletedAt:", result.CompletedAt)
|
||||
fmt.Println("WorkPreviewURL:", result.WorkPreviewURL)
|
||||
fmt.Println("EvidenceHash:", result.EvidenceHash)
|
||||
fmt.Println("ReceiptID (evId):", result.ReceiptID)
|
||||
fmt.Println("RequestID (txId):", result.RequestID)
|
||||
fmt.Println("BlockHeight:", result.BlockHeight)
|
||||
fmt.Println("TxTime:", result.TxTime)
|
||||
fmt.Println("SM3Hash:", result.SM3Hash)
|
||||
fmt.Println("PopiCertificateCertNo:", result.PopiCertificateCertNo)
|
||||
fmt.Println("PopiCertificateVerifyURL:", result.PopiCertificateVerifyURL)
|
||||
fmt.Println("PopiCertificateCertificateImageURL:", result.PopiCertificateCertificateImageURL)
|
||||
fmt.Println("ZXChainCertURL:", result.ZXChainCertURL)
|
||||
|
||||
return result.ReceiptID, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
loadDotEnv(".env")
|
||||
|
||||
// 只测试 h4 和 h3:先生成证书,再用 h4 返回的 evId 查询 Hash 取证。
|
||||
evID, err := h4()
|
||||
if err != nil {
|
||||
log.Printf("h4 测试失败: %v", err)
|
||||
evID = os.Getenv("ZXCHAIN_TEST_EV_ID")
|
||||
if evID == "" {
|
||||
evID = "302d355f4b7911f1bf330a77039e1980"
|
||||
}
|
||||
log.Printf("继续使用已有 evId 测试 h3: %s", evID)
|
||||
}
|
||||
h3(evID)
|
||||
|
||||
// 第一次测试:执行 Hash 上链,复制输出里的 evId。
|
||||
//h1()
|
||||
|
||||
// 第二次测试:把 h1() 注释掉,填好 h2 里的 evId,再打开下面这一行。
|
||||
//h2("302d355f4b7911f1bf330a77039e1980")
|
||||
|
||||
// 第三次测试:把 h1() 注释掉,填好 h3 里的 evId/sm3Hash/txId,再打开下面这一行。
|
||||
//h3("302d355f4b7911f1bf330a77039e1980")
|
||||
}
|
||||
Reference in New Issue
Block a user