# GoLang

<details>

<summary>Without Router - Current Approach</summary>

```go
package main

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

func main() {

	urlStr := "https://fip-1.dev.sahamati.org.in/v2/Accounts/discover"

	body := []byte(fmt.Sprintf(`{
        "ver": "2.0.0",
        "timestamp": "%s",
        "txnid": "f35761ac-4a18-11e8-96ff-0277a9fbfedc2",
        "Customer": {
            "id": "customer_identifier@AA_identifier",
            "Identifiers": [
                {
                    "category": "STRONG",
                    "type": "AADHAAR",
                    "value": "XXXXXXXXXXXXXXXX"
                }
            ]
        },
        "FITypes": [
            "DEPOSIT"
        ]
    }`, time.Now().UTC().Format(time.RFC3339)))

	client := &http.Client{
		Timeout: 30 * time.Second,
	}

	req, err := http.NewRequest("POST", urlStr, bytes.NewBuffer(body))
	if err != nil {
		fmt.Printf("Error creating request: %v\n", err)
		return
	}

	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("x-jws-signature", "eyJhbGciOiJSUzI1NiIsImtpZCI6IlRlZ1FhMms3MUlFWlotaEhxcm1ueWFFc3ZvSWloNWdrVUx2SjFfTEhibGsiLCJjcml0IjpbImI2NCJdLCJiNjQiOmZhbHNlfQ..Dux_bx7X-q1YSvyNmZiyPM60ZgaK3MshW...")
	req.Header.Set("x-simulate-res", "Ok")
	req.Header.Set("Authorization", "Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJsRlByWU4wR3dBQ3YyUzJFVFZyRkVvZVVlc2VzelppQ2xIaVY1M3hrU3JNIn0.eyJleHAiOjE3NDQ5NjgwNDAsImlhdCI6MTc0NDg4MTY0MCwianRpIjoiYzZiZTcyNDAtOWU5Ny00MzYwLTk3OGUtZWI5MTY0MWZiMmMwIiwiaXNzIjoiaHR0cHM6Ly9hcGkuZGV2LnNhaGFtYXRpLm9yZy5pbi9hdXRoL3JlYWxtcy9zYWhhbWF0aSIsInN1YiI6ImIyMzE1MTU3LWRmNzYtNGQzZS04ZjM2LWQ4NzZmY2ViOWFlZiIsInR5cCI6IkJlYXJlciIsImF6cCI6IkFBLVNJTVVMQVRPUiIsImFjciI6IjEiLCJzY29wZSI6ImVtYWlsIG1pY3JvcHJvZmlsZS1qd3QgcHJvZmlsZSBhZGRyZXNzIHBob25lIiwidXBuIjoic2VydmljZS1hY2NvdW50LWFhLXNpbXVsYXRvciIsImNsaWVudElkIjoiQUEtU0lNVUxBVE9SIiwiYWRkcmVzcyI6e30sImNsaWVudEhvc3QiOiIxMC4yMjQuMC4xODIiLCJyb2xlcyI6IkFBIiwic2VjcmV0LWV4cGlyeS10cyI6IjIwMjUtMTItMDRUMTU6MzM6MzQuMDU5MTgzIiwiY2xpZW50QWRkcmVzcyI6IjEwLjIyNC4wLjE4MiJ9.G-ErvIeZUtKkqN4CbaH09Nwzy9fUjKSD18xpNh6y74AQdB8YFfNuhC8m6nxMpDCLY2fUj8sIcQ--Jp-EYDxChSR8kQTbKDmYJzPGRGunO-hkLxPK83R3Q7Byc6KZot1lZlj-Dsv-l5JD0Ay0KpPr4bKqIas5FEZTx2qoA3p6J1CyNbiQ81t4_KxVoO44hmVKPe0FIVNLw9MK04bkHOwO-WMB9DoUX5Y8bBREYgRv_W3QEEC8gcI5vZLnHuBXSZSXQ3MDPSLOq7lGnMsxh5A0YF1Wvfqg3LJjXizMfIfRNMyq2M0eMwHQEWfjLNTEqS6Bd6qkjPREVdhRTTnHaggq9A")

	resp, err := client.Do(req)
	if err != nil {
		fmt.Printf("Error executing request: %v\n", err)
		return
	}
	defer resp.Body.Close()

	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		fmt.Printf("Error reading response body: %v\n", err)
		return
	}

	fmt.Printf("Status: %s\n", resp.Status)
	fmt.Printf("Headers: %v\n", resp.Header)
	fmt.Printf("Response Body: %s\n", string(respBody))

	if resp.StatusCode >= 400 {
		fmt.Printf("Error response received - Status Code: %d\n", resp.StatusCode)
	}
}

```

