SOAP + PHP | Ошибка: серверу не удалось обработать запрос. ---> Индекс находился за пределами массива - PullRequest
1 голос
/ 01 мая 2020

Я новичок PHP и впервые работаю с WebServices (SOAP) - интегрирую форму на целевой странице с CRM клиента. Поскольку это платформа с небольшим количеством клиентов, у меня есть только одна документация, и я жгу себя от этой ошибки, смеется.

Процесс отправки данных состоит из трех этапов: проверка (отправка ключа и пароля для генерации). токен), отправка (с использованием токена и отправка информации формы) и запрос подтверждения (возвращает зарегистрированный идентификатор клиента - не требуется). Часть проверки уже выполнена и работает, но при отправке формы выдается следующая ошибка:


    Fatal error: Uncaught SoapFault exception: [soap:Server] Server was unable to process request. ---> Index was outside the bounds of the array. in /home2/supera48/guaruja_root/crm4u/apiguaruja.php:58 Stack trace: #0 /home2/supera48/guaruja_root/crm4u/apiguaruja.php(58): SoapClient->__soapCall('PutLead', Array, Array) #1 {main} thrown in /home2/supera48/guaruja_root/crm4u/apiguaruja.php on line 58

После генерации токена я должен отправить данные формы в следующем формате:


        <soapenv:Header/>
        <soapenv:Body>
            <tem:PutLead>
                <tem:pessoa>
                    <tem:Nome>LEAD'S NAME</tem:Nome>
                    <tem:Email>LEAD@EMAIL.COM</tem:Email>
                    <tem:Telefone>999999999</tem:Telefone>
                    <tem:Observacoes>DETAILS</tem:Observacoes>
                </tem:pessoa>
                <tem:Key>TOKEN GENERATED IN VALIDATION</tem:Key>
            </tem:PutLead>
        </soapenv:Body>
    </soapenv:Envelope>

Если подтверждение подтверждено, оно возвращает мне идентификатор - например, так:

        <soap:Body>
            <PutLeadResponse xmlns="http://tempuri.org/">
                <PutLeadResult>ID DO LEAD</PutLeadResult>
            </PutLeadResponse>
        </soap:Body>
    </soap:Envelope>

Я беру и прикрепляю здесь код формы отправки и сценарий, который я запускаю:

ФОРМА:


    <form id="formulario" action="api.php" method="post">
    <div width="100%">
        <input type="text" id="nome" name="nome" class="campos" placeholder="Seu nome" required>
    </div>
    <div width="100%">
        <input type="text" id="email" name="email" class="campos" placeholder="Seu e-mail" required>
    <div width="100%">
        <input type="tel" id="telefone" name="telefone" class="campos" placeholder="Seu celular" required>
    </div>    
    <div width="100%" class="motivo">
        <select id ="observacoes" name="observacoes">
        <option value="Selecionar">----- Com o que podemos te ajudar?</option>
        <option value="Concurso e vestibular">Concurso e vestibular</option>
        <option value="Inteligência">Inteligência</option>
        <option value="Memória">Memória</option>
        <option value="Profissional">Profissional</option>
        <option value="Alzheimer">Alzheimer</option>
        <option value="Ansiedade">Ansiedade</option>
        <option value="Atenção">Atenção</option>
        <option value="Estresse">Estresse</option>
        <option value="Estudo">Estudo</option>
        </select>
    </div>
    <div width="100%" align="center">
        <button id="enviar" name="enviar" type="submit" class="btn-enviar">Enviar</button>
    </div>
    </form>

API. PHP


    <?php

    $nome = $_POST['nome'];
    $email = $_POST['email'];
    $telefone = $_POST['telefone'];
    $observacoes = $_POST['observacoes'];


    $client = new SoapClient('http://crm4u.azurewebsites.net/WS_Integracao.asmx?WSDL');

    $function = 'GetToken';

    $arguments= array('GetToken' => array(
                                            'ApiKey'   => XXXXXXX
                                          )
                     );

    $options = array('location' => 'http://crm4u.azurewebsites.net/WS_Integracao.asmx');

    $result = $client->__soapCall($function, $arguments, $options);

    $json = $result->GetTokenResult;
    $item = json_decode($json, true);

    print_r($item);

    $apikey = 'XXXXXXX';

    $apipassword = 'YYYYYYYY';

    $combinacao = $apikey."|".$apipassword."|".$item;

    $combinacaomd5 = md5($combinacao);

    $tokenfinal = $combinacaomd5."|".$apikey;

    print_r($tokenfinal);

    $argumentsPost = array('PutLead' => array(
                                'Pessoa'   => array(
                                        'Nome'   => $nome,
                                        'Email'   => $email,
                                        'Telefone'   => $telefone,
                                        'Observacoes'   => $observacoes
                                ),
                                'Key' => array(
                                    'ApiKey'   => $tokenfinal
                                  )
                                )
                            );

    $optionsPost = array('location' => 'http://crm4u.azurewebsites.net/WS_Integracao.asmx');

    $functionPost = 'PutLead';

    $resultPost = $client->__soapCall($functionPost, $argumentsPost, $optionsPost);

    ?>

