Api References

List Stores

Retrieve store information to obtain storeId for payment operations.

Endpoint

POST https://merchant.dv.vai247.pro/api/v1/payment-gateway/stores/list

Authentication

This endpoint uses standard authentication and requires only the X-Api-Key header.

Required Header:

  • X-Api-Key: Your API key

See Authentication for more details.

Description

The List Stores endpoint retrieves all stores associated with your merchant account. The storeId returned by this endpoint is required for:

  1. Creating payment orders - The storeId must be provided when calling the Create Order endpoint
  2. Generating KHQR codes - The storeId is required when calling the Generate QR endpoint

This endpoint should typically be called before initiating any payment operations to ensure you have the correct store identifiers.

Best Practice: Call this endpoint once during your application initialization and cache the store list locally. Only refresh when needed (e.g., when adding new stores or on application restart).

Request Parameters

This endpoint does not require any request body parameters. Authentication is handled via the X-Api-Key header.

Code Examples

package main

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

type Store struct {
    StoreID   int64  `json:"storeId"`
    StoreName string `json:"storeName"`
    Address   string `json:"address"`
}

type StoresResponse struct {
    StatusCode int     `json:"statusCode"`
    Message    string  `json:"message"`
    Data       []Store `json:"data"`
    TraceID    string  `json:"traceId"`
}

func listStores(apiKey string) (*StoresResponse, error) {
    url := "https://merchant.dv.vai247.pro/api/v1/payment-gateway/stores/list"

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

    // Add authentication header
    req.Header.Set("X-Api-Key", apiKey)
    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 StoresResponse
    if err := json.Unmarshal(body, &result); err != nil {
        return nil, err
    }

    return &result, nil
}

func main() {
    stores, err := listStores("your-api-key")
    if err != nil {
        fmt.Printf("Error: %v\n", err)
        return
    }

    fmt.Printf("Found %d store(s):\n", len(stores.Data))
    for _, store := range stores.Data {
        fmt.Printf("\nStore ID: %d\n", store.StoreID)
        fmt.Printf("Name: %s\n", store.StoreName)
        fmt.Printf("Address: %s\n", store.Address)
    }
}

Response

Success Response (200)

{
  "statusCode": 200,
  "message": "Success",
  "data": [
    {
      "storeId": 1234567890,
      "storeName": "Main Store - Downtown",
      "address": "123 Main Street, Phnom Penh, Cambodia"
    },
    {
      "storeId": 1234567891,
      "storeName": "Branch Store - Airport",
      "address": "456 Airport Road, Phnom Penh, Cambodia"
    }
  ],
  "traceId": "trace_abc123"
}

Response Fields

FieldTypeDescription
statusCodenumberHTTP status code (200 for success)
messagestringResponse message
dataarrayArray of store objects
data[].storeIdnumberUnique store identifier (use this for Create Order and Generate QR)
data[].storeNamestringDisplay name of the store
data[].addressstringPhysical address of the store
traceIdstringRequest trace identifier for debugging

Error Responses

400 Bad Request

Missing required headers or invalid request format.

{
  "statusCode": 400,
  "message": "Bad Request - missing required headers or invalid request body",
  "error": "Bad Request"
}

401 Unauthorized

Invalid API credentials provided.

{
  "statusCode": 401,
  "message": "Unauthorized - invalid API credentials",
  "error": "Unauthorized"
}

404 Not Found

No stores found for the merchant account.

{
  "statusCode": 404,
  "message": "Not Found - store not found",
  "error": "Not Found"
}

500 Internal Server Error

Server-side error occurred while processing the request.

{
  "statusCode": 500,
  "message": "Internal Server Error",
  "error": "Internal Server Error"
}

Use Cases

1. Before Creating Orders

Retrieve store information before creating payment orders:

// Step 1: Get available stores
const stores = await listStores('your-api-key');
const storeId = stores.data[0].storeId;

// Step 2: Use storeId to create an order
const order = await createOrder(storeId, 100.00, 'USD');

2. Before Generating KHQR Codes

Obtain the storeId required for KHQR generation:

// Step 1: Get store information
const stores = await listStores('your-api-key');
const storeId = stores.data[0].storeId;

// Step 2: Generate KHQR code with storeId
const qr = await generateQRCode(storeId, 50.00, 'USD');

3. Multi-Store Management

