CocoaPods trunk is moving to be read-only. Read more on the blog, there are 3 months to go.

DOKUCheckout 1.0.0

DOKUCheckout 1.0.0

Maintained by DOKU.



  • By
  • PT NUSA SATU INTI ARTHA

DOKUCheckout iOS SDK

DOKU Checkout SDK provides a seamless payment integration for iOS merchant applications, supporting various payment channels including Cards, Virtual Accounts (Bank Transfer), E-Wallet, QRIS, Convenience Stores, and Paylater.

Requirements

  • iOS 17.0 or later
  • Xcode 15.2 or later
  • Swift 5.0 or later

Installation

CocoaPods

Add the following line to your Podfile:

pod 'DOKUCheckout'

Then run:

pod install

Usage

1. Import the SDK

import DOKUCheckout

2. Prepare the Checkout Request

Build the CheckoutRequest object containing order details, payment configuration, customer information, and addresses.

Order

let lineItems = [
    LineItem(
        id: "item_001",
        name: "Product Name",
        quantity: 1,
        price: 100000,
        sku: "SKU001",
        category: "others",
        url: "https://yourstore.com/product",
        image_url: "https://yourstore.com/product-image.png",
        type: "Product"
    )
]

let order = Order(
    amount: 100000,
    invoice_number: "INV-\(Int(Date().timeIntervalSince1970))",
    currency: "IDR",
    callback_url: "https://yourstore.com/callback",
    language: "EN",
    auto_redirect: false,
    disable_retry_payment: false,
    line_items: lineItems
)
Parameter Type Required Description
amount Double Total payment amount
invoice_number String Unique invoice number for the transaction
currency String Currency code (e.g., "IDR")
callback_url String? URL to redirect after payment
language String? Language code ("EN" or "ID")
auto_redirect Bool? Auto redirect after payment
disable_retry_payment Bool? Disable retry on failed payment
line_items [LineItem]? List of purchased items

Payment

let payment = Payment(
    payment_due_date: 60,   // Payment expiry in minutes
    type: "SALE"
)
Parameter Type Required Description
payment_due_date Int Payment expiry duration in minutes
type String? Payment type (e.g., "SALE")
payment_method_types [String]? Filter specific payment methods

Customer

let customer = Customer(
    id: "cust_001",
    name: "John",
    last_name: "Doe",
    phone: "628123456789",
    email: "[email protected]",
    address: "Jl. Example No. 1",
    postcode: "12345",
    state: "IDN",
    city: "Jakarta",
    country: "ID"
)
Parameter Type Required Description
id String Unique customer identifier
name String Customer first name
last_name String? Customer last name
phone String Customer phone number
email String Customer email address
address String? Customer address
postcode String? Postal code
state String? State/Province
city String? City
country String? Country code (e.g., "ID")

Address (Shipping & Billing)

let address = Address(
    first_name: "John",
    last_name: "Doe",
    address: "Jl. Example No. 1",
    city: "Jakarta",
    postal_code: "12345",
    phone: "628123456789",
    country_code: "ID"
)

Additional Info (Optional)

let additionalInfo = AdditionalInfo(
    allow_tenor: [3, 6, 12],
    doku_wallet_notify_url: "https://yourstore.com/wallet-notify",
    override_notification_url: "https://yourstore.com/notification",
    origin: Origin(
        product: "SDK_CHECKOUT_IOS",
        source: "APP",
        system: "sdk-checkout-mobile-ios"
    )
)

Assemble the Checkout Request

let request = CheckoutRequest(
    order: order,
    payment: payment,
    customer: customer,
    shipping_address: address,
    billing_address: address,
    additional_info: additionalInfo
)

3. Generate Signature

Before initializing the SDK, you need to generate a Digest and Signature for request authentication. This should ideally be done on your backend server to protect the secretKey.

⚠️ Security Warning: The example below generates the signature on the client side for demonstration purposes only. In production, always generate the signature on your backend server and pass it to the mobile app.

import CryptoKit

// Generate Digest (SHA-256 hash of the JSON body)
func generateDigest(jsonBody: String) -> String {
    let data = Data(jsonBody.utf8)
    let hash = SHA256.hash(data: data)
    return Data(hash).base64EncodedString()
}

// Generate Signature (HMAC-SHA256)
func generateSignature(
    clientId: String,
    requestId: String,
    requestTimestamp: String,
    requestTarget: String,
    digest: String,
    secretKey: String
) -> String {
    var component = ""
    component += "Client-Id:\(clientId)\n"
    component += "Request-Id:\(requestId)\n"
    component += "Request-Timestamp:\(requestTimestamp)\n"
    component += "Request-Target:\(requestTarget)\n"
    component += "Digest:\(digest)"

    let key = SymmetricKey(data: Data(secretKey.utf8))
    let signature = HMAC<SHA256>.authenticationCode(
        for: Data(component.utf8), using: key
    )
    return "HMACSHA256=" + Data(signature).base64EncodedString()
}

