Callback Payment

POST

Payara will automatically send payment notifications to your configured callback URL when transaction events occur. This provides real-time updates about transaction status changes.

Callback Request Format

When a payment event occurs, Payara will send an HTTP POST request to your configured callback URL with the following JSON format:

{
    "event": "TOPUP_SUCCESS",
    "request_id": "03fa4371-a5b6-491d-b5d2-3a21d756b6a9",
    "transaction_uuid": "topupb349-e50c-4f65-e72b-b0d49c78",
    "amount": 20000,
    "created_at": "2026-02-10T09:03:10.944370Z"
}

Request Headers

Header Value Description
Content-Type application/json Request content type
User-Agent Payara-Webhook/1.0 Identifies the webhook source

Callback Parameters

Parameter Type Description
event string Type of payment event that occurred
request_id string The request_id is a unique number generated from the request process
transaction_uuid string Unique identifier for the transaction
amount integer Transaction amount (in IDR)
created_at string ISO 8601 timestamp when the event was created

Event Types

Event Type Description
TOPUP_SUCCESS Top-up transaction completed successfully
TOPUP_FAILED Top-up transaction failed

Expected Response

Your callback endpoint must respond with HTTP status code 200 to acknowledge receipt. If Payara does not receive a successful response, it will automatically retry the callback.

Expected Response Format:

{
    "success": true,
    "message": "Callback received"
}

Retry Mechanism

If your callback endpoint fails to respond or returns an error, Payara will retry sending the callback:

  • Retry Attempts: Up to 5 times
  • Retry Intervals: 1 minute, 5 minutes, 15 minutes, 30 minutes, 1 hour
  • Timeout: Each request has a 30-second timeout

Security Best Practices

1. Validate Webhook Payload

Always validate that the webhook payload contains all required fields before processing:

if (!isset($payload['event']) || !isset($payload['transaction_uuid'])) {
    // Reject invalid payload
}

2. Implement Idempotency

Store processed transaction UUIDs to prevent duplicate processing:

if (isTransactionProcessed($payload['transaction_uuid'])) {
    // Already processed, return success without reprocessing
    return ['success' => true, 'message' => 'Already processed'];
}

3. Use HTTPS

Always configure your callback URL with HTTPS to ensure secure communication.

4. Verify Source (Optional)

If Payara provides IP whitelisting, verify that webhook requests come from authorized IP addresses.

5. Implement Logging

Log all webhook requests for debugging and audit purposes:

error_log("Webhook: " . json_encode($payload));

Testing Your Webhook

{info} Make sure to test your webhook endpoint in the Sandbox environment before moving to Production.

Testing Checklist

  • [ ] Webhook URL is publicly accessible via HTTPS
  • [ ] Endpoint returns HTTP 200 for valid requests
  • [ ] All event types are handled correctly
  • [ ] Duplicate webhooks are handled (idempotency)
  • [ ] Error responses are logged properly
  • [ ] Response time is under 30 seconds

Testing Tools

You can test your webhook endpoint using tools like:

  • Postman: Send test POST requests with sample payloads
  • cURL: Quick command-line testing
  • Webhook.site: Test and inspect webhook requests

cURL Test Example

curl -X POST https://your-domain.com/webhook/payment \
  -H "Content-Type: application/json" \
  -d '{
    "event": "TOPUP_SUCCESS",
    "request_id": "03fa4371-a5b6-491d-b5d2-3a21d756b6a9"
    "transaction_uuid": "topupb349-e50c-4f65-e72b-b0d49c78",
    "amount": 20000,
    "created_at": "2026-02-10T09:03:10.944370Z"
  }'

Common Issues

Issue 1: Webhook Not Received

Possible Causes:

  • Callback URL not configured in dashboard
  • Server not accessible from internet
  • Firewall blocking incoming requests
  • SSL certificate issues

Solutions:

  • Verify callback URL in merchant dashboard
  • Test URL accessibility with external tools
  • Check firewall and security group settings
  • Ensure valid SSL certificate

Issue 2: Webhook Timing Out

Possible Causes:

  • Processing taking too long (> 30 seconds)
  • Database queries are slow
  • External API calls blocking

Solutions:

  • Return 200 response immediately
  • Process webhook asynchronously
  • Optimize database queries
  • Use queue system for heavy processing

Issue 3: Duplicate Processing

Possible Causes:

  • Not implementing idempotency checks
  • Multiple retry attempts being processed

Solutions:

  • Check transaction_uuid before processing
  • Use database constraints to prevent duplicates
  • Return success for already-processed webhooks

Issue 4: Failed Webhooks

Possible Causes:

  • Server errors in webhook handler
  • Database connection issues
  • Not returning HTTP 200 status

Solutions:

  • Implement proper error handling
  • Add try-catch blocks
  • Always return 200 for successful receipt
  • Use logging to debug issues