Skip to main content

Gapura Hosted Checkout

Document Version 1.2.1


Gapura Hosted Checkout is a payment page hosted by DANA that can receive payment from your customers. This service returns a checkout page URL which you can integrate into your payment flow. DANA will then create and process the transaction and notify you when its completed.

Before you start

You will need to register your business in our Merchant Portal to obtain your testing credentials. After you have created your test account, make sure you have done the following:

  • Finish your company registration and select Gapura Hosted Checkout as your payment solution.
  • Setup your webhooks & redirect URLs to receive payment outcomes & redirect user after payment.
  • Obtain your testing credentials from the merchant portal.

User Experience

User experience 1

Fully Hosted by DANA
Simply redirect customers to a DANA hosted cashier page.

User experience 2

Many Payment Methods
Customer can pay using most Indonesian payment methods.

User experience 3

Instant Payment Result
Merchants & customers instantly receive payment result.


Process Flow

The general flow of payment using the Gapura payment gateway is as follows:

Gapura Hosted Checkout Mobile
  1. The user browses the merchant's website or app and proceeds to checkout after selecting a product.
  2. The merchant system generates an order internally, preparing it for payment processing.
  3. The merchant's backend sends a request to DANA’s Create Order API, passing the necessary order details.
  4. Upon receiving the request, DANA processes and stores the order details in its system.
  5. After successfully creating the order, DANA responds with a webRedirectUrl for the checkout page.
  6. The merchant uses the returned URL to prepare a redirection to DANA’s hosted checkout page.
  7. The user is redirected to the DANA-hosted checkout page where the payment can be made.
  8. Available payment methods are displayed.
  9. The user chooses one of the supported payment methods provided by DANA and follows the instructions on the DANA checkout page to complete the payment.
  10. DANA Hosted Checkout page receives the payment details and sends it to DANA API.
  11. DANA processes the payment.
  12. DANA shows payment result screen to user.
  13. DANA sends a payment notification to the merchant’s system via the Finish Notify API, updating the payment status of the order.
  14. DANA redirects to the merchant URL that already set when hitting Create Order API.

Step 1 : Library Installation

Visit our Libraries & Plugins guide for detailed information on our SDK.

DANA provides server-side API libraries for several programming languages, available through common package managers, for easier installation and version management. Follow the guide below to install our library:

Requirements

Installation

Install using npm or visit our Github

Install the API Library using npm
npm install dana-node@latest --save

Set up the env

Required Credentials
PRIVATE_KEY or PRIVATE_KEY_PATH        # Your private key 
ORIGIN # Your application's origin URL
X_PARTNER_ID # clientId provided during onboarding
ENV # DANA's environment either 'sandbox' or 'production'

Obtaining merchant credentials: Authentication


Step 2 : Initialize the library

Visit our Authentication guide to learn about the authentication process when not using our Library.

Follow the guide below to initialize the library

Initialize the library
import { Dana, PaymentGatewayApi as PaymentGatewayApiClient } from 'dana-node';

const danaClient = new Dana({
partnerId: "YOUR_PARTNER_ID", // process.env.X_PARTNER_ID
privateKey: "YOUR_PRIVATE_KEY", // process.env.X_PRIVATE_KEY
origin: "YOUR_ORIGIN", // process.env.ORIGIN
env: "sandbox", // process.env.ENV or "sandbox" or "production"
});
const { PaymentGatewayApi } = danaClient;

Step 3 : Use the Create Order API to get a hosted checkout URL

Use the Create Order API to create new payment requests which will then return the Checkout URL of the hosted payment page.

To create a new order, make a POST request to the Create Order API:

Calling Create Order API
import { Dana } from 'dana-node';

// .. initialize client with authentication

const request: CreateOrderRequest = {
// Fill in required fields here, refer to Create Order API Detail
};

const response: CreateOrderResponse = await PaymentGatewayApi.createOrder(request);

When sending the request parameters, set additionalInfo.order.scenario to REDIRECT.

If successful, the response will include the URL for the hosted payment page. For example:

Sample response from Create Order API
Content-Type: application/json
X-TIMESTAMP: 2024-12-23T09:10:11+07:00
{
"responseCode": "2005400", // Refer to response code list
"responseMessage": "Successful", // Refer to response code list
"referenceNo": "2020102977770000000009", // Transaction identifier on DANA system
"partnerReferenceNo": "2020102900000000000001", // Transaction identifier on partner system
"webRedirectUrl": "https://pjsp.com/universal?bizNo=REF993883&..."
...
}

Redirect the merchant to the webRedirectUrl in the response. The merchant will proceed to the hosted checkout page, and will be directed to do payment on the order.

If you want to simulate payments in the sandbox environment. Contact our Merchant Services team to access our sandbox simulation tools.


