Api References

Payout

Processes a payout to a specified account.

Endpoint

POST https://merchant.dv.vai247.pro/api/v1/payment-gateway/order/payout

Required Headers

HeaderTypeRequiredDescription
X-Api-KeystringYesYour API key
X-TimestampstringYesUnix timestamp in seconds
X-SignaturestringYesHMAC-SHA256 signature (see below)
X-Idempotent-KeystringYesUnique key to prevent duplicate payouts (UUID recommended)

Important:

  • The X-Signature header requires HMAC-SHA256 signature generation using your API secret
  • The X-Idempotent-Key header is required to prevent accidental duplicate payouts
  • Use a unique identifier (UUID) for each payout operation

Generating the Signature

The X-Signature header must contain an HMAC-SHA256 signature of your request:

Formula:

message = rawPayload + timestamp
signature = HMAC-SHA256(message, api_secret)

Where:

  • rawPayload = JSON request body as a string (e.g., {"accountNumber":"123456789","amount":100,"currency":"USD"})
  • timestamp = Unix timestamp in seconds (same value as X-Timestamp header)
  • api_secret = Your API secret from DVPay mobile app
Getting Your API Secret: DVPay mobile app → Settings → API Configuration → Show API Secret

Request Parameters

ParameterTypeRequiredDescription
accountNumberstringYesRecipient account number
amountnumberYesPayout amount
currencystringYesCurrency code (USD, KHR)

Code Examples

package main

import (
    "bytes"
    "crypto/hmac"
    "crypto/sha256"
    "encoding/hex"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "strconv"
    "time"
    "github.com/google/uuid"
)

type PayoutRequest struct {
    AccountNumber string  `json:"accountNumber"`
    Amount        float64 `json:"amount"`
    Currency      string  `json:"currency"`
}

type PayoutResponse struct {
    AccountName     string  `json:"accountName"`
    AccountNumber   string  `json:"accountNumber"`
    Amount          float64 `json:"amount"`
    Currency        string  `json:"currency"`
    OrderID         int64   `json:"orderId"`
    Remark          string  `json:"remark"`
    TransactionDate string  `json:"transactionDate"`
    TransactionID   int64   `json:"transactionId"`
}

func generateSignature(secret, timestamp, rawPayload string) string {
    // Create message: rawPayload + timestamp
    message := rawPayload + timestamp

    // Create HMAC with SHA256
    h := hmac.New(sha256.New, []byte(secret))
    h.Write([]byte(message))

    // Return hex digest
    return hex.EncodeToString(h.Sum(nil))
}

func processPayout(accountNumber string, amount float64, currency, apiKey, apiSecret string) (*PayoutResponse, error) {
    url := "https://merchant.dv.vai247.pro/api/v1/payment-gateway/order/payout"

    payload := PayoutRequest{
        AccountNumber: accountNumber,
        Amount:        amount,
        Currency:      currency,
    }

    jsonData, err := json.Marshal(payload)
    if err != nil {
        return nil, err
    }
    rawPayload := string(jsonData)

    // Generate timestamp
    timestamp := strconv.FormatInt(time.Now().Unix(), 10)

    // Generate signature
    signature := generateSignature(apiSecret, timestamp, rawPayload)

    // Generate idempotent key
    idempotentKey := uuid.New().String()

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

    // Add authentication headers
    req.Header.Set("X-Api-Key", apiKey)
    req.Header.Set("X-Timestamp", timestamp)
    req.Header.Set("X-Signature", signature)
    req.Header.Set("X-Idempotent-Key", idempotentKey)
    req.Header.Set("Content-Type", "application/json")

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

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

    var result PayoutResponse
    if err := json.Unmarshal(body, &result); err != nil {
        return nil, err
    }

    return &result, nil
}

func main() {
    payout, err := processPayout("123456789", 100.00, "USD", "your-api-key", "your-api-secret")
    if err != nil {
        fmt.Printf("Error: %v\n", err)
        return
    }

    fmt.Printf("Transaction ID: %d\n", payout.TransactionID)
    fmt.Printf("Account: %s (%s)\n", payout.AccountName, payout.AccountNumber)
    fmt.Printf("Amount: %.2f %s\n", payout.Amount, payout.Currency)
}

Response

{
  "statusCode": 200,
  "message": "Success",
  "data": {
    "accountName": "John Doe",
    "accountNumber": "123456789",
    "amount": 100.00,
    "currency": "USD",
    "orderId": 1234567890,
    "remark": "",
    "transactionDate": "2026-03-02T12:00:00Z",
    "transactionId": 9876543210
  },
  "traceId": "trace_abc123"
}

Notes

  • Signature Required: All payout requests must include a valid X-Signature header generated using HMAC-SHA256
  • Idempotency: Each payout request requires a unique X-Idempotent-Key header. If you retry a request with the same key, the API will return the original response without processing a duplicate payout
  • Verify account balance before initiating payouts
  • Payouts typically process within 1-2 business days
  • Failed payouts are automatically reversed
Migration from v1.3.0: The X-App-Id header has been removed. Use signature-based authentication with X-Signature header instead. See v1.4.0 Release Notes for migration guide.