Usage:

let clientId = "YOUR_CLIENT_ID"
let secretKey = "YOUR_SECRET_KEY"
let requestId = UUID().uuidString
let requestTimestamp = ISO8601DateFormatter.string(
    from: Date(), 
    timeZone: TimeZone(secondsFromGMT: 0)!, 
    formatOptions: [.withInternetDateTime, .withColonSeparatorInTimeZone]
)

// Encode request to JSON
let encoder = JSONEncoder()
encoder.outputFormatting = [.sortedKeys]
let jsonData = try! encoder.encode(request)
let jsonBody = String(data: jsonData, encoding: .utf8)!

// Generate digest & signature
let digest = generateDigest(jsonBody: jsonBody)
let signature = generateSignature(
    clientId: clientId,
    requestId: requestId,
    requestTimestamp: requestTimestamp,
    requestTarget: "/checkout/v1/payment",
    digest: digest,
    secretKey: secretKey
)

4. Initialize & Present Checkout

// Configure the SDK
let config = SDKConfig(
    clientId: clientId,
    requestId: requestId,
    requestTimestamp: requestTimestamp,
    signatureKey: signature,
    invoiceNumber: order.invoice_number,
    environment: .sandbox    // Use .production for live transactions
)

// Initialize and present
let sdk = DOKUCheckout(config: config)
sdk.presentCheckout(request: request)

SDKConfig Parameters

Parameter Type Required Description
clientId String Merchant Client ID from DOKU
requestId String Unique request identifier (UUID)
requestTimestamp String ISO 8601 formatted timestamp
signatureKey String HMAC-SHA256 signature
invoiceNumber String Invoice number matching the order
environment Environment .sandbox or .production
colorPallete String? Custom primary color hex (e.g., "#FF5733")

Environment Options

Value Description
.sandbox For testing and development (api-sandbox.doku.com)
.production For live transactions (api.doku.com)

Complete Example

import SwiftUI
import DOKUCheckout
import CryptoKit

struct PaymentView: View {
    var body: some View {
        Button("Pay Now") {
            startPayment()
        }
    }

    func startPayment() {
        let clientId = "YOUR_CLIENT_ID"
        let secretKey = "YOUR_SECRET_KEY"
        let requestId = UUID().uuidString
        let requestTimestamp = ISO8601DateFormatter.dokuFormat()
        let invoiceNumber = "INV-\(Int(Date().timeIntervalSince1970))"

        // 1. Build order
        let order = Order(
            amount: 100000,
            invoice_number: invoiceNumber,
            currency: "IDR"
        )

        // 2. Build payment
        let payment = Payment(payment_due_date: 60, type: "SALE")

        // 3. Build customer
        let customer = Customer(
            id: "cust_001",
            name: "John",
            last_name: "Doe",
            phone: "628123456789",
            email: "[email protected]",
            address: nil, postcode: nil, state: nil, city: nil, country: nil
        )

        // 4. Build address
        let address = Address(
            first_name: "John", last_name: "Doe",
            address: "Jl. Example No. 1", city: "Jakarta",
            postal_code: "12345", phone: "628123456789", country_code: "ID"
        )

        // 5. Build checkout request
        let request = CheckoutRequest(
            order: order,
            payment: payment,
            customer: customer,
            shipping_address: address,
            billing_address: address,
            additional_info: nil
        )

        // 6. Generate signature (⚠️ do this on your backend in production)
        let encoder = JSONEncoder()
        encoder.outputFormatting = [.sortedKeys]
        guard let jsonData = try? encoder.encode(request),
              let jsonBody = String(data: jsonData, encoding: .utf8) else { return }

        let digest = generateDigest(jsonBody: jsonBody)
        let signature = generateSignature(
            clientId: clientId, requestId: requestId,
            requestTimestamp: requestTimestamp,
            requestTarget: "/checkout/v1/payment",
            digest: digest, secretKey: secretKey
        )

        // 7. Initialize SDK & present checkout
        let config = SDKConfig(
            clientId: clientId,
            requestId: requestId,
            requestTimestamp: requestTimestamp,
            signatureKey: signature,
            invoiceNumber: invoiceNumber,
            environment: .sandbox
        )

        let sdk = DOKUCheckout(config: config)
        sdk.presentCheckout(request: request)
    }
}

Supported Payment Channels

Category Payment Channels
Cards Visa, Mastercard, JCB
Virtual Account BCA, BNI, BRI, Mandiri, and more
E-Wallet OVO, DANA, ShopeePay, LinkAja, and more
QRIS QRIS standard supported across e-wallets and banks
Convenience Store Alfamart, Indomaret
Paylater Akulaku, Kredivo, and more

License

DOKUCheckout is available under the MIT license. See the LICENSE file for more details.


© 2026 PT. Nusa Satu Inti Artha (DOKU). All rights reserved.