---
# System prepended metadata

title: 雲策外部API接入文件

---

# 雲策外部API接入文件

貴司在申請到系統之後，會拿到一組唯一的「API Key」，和公司單位識別號「Company Number」，所有跟 API Server 的互動都是透過這組API Key來產生「檢查碼(X-CHECKSUM)」。

為了保證資料傳輸的正確性，在呼叫任何一隻API之前，都必須在檔頭(Header)填入檢查碼，以確保所有的API呼叫都是由貴司服務發出。

檢查碼的計算公式為：
X-CHECKSUM = sha256(jsonToString(body) + api_key)

SHA256 Online: 
https://emn178.github.io/online-tools/sha256.html


範例：

api_key = abc123
body = {
    "sportname": "football",
    "gamestatus": "inplay"
}

將 body 轉成字串之後跟 api_key 串接，會得到
{"sportname":"football","gamestatus":"inplay"}abc123

對字串做 sha256雜湊 之後，得到檢查碼:
e9f9962fa91bb9d7a02fda394c3c0d9e8753ebd81629b2a503cf85caba6c147c

將檢查碼(X-CHECKSUM),公司單位識別號(X-COMPANY-NUM)塞到檔頭Header，跟body一起傳送到 API Server

Header:
{
    "Content-Type": "application/json",
    "X-COMPANY-NUM": "1",
    "X-CHECKSUM": "e9f9962fa91bb9d7a02fda394c3c0d9e8753ebd81629b2a503cf85caba6c147c"
}

Golang程式範例:
```golang=
package main

import (
	"bytes"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"time"
)

const (
	SPORT_FOOTBALL   = 0 
	SPORT_BASKETBALL = 1 
	SPORT_TENNIS     = 2
	SPORT_BASEBALL   = 3 

	STATUS_IN_PLAY     = 0 
	STATUS_PRE_MATCH   = 1 
	STATUS_EARLY_MATCH = 2
	STATUS_FINISHED    = 3
)

type GetMatchesRequest struct {
	SportName      int      `json:"SportName"`
	GameStatus     int      `json:"gameStatus"`
	TournamentName []string `json:"tournamentName"`
	MarketType     []int32  `json:"marketType"`
	StartTime      *string  `json:"startTime"`
	EndTime        *string  `json:"endTime"`
}

var (
	ApiKey     = "abc123" // Company key
	CompanyNum = "1"      // Company number
	ApiServer  = "http://localhost:8080"
)

func main() {

	req := GetMatchesRequest{
		SportName:      SPORT_FOOTBALL,
		GameStatus:     STATUS_IN_PLAY,
		TournamentName: []string{"歐冠"},
		MarketType:     []int32{1},
		StartTime:      nil,
		EndTime:        nil,
	}

	path := "/v1/getMatches"
	respBody, isErr := PostDataToTP(req, path)
	if isErr {
		log.Printf("post data to TP failed\n")
		return
	}

	log.Println("respBody: ", string(respBody))
}

func PostDataToTP(data interface{}, path string) (respBody []byte, isErr bool) {

	jsonData, checksum, isErr := GenCheckSum(data)
	if isErr {
		isErr = true
		log.Println("[PostDataToTP] checksum data failed.")
		return
	}

	targetUrl := fmt.Sprintf("%s%s", ApiServer, path)

	req, err := http.NewRequest("POST", targetUrl, bytes.NewBuffer(jsonData))
	if err != nil {
		isErr = true
		log.Printf("[PostDataToTP] req setup failed. err: %s\n", err)
		return
	}

	req.Header.Set("X-CHECKSUM", checksum)
	req.Header.Set("X-COMPANY-NUM", CompanyNum)
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{
		Timeout: 30 * time.Second,
	}
	resp, err := client.Do(req)
	if err != nil {
		isErr = true
		log.Printf("[PostDataToTP] connect to TP failed. err: %s\n", err)
		return
	}
	defer resp.Body.Close()

	respBody, err = io.ReadAll(resp.Body)
	if err != nil {
		isErr = true
		log.Printf("[PostDataToTP] respBody transfer failed. err: %s\n", err)
		return
	}
	return
}

func GenCheckSum(anything any) (jsonData []byte, checksum string, isErr bool) {
	var err error
	jsonData, err = json.Marshal(anything)
	if err != nil {
		isErr = true
		log.Printf("[GenCheckSum] jsonEncode failed. err: %s\n", err)
		return
	}

	hash := sha256.New()
	hash.Write([]byte(string(jsonData) + ApiKey))
	preChecksum := hash.Sum(nil)
	Checksum := hex.EncodeToString(preChecksum)
	checksum = Checksum

	return
}
```