</details>

<details>

<summary>With Router Integration - Request</summary>

```go
package main

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

const (
	baseURL                    = "http://fip-1.sandbox.sahamati.org.in/fip-simulate"
	routerIntegrationHelperURL = "https://api.sandbox.sahamati.org.in/router-helper/v1/request/header"
	recipientID                = "FIP-SIMULATOR"
)

var httpClient = &http.Client{Timeout: 30 * time.Second}

func main() {
	// Step 1: Execute discovery request
	response, err := executeDiscoveryRequest()
	if err != nil {
		fmt.Printf("Account discovery failed. Error: %v\n", err)
		return
	}

	fmt.Println("Account discovery successful:", response)

	// Step 2: Do something with response
	performAnotherOperations(response)
}

/**
 * Executes account discovery:
 *  - Builds request
 *  - Adds router headers via Integration Helper
 *  - Sends request
 */
func executeDiscoveryRequest() (string, error) {
	route := "/Accounts/discover"

	// ReBIT defined request body
	rebitRequestBody := map[string]interface{}{
		"ver":      "2.0.0",
		"timestamp": time.Now().UTC().Format(time.RFC3339),
		"txnid":    "f35761ac-4a18-11e8-96ff-0277a9fbfedc2",
		"Customer": map[string]interface{}{
			"id": "9766334467@aa_simulator",
			"Identifiers": []map[string]interface{}{
				{
					"category": "STRONG",
					"type":     "AADHAAR",
					"value":    "XXXXXXXXXXXXXXXX",
				},
			},
		},
		"FITypes": []string{"DEPOSIT"},
	}

	// Step 1: Build initial request (with base URL)
	url := baseURL + route
	req, err := buildHttpRequest(url, map[string]string{}, rebitRequestBody)
	if err != nil {
		return "", fmt.Errorf("failed to build request: %w", err)
	}

	// Step 2: Add Sahamati router configuration (helper API call)
	req, err = addSahamatiConfiguration(req, route, rebitRequestBody)
	if err != nil {
		return "", fmt.Errorf("failed to add router configuration: %w", err)
	}

	// Step 3: Execute request
	resp, err := httpClient.Do(req)
	if err != nil {
		return "", fmt.Errorf("request execution failed: %w", err)
	}
	defer resp.Body.Close()

	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("failed to read response body: %w", err)
	}

	return string(respBody), nil
}

/**
 * Builds a basic POST request with headers + JSON body
 */
func buildHttpRequest(url string, headers map[string]string, body map[string]interface{}) (*http.Request, error) {
	jsonData, err := json.Marshal(body)
	if err != nil {
		return nil, err
	}

	req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
	if err != nil {
		return nil, err
	}

	req.Header.Set("Content-Type", "application/json")
	for k, v := range headers {
		req.Header.Set(k, v)
	}
	return req, nil
}

/**
 * Adds Sahamati Router headers by calling the Router Integration Helper API
 */
func addSahamatiConfiguration(req *http.Request, route string, rebitRequestBody map[string]interface{}) (*http.Request, error) {
	// Call router integration helper
	headerResponse, err := routerIntegrationHelper(route, rebitRequestBody)
	if err != nil {
		return nil, err
	}

	baseurl, ok := headerResponse["baseurl"].(string)
	if !ok || baseurl == "" {
		return nil, fmt.Errorf("Router Helper response missing required field 'baseurl'")
	}

	// Build new URL
	newURL := baseurl + route

	// Clone body (req.Body cannot be reused after read, so re-marshal)
	var originalBody map[string]interface{}
	json.NewDecoder(req.Body).Decode(&originalBody)
	req.Body.Close()
	jsonBody, _ := json.Marshal(rebitRequestBody)

	newReq, err := http.NewRequest(req.Method, newURL, bytes.NewBuffer(jsonBody))
	if err != nil {
		return nil, err
	}

	// Copy headers from old request
	for k, v := range req.Header {
		for _, vv := range v {
			newReq.Header.Add(k, vv)
		}
	}

	// Add x-request-meta header only if it exists
	if xRequestMeta, ok := headerResponse["x-request-meta"].(string); ok && xRequestMeta != "" {
		newReq.Header.Set("x-request-meta", xRequestMeta)
	}

	return newReq, nil
}

/**
 * Calls Router Integration Helper Service
 */
func routerIntegrationHelper(route string, rebitRequestBody map[string]interface{}) (map[string]interface{}, error) {
	payload := map[string]interface{}{
		"rebitAPIEndpoint": route,
		"recipientId":      recipientID,
		"customerId":       "9766334467@aa_simulator",
		"requestBody":      rebitRequestBody,
	}

	payloadBytes, _ := json.Marshal(payload)
	req, err := http.NewRequest("POST", routerIntegrationHelperURL, bytes.NewBuffer(payloadBytes))
	if err != nil {
		return nil, err
	}
	req.Header.Set("Content-Type", "application/json")

	resp, err := httpClient.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	var responseMap map[string]interface{}
	if err := json.Unmarshal(respBody, &responseMap); err != nil {
		return nil, err
	}
	return responseMap, nil
}

/**
 * Example: Further operations with the discovery response
 */
func performAnotherOperations(accountDiscoverResponse string) {
	fmt.Println("Next steps with response:", accountDiscoverResponse)
}


```