Optional Query Order Status, Cancel Order, and Refund Order

There are additional APIs available to enhance your integration process:

  1. Query Payment API - Use this API to inquire the latest status of a payment request.
  2. Sample Query Payment API
    import { Dana } from 'dana-node';

    //initiate danaClient with authentication

    const request: QueryPaymentRequest = {
    // Fill in required fields here, refer to Query Payment API Detail
    };

    const response: QueryPaymentResponse = await PaymentGatewayApi.queryPayment(request);
  3. Cancel Order API - Cancel unpaid orders or paid orders within 24 hours. Cancellation can be initiated by users through the merchant platform or directly through DANA (for DANA Balance payments).
  4. Sample Cancel Order API
    import { Dana } from 'dana-node';

    //initiate danaClient with authentication

    const request: CancelOrderRequest = {
    // Fill in required fields here, refer to Cancel Order API Detail
    };

    const response: CancelOrderResponse = await PaymentGatewayApi.cancelOrder(request);
  5. Refund Order API - Process refunds for completed orders. You can trigger a refund request on behalf of the customer using this API, who will then process the refund through DANA.
  6. Sample Refund Order API
    import { Dana } from 'dana-node';

    //initiate danaClient with authentication

    const request: RefundOrderRequest = {
    // Fill in required fields here, refer to Refund Order API Detail
    };

    const response: RefundOrderResponse = await PaymentGatewayApi.refundOrder(request);

Step 4 : Receive Payment Outcome via Finish Notify API

After a successful payment:

  1. The user will be redirected to your specified Redirect URL, which you can configure using the urlParams parameter in the Create Order API API request.
  2. DANA will send payment notifications to your Notification URL via the Finish Notify API. Configure your notification endpoint with the ASPI-mandated path format: /v1.0/debit/notify.

Construction

Construction
new WebhookParser(publicKey?: string, publicKeyPath?: string)

Request

ParameterTypeRemarks
publicKeystringThe DANA gateway's public key as a PEM formatted string. This is used if publicKeyPath is not provided or is empty
publicKeyPathstringThe file path to the DANA gateway's public key PEM file. If provided, this will be prioritized over the publicKey string

Notes: One of publicKey or publicKeyPath must be provided.

Method

Method
parseWebhook(httpMethod: string, relativePathUrl: string, headers: { [key: string]: string }, body: string): FinishNotifyRequest

Request

ParameterTypeRemarks
httpMethodstringThe HTTP method of the incoming webhook request e.g., POST
relative_path_urlstringThe relative URL path of the webhook endpoint that received the notification e.g /v1.0/debit/notify
headersmap[string]stringA map containing the HTTP request headers. This map must include X-SIGNATURE and X-TIMESTAMP headers provided by DANA for signature verification
bodystringThe raw JSON string payload from the webhook request body
  • Returns: A pointer to a FinishNotifyRequeststruct containing the parsed and verified webhook data, or an error if parsing or signature verification fails.
  • Raises: ValueError if signature verification fails or the payload is invalid.

Security Notes

  • Always use the official public key provided by DANA for webhook verification.
  • Reject any webhook requests that fail signature verification or have malformed payloads.
  • Never trust webhook data unless it passes verification.
Webhook Finish Notify
import { WebhookParser } from 'dana-node/dist/webhook'; // Adjust import path as needed

async function handleDanaWebhook(req: AnyRequestType, res: AnyResponseType) {
// Retrieve the DANA public key from environment variables or a secure configuration.
// Option 1: Public key as a string
const danaPublicKeyString: string | undefined = process.env.DANA_WEBHOOK_PUBLIC_KEY_STRING;
// Option 2: Path to the public key file (recommended for production)
const danaPublicKeyPath: string | undefined = process.env.DANA_WEBHOOK_PUBLIC_KEY_PATH;

if (!danaPublicKeyString && !danaPublicKeyPath) {
console.error('DANA webhook public key not configured.');
res.status(500).send('Webhook processor configuration error.'); // Or appropriate error handling
return;
}

const httpMethod: string = req.method!; // e.g., "POST"
const relativePathUrl: string = req.path!; // e.g., "/v1.0/debit/notify". Ensure this is the path DANA signs.

const headers: Record<string, string> = req.headers as Record<string, string>;

let requestBodyString: string;
if (typeof req.body === 'string') {
requestBodyString = req.body;
} else if (req.body && typeof req.body === 'object') {
requestBodyString = JSON.stringify(req.body);
} else {
console.error('Request body is not a string or a parseable object.');
res.status(400).send('Invalid request body format.');
return;
}

// Initialize WebhookParser.
const parser = new WebhookParser(danaPublicKeyString, danaPublicKeyPath);

try {
// Verify the signature and parse the webhook payload
const finishNotify = parser.parseWebhook(
httpMethod,
relativePathUrl,
headers,
requestBodyString
);

console.log('Webhook verified successfully:');
console.log('Original Partner Reference No:', finishNotify.originalPartnerReferenceNo);
// TODO: Process the finishNotify object (e.g., update order status in your database)

res.status(200).send('Webhook received and verified.');
} catch (error: any) { // Catching as 'any' to access error.message
console.error('Webhook verification failed:', error.message);
// Respond with an error status. DANA might retry if it receives an error.
res.status(400).send(`Webhook verification failed: ${error.message}`);
}
}

