GoLang
Without Router - Current Approach
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)
}
}
With Router Integration - Request
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
}
targetHost, ok := headerResponse["targetHost"].(string)
if !ok || targetHost == "" {
return nil, fmt.Errorf("Router Helper response missing required field 'targetHost'")
}
// Build new URL
newURL := targetHost + 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)
}
With Router Integration - Response
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))
}
Last updated
Was this helpful?