299 lines
10 KiB
PHP
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) {}
|
|
}
|
|
} |