For detailed example, please refer to the following resource: Example Webhook.

Example of a successful payment webhook payload:

Example of a successful Finish Notify:
Content-Type: application/json
X-TIMESTAMP: 2024-12-23T09:10:11+07:00
{
"responseCode": "2005400", // Refer to response code list
"responseMessage": "Successful", // Refer to response code list
"referenceNo": "2020102977770000000009", // Transaction identifier on DANA system
"partnerReferenceNo": "2020102900000000000001", // Transaction identifier on partner system
"webRedirectUrl": "https://pjsp.com/universal?bizNo=REF993883&..."
...
}

Additional Enum Configuration

The library provides several enums (enumerations) to represent a fixed set of constant values, ensuring consistency and reducing errors during integration.

Example Usage
import { EnvInfoSourcePlatformEnum } from 'dana-node/dist/payment_gateway/v1';

const ipg = EnvInfoSourcePlatformEnum.Ipg;

The following enums are available in the Library Payment Gateway:

  1. AcquirementStatusEnum
  2. ActorTypeEnum
  3. OrderTerminalTypeEnum
  4. PayMethodEnum
  5. PayOptionEnum
  6. ScenarioEnum
  7. SourcePlatformEnum
  8. TerminalTypeEnum
  9. TypeEnum

Step 5 : Automated UAT Testing Suite

To verify your integration, run our automated test suite. It takes under 2 minutes to tests your integration with mandated test scenarios. Check out the Github repo for more instructions


Step 6 : Apply for Live Payment

As part of regulatory compliance, merchants are required to submit UAT testing documents to meet Bank Indonesia's requirements. After completing sandbox testing, follow these steps to move to production:

  1. Generate production keys
    Create your production private and public keys, follow this instruction: Authentication - Production Credential.

  2. Confirm UAT testing logs
    Confirm that you have completed all testing scenarios from our Merchant Portal.

  3. Fill go-live submission form
    Follow the instructions inside our Merchant Portal to apply for production credentials. We will process your application in 1-2 days.

  4. Obtain production credentials
    Once approved, you will receive your production credentials such as: Merchant ID, Client ID known as X-PARTNER-ID, and Client Secret.


Testing in production environment

  1. Configure production environment
    Switch your application settings from sandbox to production environment by updating the API endpoints and credentials.

  2. Test using production credentials
    Conduct the same testing scenarios as sandbox testing, using your production credentials.

  3. UAT production sign-off
    Once testing is complete, DANA will prepare the UAT Production Sign Off document in the Merchant Portal. Both merchant and DANA representatives must sign this document to formally approve the integration.

  4. Go-live
    After receiving all approvals, your DANA integration will be activated and ready for live payments from your customers.


Ready to submit testing documents?
Access our merchant portal for detailed guide to start receiving live payments

Version 1.2.1 - May 08, 2025
Changes
  • Added additional information section for all APIs
Version 1.2.0 - January 22, 2025
Affected APIs
Changes
  • Updated Service Code
  • Updated URL
  • Updated Idempotent Key and Rules
  • Updated Condition webRedirectUrl on Response section
  • Updated Request and Response Sample
  • Updated Response Code
Version 1.1.3 - November 22, 2024
Affected APIs
Changes
  • Updated value of ``REDIRECTION`` become ``REDIRECT`` on ScenarioEnum
  • Updated remarks additionalInfo.order.scenario on Create Order API
  • Updated Request Sample on Create Order API
Version 1.1.2 - October 07, 2024
Changes
  • Updated all words of “Plugin” become “Drop-in”
Version 1.1.1 - September 09, 2024
Changes
  • Updated Environment URL for Sandbox on Specification section for all APIs
  • Updated Request Sample on URL Section for all APIs
Version 1.1.0 - August 15, 2024
Changes
  • Updated API name from ‘Payment Redirect’ to ‘Create Order’
  • Added Environment URL on Specification section for all APIs.
  • Added new programming language (Go, Java, JavaScript, Python, Ruby) on Request Sample for all APIs.
Version 1.0.0 - March 27, 2024
  • Initial Version