MIF_E31222882/app/Services/MidtransService.php

237 lines
8.0 KiB
PHP

<?php
namespace App\Services;
use App\Models\Booking;
use App\Models\Table;
use App\Models\User;
use Midtrans\Config;
use Midtrans\Snap;
use Illuminate\Support\Facades\Log;
class MidtransService
{
public function __construct()
{
$serverKey = config('midtrans.server_key');
$clientKey = config('midtrans.client_key');
$merchantId = config('midtrans.merchant_id');
$isProduction = config('midtrans.is_production', false);
// Log semua konfigurasi untuk debugging
Log::info('Midtrans Configuration:', [
'server_key' => $serverKey,
'client_key' => $clientKey,
'merchant_id' => $merchantId,
'is_production' => $isProduction
]);
if (empty($serverKey)) {
throw new \Exception('Midtrans server key is not configured');
}
Config::$serverKey = $serverKey;
Config::$isProduction = $isProduction;
Config::$isSanitized = true;
Config::$is3ds = true;
// Log konfigurasi yang digunakan oleh Midtrans
Log::info('Midtrans Config:', [
'server_key' => Config::$serverKey,
'is_production' => Config::$isProduction,
'is_sanitized' => Config::$isSanitized,
'is_3ds' => Config::$is3ds
]);
}
// Method baru untuk membuat transaksi sementara tanpa booking record
public function createTemporaryTransaction(Table $table, int $amount, string $orderId, User $user)
{
try {
if ($amount <= 0) {
throw new \Exception('Invalid booking amount');
}
$params = [
'transaction_details' => [
'order_id' => $orderId,
'gross_amount' => (int) $amount,
],
'customer_details' => [
'first_name' => $user->name,
'email' => $user->email,
],
'item_details' => [
[
'id' => $table->id,
'price' => (int) $amount,
'quantity' => 1,
'name' => 'Booking Meja ' . $table->name,
],
],
'expiry' => [
'start_time' => now()->format('Y-m-d H:i:s O'),
'unit' => 'hour',
'duration' => 24,
],
];
Log::info('Creating Midtrans temporary transaction:', [
'order_id' => $orderId,
'amount' => $amount,
'params' => $params
]);
$snapToken = Snap::getSnapToken($params);
if (empty($snapToken)) {
throw new \Exception('Empty snap token received from Midtrans');
}
Log::info('Midtrans temporary transaction created successfully:', [
'order_id' => $orderId,
'snap_token' => $snapToken
]);
return $snapToken;
} catch (\Exception $e) {
Log::error('Midtrans temporary transaction failed:', [
'order_id' => $orderId,
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
throw new \Exception('Failed to create Midtrans transaction: ' . $e->getMessage());
}
}
// Metode original untuk backward compatibility
public function createTransaction(Booking $booking)
{
try {
if (!$booking->user) {
throw new \Exception('User not found for booking');
}
if (empty($booking->total_amount) || $booking->total_amount <= 0) {
throw new \Exception('Invalid booking amount');
}
$params = [
'transaction_details' => [
'order_id' => 'BOOK-' . $booking->id,
'gross_amount' => (int) $booking->total_amount,
],
'customer_details' => [
'first_name' => $booking->user->name,
'email' => $booking->user->email,
],
'item_details' => [
[
'id' => $booking->table_id,
'price' => (int) $booking->total_amount,
'quantity' => 1,
'name' => 'Booking Meja ' . $booking->table->name,
],
],
'expiry' => [
'start_time' => now()->format('Y-m-d H:i:s O'),
'unit' => 'hour',
'duration' => 24,
],
];
Log::info('Creating Midtrans transaction:', [
'booking_id' => $booking->id,
'amount' => $booking->total_amount,
'params' => $params
]);
$snapToken = Snap::getSnapToken($params);
if (empty($snapToken)) {
throw new \Exception('Empty snap token received from Midtrans');
}
Log::info('Midtrans transaction created successfully:', [
'booking_id' => $booking->id,
'snap_token' => $snapToken
]);
return $snapToken;
} catch (\Exception $e) {
Log::error('Midtrans transaction failed:', [
'booking_id' => $booking->id,
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
throw new \Exception('Failed to create Midtrans transaction: ' . $e->getMessage());
}
}
public function handleNotification($notification)
{
try {
$transaction = $notification->transaction_status;
$type = $notification->payment_type;
$orderId = $notification->order_id;
$fraud = $notification->fraud_status;
Log::info('Received Midtrans notification:', [
'transaction_status' => $transaction,
'payment_type' => $type,
'order_id' => $orderId,
'fraud_status' => $fraud
]);
// Check if this is a temporary order
if (strpos($orderId, 'TEMP-') === 0) {
Log::info('Notification for temporary order received, will be handled separately', [
'order_id' => $orderId
]);
return null;
}
// Handle existing bookings
// Extract booking ID from order ID (format: BOOK-{id})
$bookingId = explode('-', $orderId)[1];
$booking = Booking::findOrFail($bookingId);
if ($transaction == 'capture') {
if ($type == 'credit_card') {
if ($fraud == 'challenge') {
$booking->status = 'pending';
} else {
$booking->status = 'paid';
}
}
} else if ($transaction == 'settlement') {
$booking->status = 'paid';
} else if ($transaction == 'pending') {
$booking->status = 'pending';
} else if ($transaction == 'deny') {
$booking->status = 'cancelled';
} else if ($transaction == 'expire') {
$booking->status = 'expired';
} else if ($transaction == 'cancel') {
$booking->status = 'cancelled';
}
$booking->payment_id = $notification->transaction_id;
$booking->payment_method = $type;
$booking->save();
Log::info('Booking status updated:', [
'booking_id' => $booking->id,
'new_status' => $booking->status
]);
return $booking;
} catch (\Exception $e) {
Log::error('Failed to handle Midtrans notification:', [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
throw $e;
}
}
}