Ошибка, согласно сценарию, находится на предпоследней строке (58). Я не знаю, что я могу сделать по-другому, или я делаю неправильно, но я подозреваю, что это может быть связано с тем, что "Person" находится внутри "PutLead". Несмотря на это, я уже тестировал $ functionPost, вызывая «Person», но ошибка не исчезла.

Кто-нибудь знает, как я могу решить эту проблему?

Спасибо!

Ответы [ 2 ]

0 голосов
/ 02 мая 2020

Нет lol , потому что сервис работает как задумано. Давайте выясним, почему ваш soap клиент выдает эту ошибку.

Сначала взглянем на определения в wsdl. Для метода PutLead параметр определяется следующим образом.

<s:element name="PutLead">
    <s:complexType>
        <s:sequence>
            <s:element minOccurs="0" maxOccurs="1" name="pessoa" type="tns:Lead"/>
            <s:element minOccurs="0" maxOccurs="1" name="Key" type="s:string"/>
        </s:sequence>
    </s:complexType>
</s:element>

Для правильного выполнения метода веб-службы PutLead определен комплексный тип PutLead, который имеет элементы pessoa и Key. Элемент pessoa определяется как tns: Lead type. Элемент Key представляет собой простую строку. Определение сложного типа можно рассматривать как объект значения данных php. простой объект, который содержит данные. Итак, давайте определим объект php для комплексного типа PutLead.

<?php
declare(strict_types=1);
namespace Application\Model;

class PutLead
{
    protected ?Lead $pessoa;
    protected ?string $Key;

    public function getPessoa(): ?Lead
    {
        return $this->pessoa;
    }

    public function setPessoa(Lead $pessoa): self
    {
        $this->pessoa = $pessoa;
        return $this;
    }

    public function getKey(): ?string
    {
        return $this->Key();
    }

    public function setKey(string $key): self
    {
        $this->Key = $key;
        return $this;
    }
}

Этот объект значения php распознает все определения из определения комплексного типа wsdl PutLead. Два свойства могут встречаться в точности ноль или один раз. Свойство Key является строковым типом, а свойство pessoa может быть объектом Lead.

Что говорит wsdl об определении tns:Lead?

<s:complexType name="Lead">
    <s:sequence>
        <s:element minOccurs="1" maxOccurs="1" name="Id" type="s:int"/>
        <s:element minOccurs="0" maxOccurs="1" name="Nome" type="s:string"/>
        <s:element minOccurs="0" maxOccurs="1" name="Email" type="s:string"/>
        <s:element minOccurs="0" maxOccurs="1" name="Telefone" type="s:string"/>
        <s:element minOccurs="0" maxOccurs="1" name="Observacoes" type="s:string"/>
        <s:element minOccurs="0" maxOccurs="1" name="Campanha" type="s:string"/>
        <s:element minOccurs="1" maxOccurs="1" name="Unidade_Id" type="s:int"/>
    </s:sequence>
</s:complexType>

Здесь мы можем видите, почему ваш клиент выдает ошибку soap с сообщением object has no 'Id' property. Сложный тип pessoa должен содержать свойство Id и свойство Unidade_Id. Оба не были определены, поэтому веб-служба выдает ошибку.

Объект значения php должен выглядеть следующим образом:

<?php
declare(strict_types=1);
namespace Application\Model;

class Lead
{
    protected int $Id;
    protected ?string $Nome;
    protected ?string $Email;
    protected ?string $Telefone;
    protected ?string $Observacoes;
    protected ?string $Campanha;
    protected int $Unidade_Id;

    public function getId(): int
    {
        return $this->Id;
    }

    public function setId(int $id): self
    {
        $this->Id = $id;
        return $this;
    }

    public function getNome(): ?string
    {
        return $this->Nome;
    }

    public function setNome(string $nome): self
    {
        $this->Nome = $nome;
        return $this;
    }

    public function getEmail(): ?string
    {
        return $this->Email;
    }

    public function setEmail(string $email): self
    {
        $this->Email = $email;
        return $this;
    }

    public function getTelefone(): ?string
    {
        return $this->Telefone;
    }

    public function setTelefone(string $telefone): self
    {
        $this->Telefone = $telefone;
        return $this;
    }

