Skip to main content

go-signature-sample


package main

import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"fmt"
"strings"
)

const CLIENT_ID = "Client-Id"
const REQUEST_ID = "Request-Id"
const REQUEST_TIMESTAMP = "Request-Timestamp"
const REQUEST_TARGET = "Request-Target"
const DIGEST = "Digest"
const SYMBOL_COLON = ":"

// Generate Digest
func generateDigest(jsonBody string) string {
converted := []byte(jsonBody)
hasher := sha256.New()
hasher.Write(converted)
return (base64.StdEncoding.EncodeToString(hasher.Sum(nil)))

}

func generateSignature(clientId string, requestId string, requestTimestamp string, requestTarget string, digest string, secret string) string {
// Prepare Signature Component
fmt.Println("----- Component Signature -----")
var componentSignature strings.Builder
componentSignature.WriteString(CLIENT_ID + SYMBOL_COLON + clientId)
componentSignature.WriteString("\n")
componentSignature.WriteString(REQUEST_ID + SYMBOL_COLON + requestId)
componentSignature.WriteString("\n")
componentSignature.WriteString(REQUEST_TIMESTAMP + SYMBOL_COLON + requestTimestamp)
componentSignature.WriteString("\n")
componentSignature.WriteString(REQUEST_TARGET + SYMBOL_COLON + requestTarget)
componentSignature.WriteString("\n")
componentSignature.WriteString(DIGEST + SYMBOL_COLON +digest)
// If body not send when access API with HTTP method GET/DELETE
if len(digest) > 0 {
componentSignature.WriteString("\n")
componentSignature.WriteString(DIGEST + SYMBOL_COLON +digest)
}

fmt.Println(componentSignature.String())
fmt.Println("")

// Calculate HMAC-SHA256 base64 from all the components above
key := []byte(secret)
h := hmac.New(sha256.New, key)
h.Write([]byte(componentSignature.String()))
signature := base64.StdEncoding.EncodeToString(h.Sum(nil))
// Prepend encoded result with algorithm info HMACSHA256=
return "HMACSHA256="+signature
}

// Sample of Usage
func main() {

// Genreate Digest from JSON Body
var jsonBody = '{\"order\":{\"invoice_number\":\"INV-20210124-0001\",\"amount\":150000},\"virtual_account_info\":{\"expired_time\":60,\"reusable_status\":false,\"info1\":\"Merchant Demo Store\"},\"customer\":{\"name\":\"Taufik Ismail\",\"email\":\"taufik@example.com\"}}'
digest := generateDigest(jsonBody);
fmt.Println("----- Digest -----")
fmt.Println(digest)
fmt.Println("")

// Generate Signature
headerSignature := generateSignature(
"yourClientId",
"yourRequestId",
"2020-10-21T03:38:28Z",
"/request-target/goes-here", // For merchant request to DOKU, use DOKU path here. For HTTP Notification, use merchant path here
digest, // Set empty string for this argumentes if HTTP Method is GET/DELETE
"secret-key-from-DOKU-back-office")

fmt.Println("----- Header Signature -----")
fmt.Println(headerSignature)
}