Skip to content

Payment (DOKU)

Payment adalah DOKU. Backend membuat payment dan memverifikasi callback; storefront membuka widget checkout DOKU.

Cara halaman ini diverifikasi

Dibaca pada 2026-09-15 dari module payments backend dan hook DOKU storefront.

Backend

Module payments tidak punya entity sendiri — data payment ada di order. Ia REST-only (tidak ada di include GraphQL).

  • PaymentsService (src/payments/services/payments.service.ts) adalah client DOKU: postPaymentRequest dan checkPaymentStatus. Base URL DOKU_BASEURL; kredensial DOKU_CLIENT_ID dan DOKU_SECRET_KEY; tiap request ditandatangani HMAC-SHA256 (HMACSHA256=<base64>). Payment window adalah DOKU_PAYMENT_DUE_DATE_MINUTE.
  • URL callback dibangun dari APP_FRONTEND_STOREFRONT_BASE_URL; notify DOKU menuju ${APP_BACKEND_BASE_URL}/webhooks/payments.
  • webhook-payments.service.ts handleEvent: pada transaction.status === 'SUCCESS' ia memindahkan order ke processing. Backend dibuat dengan rawBody: true agar bisa memverifikasi signature DOKU.

Order dibuat dengan payment link selama createOrder() — lihat Cart and checkout.

Storefront

src/hooks/useDokuCheckoutPayment.tsx memuat script Jokul Checkout DOKU (URL sandbox vs production berdasarkan NEXT_PUBLIC_DOKU_ENV) dan memanggil window.loadJokulCheckout(paymentUrl) dengan paymentLinkUrl yang dikembalikan frontValidateMemberCartCheckout. Saat ditutup, customer mendarat di /user/my-order?status=pending_payment. Hook yang sama menjalankan "pay again" dari detail order (src/modules/my-order/components/order-item-detail.tsx).

Order yang belum dibayar

Order yang tertinggal pending_payment melewati window-nya dibatalkan oleh order expiry cron, yang mengecek ulang DOKU lebih dulu.

Hal yang perlu diwaspadai

  • Signature butuh raw body. Backend menjaga rawBody: true justru untuk ini — jangan hilangkan.
  • Di dev, DOKU adalah simulator. Simulator bisa memaksa DOKU error; kegagalan payment di dev bisa jadi toggle-nya, bukan kodenya.
  • Jalur callback production yang masuk menyebar lewat webhook receiver → SNS, bukan langsung ke backend.