</details>

<details>

<summary>With Router Integration - Response</summary>

```go
package main

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

const (
	ROUTER_RESPONSE_HEADER_URL = "https://api.sandbox.sahamati.org.in/router-helper/v1/response/header"
	RECIPIENT_ID               = "AA-SIMULATOR"
)

type Account struct {
	FIType          string `json:"FIType"`
	AccType         string `json:"accType"`
	AccRefNumber    string `json:"accRefNumber"`
	MaskedAccNumber string `json:"maskedAccNumber"`
}

type CustomerIdentifier struct {
	Category string `json:"category"`
	Type     string `json:"type"`
	Value    string `json:"value"`
}

type Customer struct {
	ID          string               `json:"id"`
	Identifiers []CustomerIdentifier `json:"Identifiers"`
}

type DiscoverRequest struct {
	Customer Customer `json:"Customer"`
}

func fetchAccountFromRequestBody(requestBody map[string]interface{}) *Account {
	customerObj, ok := requestBody["Customer"].(map[string]interface{})
	if !ok {
		return nil
	}
	identifiersObj, ok := customerObj["Identifiers"].([]interface{})
	if !ok {
		return nil
	}
	for _, idObj := range identifiersObj {
		idMap, ok := idObj.(map[string]interface{})
		if !ok {
			continue
		}
		category, _ := idMap["category"].(string)
		typeVal, _ := idMap["type"].(string)
		value, _ := idMap["value"].(string)
		if category == "STRONG" && typeVal == "AADHAAR" && value != "" {
			return &Account{
				FIType:          "DEPOSIT",
				AccType:         "SAVINGS",
				AccRefNumber:    "BANK11111111",
				MaskedAccNumber: "XXXXXXX3468",
			}
		}
	}
	return nil
}

func routerIntegrationHelper(requestBody map[string]interface{}) (map[string]interface{}, error) {
	jsonData, _ := json.Marshal(requestBody)
	resp, err := http.Post(ROUTER_RESPONSE_HEADER_URL, "application/json", bytes.NewBuffer(jsonData))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)
	var result map[string]interface{}
	json.Unmarshal(body, &result)
	return result, nil
}

func handleAccountDiscovery(w http.ResponseWriter, r *http.Request) {
	var incomingRequestBody map[string]interface{}
	if err := json.NewDecoder(r.Body).Decode(&incomingRequestBody); err != nil {
		w.WriteHeader(http.StatusBadRequest)
		w.Write([]byte(`{"error":"Invalid request"}`))
		return
	}
	discoveredAccount := fetchAccountFromRequestBody(incomingRequestBody)
	if discoveredAccount == nil {
		w.WriteHeader(http.StatusNotFound)
		w.Write([]byte(`{"error":"Account not found"}`))
		return
	}
	responseBody := map[string]interface{}{
		"ver":                "2.0.0",
		"timestamp":          time.Now().Format(time.RFC3339),
		"txnid":              "f35761ac-4a18-11e8-96ff-0277a9fbfedcs",
		"DiscoveredAccounts": []Account{*discoveredAccount},
	}
	responseHeaderRequestBody := map[string]interface{}{
		"rebitAPIEndpoint":     "/accounts/discover",
		"customerId":           "9977336577@aa_simulator",
		"recipientId":          RECIPIENT_ID,
		"additionalAttributes": map[string]interface{}{},
		"responseBody":         responseBody,
	}
	responseHeaderResp, err := routerIntegrationHelper(responseHeaderRequestBody)
	if err == nil {
		if xResponseMeta, ok := responseHeaderResp["x-response-meta"].(string); ok && xResponseMeta != "" {
			w.Header().Set("x-response-meta", xResponseMeta)
		}
	}
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(responseBody)
}

func main() {
	http.HandleFunc("/accounts/discover", handleAccountDiscovery)
	log.Println("Server running on :8080")
	log.Fatal(http.ListenAndServe(":8080", nil))
}


```

</details>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://developer.sahamati.org.in/sahamatinet-mvp/integration-steps/integration-with-router/sample-code-snippets/golang.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
