# 🔐 Signature Generation (bodysign)

To ensure secure communication between your application and Redision Payment Gateway, every request must include a `bodysign` header. This value is a **HMAC-SHA256 hash** of the JSON request body using your `appsecret`, then encoded in **Base64 URL-safe** format.

***

### 🧾 How to Generate bodysign

#### Step-by-step:

1. Serialize your request body as a raw JSON string.
2. Generate HMAC using SHA-256 with your appsecret as key.
3. Encode the result to Base64.
4. Replace `+` with `-` and `/` with `_` to make it URL-safe.

***

### Example in PHP

```php

 <?php
function generateBodySign(array $payload, string $appSecret): string {
    $payloadJson = json_encode($payload, JSON_UNESCAPED_SLASHES);

    // HMAC-SHA256 binary
    $hash = hash_hmac('sha256', $payloadJson, $appSecret, true);

    // Base64 + URL safe (tidak hilangkan '=')
    $bodysign = base64_encode($hash);
    $bodysign = str_replace(['+', '/'], ['-', '_'], $bodysign);

    return $bodysign;
}

// Contoh penggunaan
$payload = [
    "redirect_url" => "https://redirect-url.com,
    "user_id" => "USER123",
    "user_mdn" => "085712345678",
    "merchant_transaction_id" => "INV123456",
    "payment_method" => "qris",
    "currency" => "IDR",
    "amount" => 10000,
    "item_name" => "name",
    "customer_name" => "customer name",
    "notification_url" => "https://example.com/callback"
];

$appSecret = "your_secret";
echo "Bodysign: " . generateBodySign($payload, $appSecret);

```

### Example in Golang

```go
import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/base64"
	"encoding/json"
	"log"
	"strings"
)

func GenerateBodySign(payload interface{}, appSecret string) string {
	payloadJSON, err := json.Marshal(payload)
	if err != nil {
		log.Println("Error encoding JSON:", err)
		return ""
	}

	h := hmac.New(sha256.New, []byte(appSecret))
	h.Write(payloadJSON)
	hash := h.Sum(nil)

	bodysign := base64.StdEncoding.EncodeToString(hash)
	bodysign = strings.NewReplacer("+", "-", "/", "_").Replace(bodysign)

	return bodysign
}
```

### Example in Node.js

```js
import crypto from "crypto";

function generateBodySign(payload, appSecret) {
  // JSON tanpa escape slash
  const payloadJson = JSON.stringify(payload).replace(/\\\//g, "/");

  // HMAC-SHA256 (binary output)
  const hash = crypto
    .createHmac("sha256", appSecret)
    .update(payloadJson)
    .digest();

  // Base64 + URL safe (tidak hilangkan '=')
  let bodysign = hash.toString("base64");
  bodysign = bodysign.replace(/\+/g, "-").replace(/\//g, "_");

  return bodysign;
}

// Contoh penggunaan
const payload = {
  redirect_url: "https://merchant.com/return",
  user_id: "20250209TEST3477000000",
  user_mdn: "08123412451",
  merchant_transaction_id: "TESTSH0000011",
  payment_method: "indosat_airtime",
  currency: "IDR",
  amount: 5000,
  item_id: "1",
  item_name: "PAYMENT",
  notification_url: "https://merchant/callback-payment"
};

const appSecret = "your_secret_key";
console.log("Bodysign:", generateBodySign(payload, appSecret));

```

### Example in Java

```java
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.LinkedHashMap;
import java.util.Map;
import java.nio.charset.StandardCharsets;

public class BodySignUtil {

    public static String generateBodySign(Map<String, Object> payload, String appSecret) {
        try {
            String payloadJson = mapToJson(payload);

            // Generate HMAC-SHA256
            Mac mac = Mac.getInstance("HmacSHA256");
            SecretKeySpec secretKeySpec = new SecretKeySpec(appSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
            mac.init(secretKeySpec);
            byte[] hash = mac.doFinal(payloadJson.getBytes(StandardCharsets.UTF_8));

            // Base64 encode + URL safe (tidak hilangkan '=')
            String bodysign = Base64.getEncoder().encodeToString(hash);
            bodysign = bodysign.replace('+', '-').replace('/', '_');

            return bodysign;
        } catch (Exception e) {
            throw new RuntimeException("Error generating bodysign", e);
        }
    }

    private static String mapToJson(Map<String, Object> map) {
        StringBuilder json = new StringBuilder("{");
        boolean first = true;
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            if (!first) json.append(",");
            json.append("\"").append(entry.getKey()).append("\":");

            if (entry.getValue() instanceof String) {
                json.append("\"").append(entry.getValue()).append("\"");
            } else {
                json.append(entry.getValue());
            }
            first = false;
        }
        json.append("}");
        return json.toString();
    }

    public static void main(String[] args) {
        Map<String, Object> payload = new LinkedHashMap<>();
        payload.put("redirect_url", "https://redirect_url");
        payload.put("user_id", "12345678");
        payload.put("merchant_transaction_id", "TX123");
        payload.put("payment_method", "qris");
        payload.put("currency", "IDR");
        payload.put("amount", 10000);
        payload.put("item_name", "TestOrder");
        payload.put("customer_name", "John Doe");
        payload.put("notification_url", "https://example.com/webhook");

        String appSecret = "your_secret";
        String bodysign = generateBodySign(payload, appSecret);

        System.out.println("Bodysign: " + bodysign);
    }
}

```


---

# 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://redpay.gitbook.io/redpay-docs/api-information/signature-generation-bodysign.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.
