SMAMUGAPAY/app/Controllers/Siswa/Payment.php

333 lines
13 KiB
PHP

<?php
namespace App\Controllers\Siswa;
use CodeIgniter\Controller;
use App\Models\Tagihan_model;
use App\Models\Riwayat_pembayaran_model;
use App\Models\Siswa_model;
use App\Models\Order_model;
class Payment extends Controller
{
private $clientId = 'BRN-0277-1747654294964';
private $sharedKey = 'SK-1VFsbIhOpxbtxls43FFw';
private $sandbox = false;
public function create()
{
// Terima data dari frontend
$input = json_decode(file_get_contents('php://input'), true);
$invoiceNumber = $input['invoice_number'];
$amount = $input['amount'] ?? 0;
$idSiswa = $input['id_siswa'];
$idTagihan = $input['id_tagihan'];
// Cek apakah sudah ada order dengan invoice_number yang sama
$orderModel = new Order_model();
$existingOrder = $orderModel->where('invoice_number', $invoiceNumber)->first();
if ($existingOrder) {
// Jika order sudah ada, cek status pembayaran
if ($existingOrder['status'] === 'Lunas') {
// Jika status sudah Lunas, beri respons bahwa pembayaran sudah berhasil
return $this->response->setJSON([
'status' => 'error',
'message' => 'Order dengan invoice number ini sudah Lunas dan tidak perlu diproses lagi.'
]);
} else {
// Jika order sudah ada dan status belum Lunas, lanjutkan ke pembayaran Doku
// Proses pembayaran Doku...
$requestId = uniqid();
$timestamp = gmdate("Y-m-d\TH:i:s\Z");
$path = '/checkout/v1/payment';
$body = [
'order' => [
'amount' => $amount,
'invoice_number' => $invoiceNumber
],
'payment' => [
'payment_due_date' => 60
]
];
$jsonBody = json_encode($body, JSON_UNESCAPED_SLASHES);
$digest = base64_encode(hash('sha256', $jsonBody, true));
$rawSignature = "Client-Id:{$this->clientId}\n"
. "Request-Id:$requestId\n"
. "Request-Timestamp:$timestamp\n"
. "Request-Target:$path\n"
. "Digest:$digest";
$signature = base64_encode(hash_hmac('sha256', $rawSignature, $this->sharedKey, true));
$headers = [
"Content-Type: application/json",
"Client-Id: {$this->clientId}",
"Request-Id: $requestId",
"Request-Timestamp: $timestamp",
"Signature: HMACSHA256=$signature",
"Digest: SHA-256=$digest"
];
$url = $this->sandbox
? "https://api-sandbox.doku.com$path"
: "https://api.doku.com$path";
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => $url,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $jsonBody,
CURLOPT_RETURNTRANSFER => true
]);
$response = curl_exec($curl);
curl_close($curl);
$result = json_decode($response, true);
log_message('info', 'Response from Doku: ' . json_encode($result));
// Jika berhasil mendapatkan payment URL dari Doku
if (isset($result['response']['payment']['url'])) {
return $this->response->setJSON([
'status' => 'success',
'paymentUrl' => $result['response']['payment']['url']
]);
}
return $this->response->setJSON([
'status' => 'error',
'message' => 'Gagal mendapatkan payment URL',
'response' => $result
]);
}
} else {
// Jika order tidak ada, simpan order baru dan lanjutkan ke pembayaran Doku
$orderData = [
'id_siswa' => $idSiswa,
'id_tagihan' => $idTagihan,
'status' => 'Menunggu Pembayaran', // Status awal
'invoice_number' => $invoiceNumber,
'jumlah_bayar' => $amount,
'metode_pembayaran' => 'Doku',
'response_code' => '',
'response_message' => '',
'response_data' => '',
'tanggal_bayar' => null, // Belum ada tanggal bayar
'created_at' => date('Y-m-d H:i:s'),
];
// Simpan ke model dan dapatkan order_id yang auto increment
$orderId = $orderModel->insert($orderData); // $orderId adalah order_id yang auto increment
if (!$orderId) {
return $this->response->setJSON([
'status' => 'error',
'message' => 'Gagal membuat order'
]);
}
// Lanjutkan ke Doku API untuk membuat pembayaran
$requestId = uniqid();
$timestamp = gmdate("Y-m-d\TH:i:s\Z");
$path = '/checkout/v1/payment';
$body = [
'order' => [
'amount' => $amount,
'invoice_number' => $invoiceNumber
],
'payment' => [
'payment_due_date' => 60
]
];
$jsonBody = json_encode($body, JSON_UNESCAPED_SLASHES);
$digest = base64_encode(hash('sha256', $jsonBody, true));
$rawSignature = "Client-Id:{$this->clientId}\n"
. "Request-Id:$requestId\n"
. "Request-Timestamp:$timestamp\n"
. "Request-Target:$path\n"
. "Digest:$digest";
$signature = base64_encode(hash_hmac('sha256', $rawSignature, $this->sharedKey, true));
$headers = [
"Content-Type: application/json",
"Client-Id: {$this->clientId}",
"Request-Id: $requestId",
"Request-Timestamp: $timestamp",
"Signature: HMACSHA256=$signature",
"Digest: SHA-256=$digest"
];
$url = $this->sandbox
? "https://api-sandbox.doku.com$path"
: "https://api.doku.com$path";
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => $url,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $jsonBody,
CURLOPT_RETURNTRANSFER => true
]);
$response = curl_exec($curl);
curl_close($curl);
$result = json_decode($response, true);
// Jika berhasil mendapatkan payment URL dari Doku
if (isset($result['response']['payment']['url'])) {
return $this->response->setJSON([
'status' => 'success',
'paymentUrl' => $result['response']['payment']['url']
]);
}
return $this->response->setJSON([
'status' => 'error',
'message' => 'Gagal mendapatkan payment URL',
'response' => $result
]);
}
}
public function paymentNotification()
{
// Terima data yang dikirim Doku
$input = json_decode(file_get_contents('php://input'), true);
// Log untuk memverifikasi data yang diterima
log_message('info', 'Payment Notification Data: ' . json_encode($input));
// Pastikan status pembayaran berhasil (status_code 'SUCCESS' dalam response dari Doku)
if (!isset($input['transaction']['status']) || $input['transaction']['status'] !== 'SUCCESS') {
log_message('error', 'Payment failed: ' . json_encode($input));
return $this->response->setJSON([
'status' => 'error',
'message' => 'Payment failed.'
]);
}
// Mendapatkan data penting dari response Doku
$invoiceNumber = $input['order']['invoice_number']; // Ambil invoice_number dari notifikasi
log_message('info', 'Received invoice_number: ' . $invoiceNumber); // Log invoice_number yang diterima
$paymentStatus = $input['transaction']['status']; // Status pembayaran
$paymentDate = date('Y-m-d H:i:s'); // Waktu pembayaran yang akan disimpan
$amount = $input['order']['amount']; // Jumlah pembayaran yang diterima
// Ambil nama channel dari body Doku
$channelName = $input['channel']['name'] ?? 'Unknown Channel'; // Ambil nama channel (default ke 'Unknown Channel' jika tidak ada)
// Verifikasi order berdasarkan invoice_number yang dikirim Doku
$orderModel = new Order_model();
$order = $orderModel->where('invoice_number', $invoiceNumber)->first(); // Cari order berdasarkan invoice_number
if (!$order) {
// Jika order tidak ditemukan, kirimkan error response
log_message('error', 'Order not found for invoice_number: ' . $invoiceNumber);
return $this->response->setJSON([
'status' => 'error',
'message' => 'Order not found.'
]);
}
// Log jika order ditemukan
log_message('info', 'Order found: ' . json_encode($order));
// Periksa apakah status order sudah 'Lunas', jika sudah, beri respon duplikat
if ($order['status'] === 'Lunas') {
log_message('info', 'Duplicate request for invoice_number: ' . $invoiceNumber);
return $this->response->setJSON([
'status' => 'error',
'message' => 'Duplicate request. Payment already processed.'
]);
}
// Update status pembayaran di tabel orders dan ganti metode_pembayaran dengan channel.name dari Doku
$updateOrderStatus = $orderModel->update($order['id_order'], [
'status' => ($paymentStatus === 'SUCCESS') ? 'Lunas' : 'Gagal',
'tanggal_bayar' => ($paymentStatus === 'SUCCESS') ? $paymentDate : null,
'response_code' => $paymentStatus, // Menyimpan status pembayaran (misal "SUCCESS")
'response_message' => "Payment processed successfully", // Pesan response yang relevan
'response_data' => json_encode($input), // Menyimpan seluruh data respons dari Doku
'metode_pembayaran' => $channelName // Update metode pembayaran dengan nama channel
]);
if (!$updateOrderStatus) {
log_message('error', 'Failed to update order status for order_id: ' . $order['id_order']);
return $this->response->setJSON([
'status' => 'error',
'message' => 'Failed to update order status.'
]);
} else {
log_message('info', 'Order status updated successfully for order_id: ' . $order['id_order']);
}
// **Update Tagihan Status**
// Perbarui status tagihan menjadi 'Lunas' jika pembayaran berhasil
if ($paymentStatus === 'SUCCESS') {
$tagihanModel = new Tagihan_model();
$updateTagihan = $tagihanModel->update($order['id_tagihan'], [
'status' => 'Lunas',
'tanggal_bayar' => $paymentDate // Update tanggal bayar
]);
if (!$updateTagihan) {
log_message('error', 'Failed to update tagihan status for tagihan_id: ' . $order['id_tagihan']);
return $this->response->setJSON([
'status' => 'error',
'message' => 'Failed to update tagihan status.'
]);
} else {
log_message('info', 'Tagihan status updated successfully for tagihan_id: ' . $order['id_tagihan']);
}
}
// **Insert Riwayat Pembayaran**
// Ambil ID siswa terkait dengan order
$siswaModel = new Siswa_model();
$siswa = $siswaModel->find($order['id_siswa']); // Ambil data siswa terkait dengan order
if ($siswa) {
// Menambahkan data riwayat pembayaran
$dataRiwayatPembayaran = [
'id_siswa' => $siswa['id_siswa'],
'id_tagihan' => $order['id_tagihan'],
'tanggal_bayar' => $paymentDate,
'jumlah_bayar' => $amount,
'id_order' => $order['id_order'],
'created_at' => date('Y-m-d H:i:s')
];
// Insert riwayat pembayaran ke tabel
$riwayatPembayaranModel = new Riwayat_pembayaran_model();
$riwayatPembayaranModel->insert($dataRiwayatPembayaran);
log_message('info', 'Riwayat pembayaran berhasil ditambahkan untuk siswa ID: ' . $siswa['id_siswa']);
} else {
log_message('error', 'Siswa tidak ditemukan untuk order_id: ' . $order['id_order']);
}
// Kirimkan response sukses ke Doku
log_message('info', 'Payment notification processed successfully for invoice_number: ' . $invoiceNumber);
return $this->response->setJSON([
'status' => 'success',
'message' => 'Payment notification received and processed successfully.'
]);
}
}