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.
- iOS 17.0 or later
- Xcode 15.2 or later
- Swift 5.0 or later
Add the following line to your Podfile:
pod 'DOKUCheckout'Then run:
pod installimport DOKUCheckoutBuild the CheckoutRequest object containing order details, payment configuration, customer information, and addresses.
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 |
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 |
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") |
let address = Address(
first_name: "John",
last_name: "Doe",
address: "Jl. Example No. 1",
city: "Jakarta",
postal_code: "12345",
phone: "628123456789",
country_code: "ID"
)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"
)
)let request = CheckoutRequest(
order: order,
payment: payment,
customer: customer,
shipping_address: address,
billing_address: address,
additional_info: additionalInfo
)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
)// 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)| 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") |
| Value | Description |
|---|---|
.sandbox |
For testing and development (api-sandbox.doku.com) |
.production |
For live transactions (api.doku.com) |
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)
}
}| 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 |
DOKUCheckout is available under the MIT license. See the LICENSE file for more details.
© 2026 PT. Nusa Satu Inti Artha (DOKU). All rights reserved.