    public function getObservacoes(): ?string
    {
        return $this->Observacoes;
    }

    public function setObservacoes(string $observacoes): self
    {
        $this->Observacoes = $observacoes;
        return $this;
    }

    public function getCampanha(): ?string
    {
        return $this->Campanha;
    }

    public function setCampanha(string $campanha): self
    {
        $this->Campanha = $campanha;
        return $this;
    }

    public function getUnidadeId(): int
    {
        return $this->Unidade_Id;
    }

    public function setUnidadeId(int $unidadeId): self
    {
        $this->Unidade_Id = $unidadeId;
        return $this;
    }
}

Показанный выше объект значения php отражает в точности tns:Lead определение сложного типа. С двумя определенными php объектами значения вы можете выполнить запрос PutLead.

<?php
declare(strict_types=1);
namespace Application;

use Application\Model\Lead;
use Application\Model\PutLead;
use SoapClient;
use SoapFault;

try {
    $wsdl = 'http://crm4u.azurewebsites.net/WS_Integracao.asmx?WSDL';
    $options = [
        'exceptions' => true,
        'soap_version' => SOAP_1_1,
        'trace' = true,
    ];

    $client = new SoapClient($wsdl, $options);

    // request for a valid key
    $key = ...;

    // the following variables $id, $nome, $email, $telefone, $observacoes
    // $campanha and $unidadeId must be declared before the following init
    $pessoa = (new Lead())
        ->setId($id)
        ->setNome($nome)
        ->setEmail($email)
        ->setTelefone($telefone)
        ->setObservacoes($observacoes)
        ->setCampanha($campanha)
        ->setUnidadeId($unidadeId)

    $putLead = (new PutLead())
        ->setPessoa($pessoa)
        ->setKey($key);

    $result = $client->PutLead($putLead);
} catch (SoapFault $fault) {
    var_dump($fault);
}

Как вы можете видеть, класс SoapClient инициализируется с помощью адреса wsdl и некоторых опций, которые заставляют soap клиент для выдачи исключений как SoapFault экземпляров. Кроме того, вы можете отслеживать запрос и ответ с помощью SoapClient::__getLastRequest() и SoapClient::__getLastResponse(). Если клиент был инициализирован без выдачи ошибки, вы можете использовать эти методы, чтобы просмотреть последний отправленный запрос и последний полученный ответ, если таковой был получен. Это может быть очень полезно при отладке всего процесса.

0 голосов
/ 01 мая 2020

Я заметил, что "Pessoa" в WDSL был строчным, и я изменил его в своем коде. Теперь я получил это:

<?php

    $nome = $_POST['nome'];
    $email = $_POST['email'];
    $telefone = $_POST['telefone'];
    $observacoes = $_POST['observacoes'];


    $client = new SoapClient('http://crm4u.azurewebsites.net/WS_Integracao.asmx?WSDL');

    $function = 'GetToken';

    $arguments= array('GetToken' => array(
                                            'ApiKey'   => XXXXXXX
                                          )
                     );

    $options = array('location' => 'http://crm4u.azurewebsites.net/WS_Integracao.asmx');

    $result = $client->__soapCall($function, $arguments, $options);

    $json = $result->GetTokenResult;
    $item = json_decode($json, true);

    print_r($item);

    $apikey = 'XXXXXXX';

    $apipassword = 'YYYYYYYY';

    $combinacao = $apikey."|".$apipassword."|".$item;

    $combinacaomd5 = md5($combinacao);

    $tokenfinal = $combinacaomd5."|".$apikey;

    print_r($tokenfinal);

    $argumentsPost = array('PutLead' => array(
                                'pessoa'   => array(
                                        'Nome'   => $nome,
                                        'Email'   => $email,
                                        'Telefone'   => $telefone,
                                        'Observacoes'   => $observacoes
                                ),
                                'Key' => array(
                                    'ApiKey'   => $tokenfinal
                                  )
                                )
                            );

    $optionsPost = array('location' => 'http://crm4u.azurewebsites.net/WS_Integracao.asmx');

    $functionPost = 'PutLead';

    $resultPost = $client->__soapCall($functionPost, $argumentsPost, $optionsPost);

    ?>

Теперь ошибка изменилась, смеется: Fatal error: Uncaught SoapFault exception: [Client] SOAP-ERROR: Encoding: object has no 'Id' property in /home2/supera48/guaruja_root/crm4u/apiguaruja.php:56 Stack trace: #0 /home2/supera48/guaruja_root/crm4u/apiguaruja.php(56): SoapClient->__soapCall('PutLead', Array, Array) #1 {main} thrown in /home2/supera48/guaruja_root/crm4u/apiguaruja.php on line 56

У кого-нибудь есть догадки?

Спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...