HOME


Mini Shell 1.0
La Pieza.DO | Todo lo que buscas!

Bienvenido de nuevo!

Acceso Cuenta Delivery
DIR: /var/www/devs.lapieza.net/app/Http/Controllers/Mensajeria/
Upload File :
Current File : /var/www/devs.lapieza.net/app/Http/Controllers/Mensajeria/WhatsAppController.php
<?php

namespace App\Http\Controllers\Mensajeria;

use App\Classes\WhatsAppMessage;
use App\Http\Controllers\Controller;
use App\Models\Address;
use App\Models\BusinessSetting;
use App\Models\User;
use App\Models\UserHasConversation;
use App\Models\WorkShopProposal;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\URL;

class WhatsAppController extends Controller
{
//    private const TOKEN = 'EAAEdR4iWMnQBO6QxSdCZC7o2aAGAh64uLkmZCsJVqX4oCBYfhF1WaacwcOuKwTUauVsA2RVwsZBxabM1lzNYJRZASecMmZCw0jw2BXYOZCPcpZBy7cWxT0X8nZBbVZAfjVNn2YDLjAQ2wYieL0Dzz7OhA6UFpclb22l3QqHVMTMJlPeA7zCsTOJR2klG7g6QHmgbJefAT6KITUr91ryFp';
//    private const PHONE_NUMBER_ID = '220567651146286';
    private const PHONE_NUMBER_ID = '165221420014421';
    private const VERSION = "v21.0";
    private const SEND_MESSAGE_URL = 'https://graph.facebook.com/' . self::VERSION . '/' . self::PHONE_NUMBER_ID . '/messages';
    private string $api_token;
    private array $headers;
    private const CLIENT_CONFIRM = 'SI, CONFIRMAR!';
    private const CLIENT_REJECT = 'NO, CANCELAR!';
    private const WORKSHOP_ACCEPT = 'SI PUEDO';
    private const WORKSHOP_REJECT = 'NO ESTARÉ DISPOPNIBLE';
    private const WORKSHOP_SEND_PROPOSAL = 'ENVIAR PROPUESTA';
    private const WORKSHOP_FINISHED_PROPOSAL = 'FINALIZAR PROPUESTA';
    private const CLIENT_ACCEPT_PROPOSAL = 'ACEPTAR';
    private const CLIENT_REJECT_PROPOSAL = 'RECHAZAR';

    public function __construct()
    {
        $this->api_token = config('app.whatsapp_api_token', 'EAAEdR4iWMnQBO75blnibahkpX7CZAZCCaDQ0BTXKt1rjoSD4wm3lr1wxoKLzotvqaXRisv39RYwrFghSoGDvcJQ3m33Nss6APionRFOJFVrGonbZCz7G8ufiXNSnkwLl8AUPgbAxEFP0Y8nyUCHyGsH1JKDmobvP3WQezjbkHHZB5ApfXxqG4bDbRhoH65NpzAZDZD');

        $this->headers = [
            "Authorization: Bearer " . $this->api_token,
            "Content-Type: application/json",
            "Accept: application/json"
        ];
    }

