Files
manjapro_v6/paymentlink/services/gateways/Doku.php
T
2026-08-20 18:39:37 +07:00

299 lines
10 KiB
PHP

<?php
class Doku
{
private $clientId;
private $secretKey;
private $baseUrl;
private $pdo;
public function __construct($pdo)
{
$this->pdo = $pdo;
// LOAD CONFIG
$config = require __DIR__ . '/config.php';
$this->clientId = $config['client_id'];
$this->secretKey = $config['secret_key'];
$this->baseUrl = $config['url_endpoint'];
}
// ================= SIGNATURE =================
private function generateSignature($requestId, $timestamp, $endpoint, $body)
{
$jsonBody = json_encode($body);
// DIGEST (WAJIB FORMAT INI)
$digest = base64_encode(hash('sha256', $jsonBody, true));
// STRING TO SIGN (WAJIB PERSIS DOC)
$stringToSign =
"Client-Id:" . $this->clientId . "\n" .
"Request-Id:" . $requestId . "\n" .
"Request-Timestamp:" . $timestamp . "\n" .
"Request-Target:" . $endpoint . "\n" . // ❗ TANPA post
"Digest:" . $digest;
// SIGNATURE
$signature = "HMACSHA256=" . base64_encode(
hash_hmac('sha256', $stringToSign, $this->secretKey, true)
);
return [
'signature' => $signature,
'digest' => $digest,
'jsonBody' => $jsonBody
];
}
// ================= CREATE PAYMENT =================
public function charge($data)
{
// ================= SIGNATURE =================
$requestId = bin2hex(random_bytes(16));
$timestamp = gmdate("Y-m-d\TH:i:s\Z");
$endpoint = "/checkout/v1/payment";
$url = $this->baseUrl . $endpoint;
// Trasaction ID
$trxId = $data['transaction_id'] ?? null;
$body = [
"order" => [
"amount" => $data['amount'], //$data['amount']
"invoice_number" => $trxId,
"currency" => "IDR",
"session_id" => uniqid(),
"callback_url" => "https://wp.manjapro.net/" . $_SESSION['token'],
"line_items" => [
[
"name" => $data['invoice_detail']['keterangan'],
"price" => $data['amount'], //$data['amount']
"quantity" => 1
]
]
],
"payment" => [
"payment_due_date" => 60
],
"customer" => [
"name" => $data['customer']['nama'] ?? "CUSTOMER",
"email" => $data['customer']['email'],
"phone" => $data['customer']['nomor_whtasapp'],
"address" => $data['customer']['alamat'],
"country" => "ID"
]
];
$sign = $this->generateSignature($requestId, $timestamp, $endpoint, $body);
// ================= HEADER =================
$headers = [
"Client-Id: " . $this->clientId,
"Request-Id: " . $requestId,
"Request-Timestamp: " . $timestamp,
"Request-Target: " . $endpoint, // ❗ TANPA post
"Digest: " . $sign['digest'],
"Signature: " . $sign['signature'],
"Content-Type: application/json"
];
// ================= CURL =================
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url, // ✅ FIX
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => $sign['jsonBody'],
CURLOPT_HTTPHEADER => $headers
]);
$response = curl_exec($ch);
$err = curl_error($ch);
curl_close($ch);
// ================= ERROR CURL =================
if ($err) {
$this->saveLog([
'type' => 'ERROR',
'endpoint' => $endpoint,
'request' => $sign['jsonBody'],
'response' => $err,
'status' => 'FAILED'
]);
return [
'success' => false,
'message' => $err
];
}
$result = json_decode($response, true);
// ================= HANDLE ERROR =================
if (!isset($result['response'])) {
return [
'success' => false,
'message' => $result['error']['message'] ?? 'Unknown error',
'raw' => $result
];
}
$res = $result['response'];
// ================= PARSE =================
$external_id = $res['headers']['request_id'] ?? null;
$amount = $res['order']['amount'] ?? $data['amount'];
// ✅ CHECKOUT MODE
$paymentUrl = $res['payment']['url'] ?? null;
$tokenId = $res['payment']['token_id'] ?? null;
// yang data nya gak perlu ada.
$channels = null;
$vaNumber = null;
$qrString = null;
$qrUrl = null;
// status default (checkout biasanya belum bayar)
$status = 'PENDING';
// expired
$expiredAt = isset($res['payment']['expired_datetime'])
? date("Y-m-d H:i:s", strtotime($res['payment']['expired_datetime']))
: date("Y-m-d H:i:s", strtotime("+1 day"));
// ================= SAVE =================
$this->saveTransaction([
'trx_id' => $trxId,
'external_id' => $external_id,
'customer_id' => $data['customer']['id'] ?? null,
'invoice_id' => $data['invoice_id'] ?? null,
'method' => $data['raw_method'] ?? 'DOKU_CHECKOUT',
'channel' => $channels, // simpan list method
'amount' => $amount,
'va_number' => $vaNumber,
'qr_string' => $qrString,
'qr_url' => $qrUrl,
'payment_url' => $paymentUrl,
'response_create' => $response,
'status' => $status,
'expired_at' => $expiredAt
]);
// ================= LOG =================
$this->saveLog([
'trx_id' => $trxId,
'type' => 'RESPONSE',
'endpoint' => $endpoint,
'method' => $data['raw_method'] ?? null,
'request' => $sign['jsonBody'],
'response' => $response,
'status' => 'SUCCESS'
]);
/**
* =========================
* RETURN SUCCESS
* =========================
*/
return [
"status" => $status,
"transaction_id" => $trxId,
"payment_url" => $paymentUrl,
"raw" => $result
];
}
// ================= SAVE TRANSACTION =================
private function saveTransaction($data)
{
try {
$stmt = $this->pdo->prepare("
INSERT INTO payment_winpay (
trx_id, external_id, id_pelanggan, id_tagihan,
gateway_type, method, channel, amount,
va_number, qr_string, qr_url, payment_url,
status, response_create, expired_at,
created_at, updated_at
) VALUES (
:trx_id, :external_id, :id_pelanggan, :id_tagihan,
'DOKU', :method, :channel, :amount,
:va_number, :qr_string, :qr_url, :payment_url,
:status, :response_create, :expired_at,
NOW(), NOW()
)
");
$stmt->execute([
':trx_id' => $data['trx_id'],
':external_id' => $data['external_id'],
':id_pelanggan' => $data['customer_id'],
':id_tagihan' => $data['invoice_id'],
':method' => $data['method'],
':channel' => $data['channel'],
':amount' => $data['amount'],
':va_number' => $data['va_number'],
':qr_string' => $data['qr_string'],
':qr_url' => $data['qr_url'],
':payment_url' => $data['payment_url'],
':status' => $data['status'],
':response_create' => $data['response_create'],
':expired_at' => $data['expired_at']
]);
// ================= UPDATE TAGIHAN =================
$stmt = $this->pdo->prepare("
UPDATE tagihan SET
transaction_id = :transaction_id
WHERE id = :id_tagihan
AND id_pelanggan = :id_pelanggan
");
$stmt->execute([
':transaction_id' => $data['trx_id'],
':id_tagihan' => $data['invoice_id'],
':id_pelanggan' => $data['customer_id']
]);
} catch (Exception $e) {
file_put_contents(
__DIR__ . '/doku_error.log',
date('Y-m-d H:i:s') . " | " . $e->getMessage() . PHP_EOL,
FILE_APPEND
);
}
}
// ================= SAVE LOG =================
private function saveLog($data)
{
try {
$stmt = $this->pdo->prepare("
INSERT INTO payment_winpay_log (
trx_id, type, endpoint, method,
request_body, response_body,
status, created_at
) VALUES (
:trx_id, :type, :endpoint, :method,
:request_body, :response_body,
:status, NOW()
)
");
$stmt->execute([
':trx_id' => $data['trx_id'] ?? null,
':type' => $data['type'],
':endpoint' => $data['endpoint'],
':method' => $data['method'] ?? null,
':request_body' => $data['request'],
':response_body' => $data['response'],
':status' => $data['status'],
]);
} catch (Exception $e) {}
}
}