For merchants with multiple stores, implement store selection:

const stores = await listStores('your-api-key');

// Let user select their store
stores.data.forEach((store, index) => {
  console.log(`${index + 1}. ${store.storeName} - ${store.address}`);
});

// Use selected storeId for payment operations
const selectedStoreId = stores.data[selectedIndex].storeId;

4. Store Display in POS Systems

Display store information in your point-of-sale system:

const stores = await listStores('your-api-key');

// Show current store information
const currentStore = stores.data.find(s => s.storeId === currentStoreId);
console.log(`Active Store: ${currentStore.storeName}`);
console.log(`Location: ${currentStore.address}`);

Integration Workflow

Here's a typical integration workflow using the List Stores endpoint:

sequenceDiagram
    participant App as Your Application
    participant API as DVPay API
    participant Cache as Local Cache

    App->>API: POST /stores/list
    API-->>App: Return stores array
    App->>Cache: Store storeId locally

    Note over App,Cache: Store selection
    App->>Cache: Get cached storeId

    Note over App,API: Payment operations
    App->>API: POST /order/create (with storeId)
    API-->>App: Return order with QR code

    App->>API: POST /payment/generate-qr (with storeId)
    API-->>App: Return KHQR code

Best Practices

1. Cache Store Information

Cache the store list to minimize API calls and improve performance:

let storeCache = null;
let cacheTimestamp = null;
const CACHE_DURATION = 3600000; // 1 hour in milliseconds

async function getStores(apiKey, forceRefresh = false) {
  const now = Date.now();

  if (!forceRefresh && storeCache && (now - cacheTimestamp < CACHE_DURATION)) {
    return storeCache;
  }

  const stores = await listStores(apiKey);
  storeCache = stores;
  cacheTimestamp = now;

  return stores;
}

2. Handle Empty Store Lists

Always check if stores exist before proceeding:

const stores = await listStores('your-api-key');

if (!stores.data || stores.data.length === 0) {
  throw new Error('No stores available. Please configure stores in DVPay mobile app.');
}

3. Store Selection for Multi-Store Merchants

Implement proper store selection logic:

async function selectStore(apiKey, criteria) {
  const stores = await listStores(apiKey);

  // Select by name
  if (criteria.name) {
    return stores.data.find(s =>
      s.storeName.toLowerCase().includes(criteria.name.toLowerCase())
    );
  }

  // Select by ID
  if (criteria.id) {
    return stores.data.find(s => s.storeId === criteria.id);
  }

  // Default to first store
  return stores.data[0];
}

4. Validate StoreId Before Payment Operations

Ensure the storeId exists before using it:

async function validateStoreId(apiKey, storeId) {
  const stores = await listStores(apiKey);
  const storeExists = stores.data.some(s => s.storeId === storeId);

  if (!storeExists) {
    throw new Error(`Invalid storeId: ${storeId}`);
  }

  return true;
}

5. Refresh Cache When Stores Change

Implement cache invalidation when stores are modified:

// After adding a new store via DVPay mobile app
async function refreshStores(apiKey) {
  return await getStores(apiKey, true); // Force refresh
}
Important: The storeId must be valid and belong to your merchant account. Using an invalid or unauthorized storeId will result in a 404 error when creating orders or generating QR codes.

Troubleshooting

No Stores Returned (404)

If you receive a 404 error or empty store list:

  1. Verify that you have created at least one store in the DVPay mobile application
  2. Navigate to: DVPay Mobile App → Settings → Stores → Add Store
  3. Wait a few minutes for the store to be activated
  4. Retry the API call

Unauthorized Error (401)

  • Verify your API key is correct and active
  • Check that you're using the correct API key header: X-Api-Key
  • Ensure your API key has not expired or been revoked

Store Information Outdated

If cached store information becomes stale:

  1. Implement a cache refresh mechanism
  2. Force a refresh after store modifications in the mobile app
  3. Consider adding a manual refresh option in your application

Security Notes

  • Store IDs are not sensitive but should be validated before use
  • Never expose API keys in client-side code when fetching store lists
  • Implement rate limiting if polling this endpoint frequently
  • Use secure storage for cached store information
Store Management: Stores are managed through the DVPay mobile application. To add, edit, or remove stores, use the mobile app's store management interface. Changes will be reflected immediately in the API response.