Skip to content

Go Sample

This Go example is based on the Laravel framework and uses the net/http library to make requests.

Signature implemention

go
package main

import (
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"sort"
	"strings"
)

func Sign(params map[string]string, apiToken string) string {
	keys := make([]string, 0, len(params))
	for k := range params {
		if k != "sign" && params[k] != "" && params[k] != null {
			keys = append(keys, k)
		}
	}
	sort.Strings(keys)

	var builder strings.Builder
	builder.WriteString(apiToken)

	for _, k := range keys {
		builder.WriteString("&" + k + "=" + params[k])
	}

	hash := md5.Sum([]byte(builder.String()))
	return hex.EncodeToString(hash[:])
}

Create collection order

The following shows how to create a collection order. The payout request is similar.

go
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"time"
)

func main() {
	params := map[string]string{
		"mch_id":       "2050",                          // Merchant ID
		"trans_id":     "E1763923463",                   // Transaction ID of your system
		"channel":      "bank",                          // Channel code
		"amount":       "200000.00",                     // Order amount
		"currency":     "VND",                           // Currency
		"callback_url": "https://api.blackhole.com",     // Webhook url
		"remarks":      "callme",                        // Remarks
		"nonce":        RandString(8),                   // Random string
		"timestamp":    fmt.Sprintf("%d", time.Now().Unix()), // UNIX timestamp
	}

	apiToken := "0xFAKE_TOKENx0"
	params["sign"] = Sign(params, apiToken)

	bodyBytes, err := json.Marshal(params)
	if err != nil {
		panic(err)
	}

	url := "http://domain/api/v1/mch/pmt-orders"
	req, err := http.NewRequest("POST", url, bytes.NewReader(bodyBytes))
	if err != nil {
		panic(err)
	}
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{Timeout: 5 * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	defer resp.Body.Close()

	respBody, _ := ioutil.ReadAll(resp.Body)

	if resp.StatusCode != http.StatusOK {
		fmt.Println("HTTP error code:", resp.StatusCode)
	} else {
		var result map[string]interface{}
		if err := json.Unmarshal(respBody, &result); err == nil {
			if code, ok := result["code"].(float64); !ok || int(code) != 200 {
				reason := result["message"]
				fmt.Println("Error:", reason)
			} else {
				fmt.Println("Success:", result)
			}
		} else {
			fmt.Println("Invalid json:", err)
		}
	}
}

func RandString(n int) string {
	const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
	b := make([]byte, n)
	for i := range b {
		b[i] = letters[time.Now().UnixNano()%int64(len(letters))]
	}
	return string(b)
}

Released under the MIT License.