    public function sendMessage(mixed $message)
    {
        $curl = curl_init();

        curl_setopt($curl, CURLOPT_URL, self::SEND_MESSAGE_URL);
        curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($message));
        curl_setopt($curl, CURLOPT_HTTPHEADER, $this->headers);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        //TODO: Verificar certificados
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);

        $response = curl_exec($curl);

        if ($response === false) {
            $error = curl_error($curl);
            curl_close($curl);
            //Log::error('Error al enviar mensaje whatsapp: ' . $error);
            return response()->json(['error' => 'Error al enviar mensaje: ' . $error]);
        }

        curl_getinfo($curl, CURLINFO_HTTP_CODE);
        curl_close($curl);

        $response = json_decode($response, true);

        if (json_last_error() !== JSON_ERROR_NONE) {
            $error = json_last_error_msg();
            //Log::error('Error al decodificar respuesta whatsApp : ' . $error);
            return response()->json(['error' => 'Error al decodificar respuesta: ' . $error]);
        }
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);

        //Log::debug("Response al enviar mensaje whatsApp: " . json_encode($response));
        return response()->json(['message' => 'EVENT_RECEIVED']);
    }

    private function markMessageAsRead($message_id)
    {
        $data = array(
            "messaging_product" => "whatsapp",
            "status" => "read",
            "message_id" => "$message_id",
        );

        $curl = curl_init(self::SEND_MESSAGE_URL);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");
        curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
        curl_setopt($curl, CURLOPT_HTTPHEADER, $this->headers);

        $response = curl_exec($curl);

        curl_close($curl);
    }

    public function dispatchAction(Request $request): void
    {
        $data = $this->getUserResponse($request);
        $message = $data['message'];
        $date_id = $data['selectedDate'];
        $wasMatched = true;

        // Search entry user by phone provided from whatsapp
        $user = self::searchUserByPhone($data['phone']);

        // If entre user not found search a workshop by the phone provided from whatapp
        if (!$user) {
            $user = self:: searchUserByPhone($data['phone'], 'workshop');
        }

        //log::info('whatsApp dispatchAction message: ' . print_r($request, true));

        // If user and workshop isn't found stop the function
        if (!$user) return;

        switch ($message) {
            case self::CLIENT_CONFIRM:
                // Search if the user have and opened conversation
                if (!$this->checkIfClientHasAnOpenedConversation($data['phone'])) return;
                WorkShopController::sendRequestedDataToWorkShop($data['phone']);
                break;
            case self::CLIENT_REJECT:
                if (!$this->checkIfClientHasAnOpenedConversation($data['phone'])) return;
                ClientController::clientCancelService($data['phone']);
                break;
            case self::WORKSHOP_ACCEPT:
                if ($this->checkIfWorkshopWasAnswerDailyAvaiability($data['phone'])) return;
                WorkShopController::setWorkshopAsAvailable($data['phone']);
                break;
            case self::WORKSHOP_REJECT:
                if ($this->checkIfWorkshopWasAnswerDailyAvaiability($data['phone'])) return;
                WorkShopController::setWorkshopAsNotAvailable($data['phone']);;
//                WorkShopController::workShopDeniedService( $data['phone'] );
                break;
            case self::WORKSHOP_SEND_PROPOSAL:
                if (!$this->checkIfClientHasAnOpenedConversation($data['phone'], 'workshop')) return;
                WorkShopController::sendProposeIndications($data['phone']);
                break;
            case self::WORKSHOP_FINISHED_PROPOSAL:
                if (!$this->checkIfClientHasAnOpenedConversation($data['phone'], 'workshop')) return;
                $proposal = WorkShopProposal::find($data['conversation_id']);
                // TODO: Marcar la propuesta como finalizada
                ClientController::sendProposeToClient($proposal);
                break;
            case self::CLIENT_ACCEPT_PROPOSAL:
                if (!$this->checkIfClientHasAnOpenedConversation($data['phone'])) return;
                ClientController::sendServiceConfirmation($data['conversation_id']);
                break;
            case self::CLIENT_REJECT_PROPOSAL:
                if (!$this->checkIfClientHasAnOpenedConversation($data['phone'])) return;
                ClientController::sendServiceDenied($data['conversation_id']);
                break;
            default:
                $wasMatched = false;
        }

        // La expresión regular que coincide con el formato número
        $regex = '/^\d+$/';

        // Case any response match whit the options
        if (!$wasMatched) {
            // Case recieve a dateId
            if (!is_null($date_id)) {
                if (!$this->checkIfClientHasAnOpenedConversation($data['phone'], 'worshop')) return;
                WorkShopController::workshopFinishedProposeProcess($date_id);
            }
            // Case recieve a quantity
            if (preg_match($regex, $message)) {
                if (!$this->checkIfClientHasAnOpenedConversation($data['phone'], 'worshop')) return;
                WorkShopController::workshopSetAvailableDays($data['phone'], $message);
            }
        }
    }

    private function getUserResponse($request)
    {
        //Log::debug("Recibido en el webhook whatsApp " . print_r($request, true));
        //Log::debug($request->entry[0]);

        // Check if the entry is a message from the user
        if (isset($request->entry[0]['changes'][0]['value']['messages'])) {
            $entry = $request->entry[0]['changes'][0]['value']['messages'][0];
            $message = null;
            $id = null;
            $selectedDate = null;
            $conversation_id = null;
            $phone = $entry['from'];

            if (isset($entry['text']['body'])) {
                $message = $entry['text']['body'];
                $id = $entry['id'];
            } else if (isset($entry['interactive']['button_reply']['title'])) {
                $parts = explode('_', $entry['interactive']['button_reply']['id']);
                $conversation_id = end($parts);
                $message = $entry['interactive']['button_reply']['title'];
                $id = $entry['id'];
            } else if (isset($entry['interactive']['list_reply']['description'])) {
                $message = $entry['interactive']['list_reply']['description'];
                $selectedDate = $entry['interactive']['list_reply']['id'] ?? null;
                $id = $entry['id'];
            } else if (isset($entry['button']['text'])) {
                $message = $entry['button']['text'];
                $id = $entry['id'];
            }

            $this->markMessageAsRead($id);
        }

        return [
            'message' => $message ?? null,
            'selectedDate' => $selectedDate ?? null,
            'id' => $id ?? null,
            'phone' => $phone ?? null,
            'conversation_id' => $conversation_id ?? null
        ];
    }

    public static function searchUserByPhone(string|null $phone, string $type = 'user')
    {

        if (is_null($phone)) return null;

        //log::info('whatsApp searchUserByPhone phone: ' . $phone . $type);

        if ($type == 'workshop') {
            $user = User::has('workshop')->where('phone', 'LIKE', "%$phone%")->first();
        } else {
            $user = User::doesntHave('workshop')->where('phone', 'LIKE', "%$phone%")->first();
        }

        if (!$user) {
            $address = Address::where('phone', 'LIKE', "%$phone%")
                ->where('set_default', 1)
                ->first();

            $address->user->update(['phone' => $address->phone]);

            if ($type == 'workshop') {
                $user = $address->user()->has('workshop')->first();
            } else {
                $user = $address->user()->doesntHave('workshop')->first();
            }
        }

        return $user;
    }

    public function checkIfClientHasAnOpenedConversation(string|null $phone, string $type = 'user'): bool
    {
        if ($type == 'user') {
            $user = self::searchUserByPhone($phone);
            $conversation = $user->conversations()->wherePivot('workshop_id', null)->first();

            if (is_null($conversation)) {
                return false;
            }
        } else {
            $user = self::searchUserByPhone($phone, 'workshop');
            $conversations = UserHasConversation::where('workshop_id', $user->workshop->id)->count();

            if ($conversations <= 0) {
                return false;
            }
        }

        return true;
    }

    public function checkIfWorkshopWasAnswerDailyAvaiability($phone): bool
    {
        $user = self::searchUserByPhone($phone, 'workshop');

        return $user->workshop->is_available == 'DISPONIBLE' || $user->workshop->is_available == 'NO DISPONIBLE';
    }

    public function sendVerificationMessage(User $user)
    {
        //log::info('whatsApp sendVerificationMessage user: ' . print_r($user, true));
        $this->sendMessage([
            'messaging_product' => 'whatsapp',
            'to' => $user->phone,
            'type' => 'template',
            'template' => [
                'name' => 'confirmacion_movil',
                'language' => [
                    'code' => 'es'
                ],
                "components" => [
                    [
                        "type" => "body",
                        "parameters" => [
                            [
                                "type" => "text",
                                "text" => "$user->verification_code"
                            ]
                        ]
                    ],
                    [
                        "type" => "button",
                        "sub_type" => "url",
                        'index' => "0",
                        "parameters" => [
                            [
                                "type" => "text",
                                "text" => "$user->verification_code"
                            ]
                        ]
                    ]
                ],
            ],
        ]);
    }

    public function sendCreatedAccountMessage(User $user)
    {
        $url = URL::signedRoute(
            'verification.verify',
            ['id' => $user->id, 'hash' => $user->confirmation_code]
        );

        $fullUrl = $url;
        $baseUrl = config('app.url');
        $urlSegment = str_replace($baseUrl, "", $fullUrl);
        $fullUrl = $urlSegment;
        $baseUrl = "/email/verify/";
        $urlSegment = str_replace($baseUrl, "", $fullUrl);

        $this->sendMessage([
            'messaging_product' => 'whatsapp',
            'to' => $user->phone,
            'type' => 'template',
            'template' => [
                'name' => 'user_generados',
                'language' => [
                    'code' => 'es'
                ],
                'components' => [
                    [
                        'type' => 'button',
                        'sub_type' => 'url',
                        'index' => '0',
                        'parameters' => [
                            [
                                "type" => "text",
                                "text" => "$urlSegment"
                            ],
                        ]
                    ]
                ]
            ],
        ]);
    }
}