AMS_Backend/app/Libraries/Lalamove.php
2025-11-06 13:41:06 +08:00

292 lines
12 KiB
PHP

<?php
namespace App\Libraries;
use App\Models\Outlet;
use App\Models\Orders;
use App\Models\LogLalamove;
use App\Models\OrderDeliveries;
class Lalamove {
protected $api_url;
protected $api_secret;
protected $api_key;
protected $outlet;
public function __construct() {
$this->api_url = defined('LALAMOVELINK') ? LALAMOVELINK : '';
$this->api_secret = defined('LALAMOVESECRET') ? LALAMOVESECRET : '';
$this->api_key = defined('LALAMOVEAPIKEY') ? LALAMOVEAPIKEY : '';
helper("general");
$this->outlet = new Outlet();
}
public function requestQuotation($selected_date = null, $selected_time = null, $total_amount = null, $outlet_id = null, $latitude = null, $longitude = null, $address = null) {
//check service type
if($total_amount > 150){
$service_type = 'CAR';
}else{
$service_type = 'MOTORCYCLE';
}
//get outlet details
$outlet_data = $this->outlet->where('id', $outlet_id)->first();
$outlet_address = $outlet_data['address'];
$outlet_latitude = $outlet_data['latitude'];
$outlet_longitude = $outlet_data['longitude'];
// echo($outlet_latitude);exit;
$stops = [
[
"coordinates" => [
"lat" => $outlet_latitude,
"lng" => $outlet_longitude
],
"address" => $outlet_address
],
[
"coordinates" => [
"lat" => $latitude,
"lng" => $longitude
],
"address" => $address
]
];
$request_data = [
"data" => [
'serviceType' => $service_type,
'stops' => $stops,
'language' => 'en_MY'
]
];
//handling preorder
if($selected_date && $selected_time){
// Convert local Y-m-d H:i:s to UTC ISO 8601 format
$local_datetime = $selected_date . ' ' . $selected_time;
$dt = new \DateTime($local_datetime, new \DateTimeZone('Asia/Kuala_Lumpur'));
$request_data['data']['scheduleAt'] = $dt->format('Y-m-d\TH:i:s\Z');
}
$request_body = json_encode($request_data);
$timestamp = time() * 1000;
$raw_signature = $timestamp . "\r\nPOST\r\n/v3/quotations\r\n\r\n" . $request_body;
$signature = hash_hmac('sha256', $raw_signature, $this->api_secret);
$token = $this->api_key.':'.$timestamp.':'.$signature;
$headers = [
'Authorization: hmac ' . $token,
'Content-Type: application/json',
'Market: MY',
'Request-ID: 211b9d85-ips-476f-8675-b61ec923cc27'
];
$response = send_api_request('POST', $this->api_url.'/quotations', $headers, $request_body);
$log_lalamove = new LogLalamove();
$log_lalamove->insert([
'url' => $this->api_url.'/quotations',
'request' => $request_body,
'respond' => json_encode($response),
'quotation_id' => $response['data']['quotationId'] ?? null,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s')
]);
return $response;
}
public function submitOrder($order_id){
$orders = new Orders();
$order = $orders->select('orders.*, customer_addresses.name as recipient_name, customer_addresses.phone as recipient_phone, customer_addresses.note as recipient_note, log_lalamove.quotation_id, log_lalamove.respond, outlets.pic_name, outlets.pic_phone')
->join('log_lalamove', 'log_lalamove.quotation_id = orders.lalamove_quot_id')
->join('outlets', 'outlets.id = orders.outlet_id')
->join('customer_addresses', 'customer_addresses.id = orders.customer_address_id AND customer_addresses.deleted_at IS NULL', 'left')
->where('orders.id', $order_id)
->where('orders.deleted_at', null)
->first();
$quotation_id = $order['lalamove_quot_id'];
$quotation_data = json_decode($order['respond'], true);
$request_data = [
"data" => [
'quotationId' => $quotation_id,
"sender" => [
"stopId" => $quotation_data['data']['stops'][0]['stopId'],
"name" => $order['pic_name'] ?? 'US Pizza',
"phone" => $order['pic_phone'] ?? '+60123456789'
],
"recipients" => [
[
"stopId" => $quotation_data['data']['stops'][1]['stopId'],
"name" => $order['recipient_name'],
"phone" => $order['recipient_phone'] ? '+6'.$order['recipient_phone'] : '+60123456789',
"remarks" => $order['recipient_note']
]
],
"isPODEnabled" => true,
"partner" => "USPizza Delivery",
"metadata" => [
"order_id" => $order['id'],
]
]
];
$request_body = json_encode($request_data);
$timestamp = time() * 1000;
$raw_signature = $timestamp . "\r\nPOST\r\n/v3/orders\r\n\r\n" . $request_body;
$signature = hash_hmac('sha256', $raw_signature, $this->api_secret);
$token = $this->api_key.':'.$timestamp.':'.$signature;
$headers = [
'Authorization: hmac ' . $token,
'Content-Type: application/json',
'Market: MY',
'Request-ID: 211b9d85-ips-476f-8675-b61ec923cc27'
];
$response = send_api_request('POST', $this->api_url.'/orders', $headers, $request_body);
$log_lalamove = new LogLalamove();
$log_lalamove->insert([
'url' => $this->api_url.'/orders',
'request' => $request_body,
'respond' => json_encode($response),
'quotation_id' => $quotation_id,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s')
]);
return $response;
}
public function handleWebhook($data){
//compare signature
$signature = $data['signature'];
$timestamp = $data['timestamp'];
$http_verb = 'POST';
$path = '/api/lalamove/webhook';
$json_body = json_encode($data['data'], JSON_UNESCAPED_SLASHES);
$raw_signature = $timestamp . "\r\n" . $http_verb . "\r\n" . $path . "\r\n\r\n" . $json_body;
$mysignature = hash_hmac('sha256', $raw_signature, $this->api_secret);
if($signature == $mysignature){
$log_lalamove = new LogLalamove();
$log_lalamove->insert([
'url' => $this->api_url.'/webhook',
'request' => json_encode($data),
'respond' => $data['eventType'] == 'ORDER_STATUS_CHANGED' ? 'ORDER_STATUS_CHANGED ('.$data['data']['order']['orderId'].'): '.$data['data']['order']['status'] : $data['eventType'],
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s')
]);
if($data['eventType'] == 'ORDER_STATUS_CHANGED'){
$orders = new Orders();
$order = $orders->select('orders.*, customer_addresses.phone as recipient_phone, order_deliveries.tracking_link')
->join('customer_addresses', 'customer_addresses.id = orders.customer_address_id AND customer_addresses.deleted_at IS NULL', 'left')
->join('order_deliveries', 'order_deliveries.order_id = orders.id')
->where('order_deliveries.provider_name', 'Lalamove')
->where('order_deliveries.provider_order_id', $data['data']['order']['orderId'])
->first();
if($order){
$order_id = $order['id'];
$lalamove_order_id = $data['data']['order']['orderId'];
$order_status = 'pending';
switch($data['data']['order']['status']){
case 'ON_GOING':
$order_status = 'on_the_way';
break;
case 'PICKED_UP':
$order_status = 'picked_up';
break;
case 'COMPLETED':
$order_status = 'completed';
break;
case 'CANCELLED':
$order_status = 'cancelled';
break;
}
$orders->update($order_id, ['status' => $order_status]);
//send notification to customer
$message = '';
switch($order_status){
case 'on_the_way':
$message = "🚚 Your order [**".$order['order_so']."**] is on the way!\nThe driver is delivering your food now.\nPlease get ready to receive it.\nHere is the tracking link: \n\n" . $order['tracking_link'];
break;
case 'completed':
$message = "🎉 Your order [**".$order['order_so']."**] has been completed.\nWe hope you enjoy your meal!\nThank you for ordering with us.";
break;
}
if($message){
$wato = new Wato();
$wato->pushNotification($order['recipient_phone'], $message);
}
if($order_status == 'completed'){
//get order details
$order_details = $this->getOrderDetails($lalamove_order_id);
$pod_details = $order_details['data']['stops'][1]['POD'];
if($pod_details['status'] == 'DELIVERED' || $pod_details['status'] == 'SIGNED'){
$order_deliveries = new OrderDeliveries();
$delivery_records = $order_deliveries->where('order_id', $order_id)
->where('provider_name', 'Lalamove')
->where('provider_order_id', $lalamove_order_id)
->get()->getResultArray();
if (!empty($delivery_records)) {
// Update delivery status to completed
$order_deliveries->where('order_id', $order_id)
->where('provider_name', 'Lalamove')
->where('provider_order_id', $lalamove_order_id)
->set(['POD_url' => $pod_details['image'], 'delivered_at' => $pod_details['deliveredAt']])
->update();
}
}
} elseif($order_status == 'cancelled'){
// Update delivery status to cancelled
// $order_deliveries = new OrderDeliveries();
// $order_deliveries->where('order_id', $order_id)
// ->where('provider_name', 'Lalamove')
// ->where('provider_order_id', $lalamove_order_id)
// ->set(['status' => 'cancelled', 'cancelled_at' => date('Y-m-d H:i:s')])
// ->update();
}
}
}
}
return true;
}
public function getOrderDetails($lalamove_order_id){
$timestamp = time() * 1000;
$raw_signature = $timestamp . "\r\nGET\r\n/v3/orders/" . $lalamove_order_id . "\r\n\r\n";
$signature = hash_hmac('sha256', $raw_signature, $this->api_secret);
$token = $this->api_key.':'.$timestamp.':'.$signature;
$headers = [
'Authorization: hmac ' . $token,
'Content-Type: application/json',
'Market: MY',
'Request-ID: 211b9d85-ips-476f-8675-b61ec923cc27'
];
$response = send_api_request('GET', $this->api_url.'/orders/'.$lalamove_order_id, $headers);
return $response;
}
}