OnAnswerInboundWebHook.php 5.31 KB
<?php


namespace NexmoBundle\WebHook;

use AppBundle\Entity\AdminUser;
use AppBundle\Entity\OpentokSessionTypes;
use AppBundle\Entity\Patient;
use AppBundle\Entity\VoiceCall;
use AppBundle\Repository\PatientRepository;
use AppBundle\Service\Manager\AdminUserManager;
use AppBundle\Service\Manager\PatientManager;
use JMS\DiExtraBundle\Annotation\Inject;
use JMS\DiExtraBundle\Annotation\InjectParams;
use JMS\DiExtraBundle\Annotation\Service;
use NexmoBundle\Manager\InboundCallManager;
use NexmoBundle\VoiceCall\VoiceCallStatus;
use OpenTokBundle\Pool\GlobalAdminOpenTokPool;
use OpenTokBundle\Pool\OpenTokPoolFactory;

/**
 * Class OnAnswerInboundWebHook
 * @Service("nexmo.webhooks.answer_inbound", autowire=true, public=true)
 */
class OnAnswerInboundWebHook extends NexmoWebHookHandler
{
    /**
     * @var InboundCallManager
     */
    private $callManager;

    /**
     * @var AdminUserManager
     */
    private $adminUserManager;

    /**
     * @var PatientManager
     */
    private $patientManager;

    /**
     * @var GlobalAdminOpenTokPool
     */
    private $opentokPool;

    /**
     * @param InboundCallManager $manager
     * @InjectParams({
     *     "manager" = @Inject("nexmo.manager.inbound_call", required=false)
     * })
     */
    public function setInboundVoiceCallManager(InboundCallManager $manager)
    {
        $this->callManager = $manager;
    }

    /**
     * @param AdminUserManager $manager
     * @InjectParams({
     *     "manager" = @Inject("spoke.manager.admin_user", required=false)
     * })
     */
    public function injectUserManager(AdminUserManager $manager)
    {
        $this->adminUserManager = $manager;
    }

    /**
     * @param PatientManager $manager
     * @InjectParams({
     *     "manager" = @Inject("spoke.manager.patient", required=false)
     * })
     */
    public function injectPatientManager(PatientManager $manager)
    {
        $this->patientManager = $manager;
    }

    /**
     * @param OpenTokPoolFactory $factory
     * @throws \Exception
     * @InjectParams({
     *     "factory" = @Inject("opentok_pool_factory", required=false)
     * })
     */
    public function injectAdminPool(OpenTokPoolFactory $factory)
    {
        $this->opentokPool = $factory->get(OpentokSessionTypes::ADMIN_POOL);
    }


    /**
     * @return VoiceCall|object|null
     * @throws \Exception
     */
    private function buildVoiceCallFromRequest()
    {
        $uuid = $this->getRequestParam('uuid');
        $fromNumber = $this->getRequestParam('from');
        $conversationId = $this->getRequestParam('conversation_uuid');

        $voiceCall = $this->callManager->findOneByUUID($uuid);
        // no existing voice call with uuid, create one
        if (!$voiceCall) {
            $voiceCall = $this->callManager->create();
        }

        $voiceCall->setUpdatedAt(new \DateTime());
        $voiceCall->setConversationUuid($conversationId);
        $voiceCall->setFromNumber($fromNumber);
        $voiceCall->setUuid($uuid);

        return $voiceCall;
    }

    protected function processRequest()
    {
        $voiceCall = $this->buildVoiceCallFromRequest();
        $this->logInfo("Inbound call answer url. From number: {$voiceCall->getFromNumber()}");

        // find mapped member based on the contact number
        // we can only map out one patient to this voice call log
        // for multiple patients having same contact number will be manually managed
        $patients = $this->patientManager->findByContactNumber($voiceCall->getFromNumber());
        /** @var Patient $actor */
        $actor = 1 == count($patients) ? $patients[0] : null;
        if ($actor) {
            $voiceCall->setActor($actor);
        }

        // as per Jason discussion, we will always forward the call to the default number FOR march 15
        $proxyNumber = $this->currentCobrand->getNexmo()->defaultNumber;

        // find AdminUser who owns this proxyNumber, can only handle one recipient
        $adminUsers = $this->adminUserManager->findByContactNumber($proxyNumber);
        /** @var AdminUser $adminRecipient */
        $adminRecipient = 1 == count($adminUsers) ? $adminUsers[0] : null;
        if ($adminRecipient) {
            $voiceCall->setRecipient($adminRecipient);
        }

        $voiceCall->setToNumber($proxyNumber);

        try {
            $this->callManager->beginTransaction();
            $this->callManager->save($voiceCall);
            $this->callManager->commit();

            // build out response data for connecting to proxy number
            $this->responseData = [
                [
                    "action" => "connect",
                    // redirect to advocate or company default number
                    "endpoint" => [[
                        "type" => "phone",
                        "number" => $proxyNumber
                    ]],
                    "timeout" => 45
                ]
            ];
        } catch (\Exception $exception) {
            $appName = $this->currentCobrand ? $this->currentCobrand->getApp()->getName() : null;
            $this->callManager->rollback();
            $this->sentry->captureException($exception);

            // failure
            $this->responseData = [[
                "action" => "talk",
                "text" => "Thank you for calling ${appName}, we are currently experiencing technical problems."
            ]];
        }
    }
}