Omnipay с сервером SagePay не принимает billingCountry

Я получаю следующую ошибку при попытке использовать SagePay Server (при распечатке ответа):

["data":protected]=>array(3) {
["VPSProtocol"]=>
string(4) "2.23"
["Status"]=>
string(7) "INVALID"
["StatusDetail"]=>
string(107) "The data in the BillingCountry field you supplied is an invalid length. Must be an ISO 3166-1 country code."

}

но я передаю значение «GB» в качестве BillingCountry, что является правильным (SagePay ожидает, что billingCountry будет в алфавитном порядке и не более 2 символов)

 ["card"]=>
    object(Omnipay\Common\CreditCard)#46 (1) {
      ["parameters":protected]=>
      object(Symfony\Component\HttpFoundation\ParameterBag)#48 (1) {
        ["parameters":protected]=>
        array(11) {
          ["email"]=>
          string(17) "[email protected]"
          ["billingFirstName"]=>
          string(3) "Joe"
          ["shippingFirstName"]=>
          string(3) "Joe"
          ["billingLastName"]=>
          string(6) "Bloggs"
          ["shippingLastName"]=>
          string(6) "Bloggs"
          ["billingAddress1"]=>
          string(9) "Address 1"
          ["billingAddress2"]=>
          string(9) "Address 2"
          ["billingCity"]=>
          string(4) "City"
          ["billingPostcode"]=>
          string(7) "AB1 1BA"
          ["billingCountry"]=>
          string(2) "GB"
          ["billingPhone"]=>
          string(13) "01234 567 890"
        }
      }

И это мой код:

$response = $this->gateway->Purchase(array(
        'description'=> 'Online order',
        'currency'=> 'GBP',
        'transactionId'=> mt_rand(99, 9999),
        'transactionReference' => 'test order',
        'amount'=> '1.00',
        'returnUrl' => 'http://www.test.com/returnURL/',
        'cancelUrl' => 'http://www.test.com/cancelURL/',
        'card' => array(
            'email' =>  '[email protected]',
            'clientIp' => '123.123.123.123',
            'firstName' => 'Joe',
            'LastName' => 'Bloggs',
            'billingAddress1' => 'Address 1',
            'billingAddress2' => 'Address 2',
            'billingCity' => 'City',
            'billingPostcode' => 'AB1 1BA',
            'billingCountry' => 'GB',
            'billingPhone' => '01234 567 890'
        )))->send();

Не могу разобраться, вроде все правильно. Кажется, я немного схожу с ума! Я упускаю совершенно очевидное?

Обновлено 28.07.2014: я пробовал разные вещи, включая отправку данных в разных форматах:

   $formInputData = array(
            'firstName' => 'Joe',
            'lastName' => 'Bloggs',
            'billingAddress1' => '88',
            'billingAddress2' => 'Address 2',
            'billingCity' => 'City',
            'billingPostcode' => '412',
            'billingCountry' => 'GB',
            'billingPhone' => '01234 567 890',
            'email' =>  '[email protected]',
            'clientIp' => '123.123.123.123'
        );


     $card = new CreditCard($formInputData);

     $transactionID = mt_rand(99, 9999);

     $response = $this->gateway->purchase(['amount' => '1.00', 'returnUrl' => 'http://www.example.com/return/', 'transactionId'=> $transactionID, 'description'=> 'Online order', 'transactionReference' => 'test order', 'currency'=> 'GBP', 'card' => $card])->send();

и это не имеет никакого значения.

Я также пытался отправить одни и те же данные (но с добавлением данных тестовой кредитной карты в параметр карты) как в SagePay Direct, так и в CardSave.

С SagePay Direct я получаю сообщение «Поле BillingCountry отсутствует в POST».

С CardSave транзакция проходит успешно, но я замечаю, что в поле страны указано «Н/Д», когда я смотрю на историю транзакций в своем CardSave.


person JoJo    schedule 21.07.2014    source источник
comment
Поля firstName и lastName — разве они не должны быть BillingFirstNames (да, во множественном числе) и BillingSurname?   -  person Jason    schedule 08.08.2014


Ответы (5)


Текущая версия omnipay/sagepay неправильно устанавливает штат США для платежных адресов за пределами США.

Если адрес находится за пределами США, он передает NULL для состояния, которое SagePay отклоняет. К сожалению, сообщения об ошибках SagePay часто относятся к соседнему полю, а не к фактической ошибке. Таким образом, он жалуется на то, что BillingCountry не установлен, хотя на самом деле это означает, что состояние не установлено.

В репозитории Git есть исправление для этой ошибки, но его нет в основных выпусках, поэтому Composer его пропускает.

Тем временем вы можете просто вручную установить состояние как пустую строку $data['card']['state'] = ''.

person drmonkeyninja    schedule 13.08.2014
comment
Спасибо, drmonkeyninja, я только что зашел сюда, чтобы добавить эту информацию в качестве обновления, так как сам наткнулся на нее! Это действительно устраняет проблему. К сожалению, ошибка SagePay вводила в заблуждение! - person JoJo; 14.08.2014
comment
Сообщения об ошибках SagePay часто могут сбивать с толку. Я обнаружил, что если он сообщает, что поле не установлено, это обычно означает, что соседнее поле содержит ошибку, которую необходимо проверить. - person drmonkeyninja; 14.08.2014
comment
Это полезно знать на будущее! - person JoJo; 14.08.2014
comment
Для тех, кто читает это, упомянутое исправление было в выпусках с января 2016 года. - person Jason; 09.08.2017

Может ли это быть проблемой чувствительности к регистру? Имеет ли значение изменение его на «BillingCountry»?

person user1112560    schedule 31.07.2014
comment
Увы, хотелось бы, чтобы это было так просто! Нет BillingCountry тоже не работает. Повторение ответа показывает, что billingCountry задан правильно (см. второй блок кода в моем исходном сообщении). billingCountry — правильное поле для использования в соответствии с документацией Omnipay. - person JoJo; 31.07.2014
comment
Я бы везде придерживался регистра букв в документации, например. Страной плательщика. SagePay может возвращать только одну ошибку за раз, а не кучу ошибок, если их много, поэтому ошибка, которую вы видите, может не быть первоначальной причиной сбоя. - person Jason; 08.08.2014

Поля firstName и lastName должны быть:

  • BillingFirstNames (да, во множественном числе)
  • БиллингФамилия

Свойства всех полей собраны в пакете gateway, который я написал в прошлом году:

https://github.com/academe/SagePay/blob/master/src/Academe/SagePay/Metadata/Transaction.php

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

Редактировать: это, вероятно, глупый ответ, если Omnipay переводит имена полей, поэтому не стесняйтесь игнорировать его. Моя голова была в SagePay, а не в Omnipay.

person Jason    schedule 08.08.2014
comment
Ха, нет, это хороший момент, но я опубликовал дополнительный ответ, чтобы показать, что OmniPay действительно переводит их, но спасибо :) - person JoJo; 08.08.2014
comment
Так теперь с этим разобрались? - person Jason; 09.08.2014
comment
Нет, это не так! Я не мог получить никакой помощи по этому поводу, поэтому я вернулся к CI-Merchant. Тогда у меня тоже были проблемы с этим (не помню, что именно, но это было написано теми же людьми, лол), поэтому в итоге я переключился на SagePay Direct с CI Merchant, который я делал раньше и знаю, что он работает. Мне нужно найти решение этой проблемы, поскольку оно может понадобиться будущим клиентам, но поскольку мне нужен был проект вживую, и я потратил на это много часов, мне пришлось сдаться! - person JoJo; 11.08.2014
comment
Я работаю с интерфейсом Sagepay сегодня и завтра. Я дам вам знать, как это происходит и как я справился с любыми проблемами. Я надеюсь, что это будет гладко, но с другими шлюзами Omnipay пока не так - проблема заключается в отсутствии документации (вам нужно прочитать некомментированный код, чтобы попытаться понять, как его использовать - даже пример приложения нуждается в докторской степени по микроязыку Silex, чтобы понять). Это прискорбно, но так оно и есть. - person Jason; 12.08.2014
comment
Ха получайте удовольствие! OmniPay великолепен тем, что позволяет легко переключаться между платежными шлюзами с минимальными изменениями кода, но недостатком этого является, как вы говорите, отсутствие документации или примеров. Я, вероятно, делаю что-то не так с моим кодом для сервера SagePay, но я не вижу дерева за деревьями на этом :) - person JoJo; 12.08.2014
comment
Вы пробовали пример приложения? Это может дать несколько подсказок. На данный момент я установил его здесь: acadweb.co.uk/helcim/demo Попробуйте, или, если вам не нравится вводить идентификатор поставщика (я не сохраняю все, что вы вводите), попробуйте установить его самостоятельно. Он должен работать на корневом пути домена без каких-либо ручных исправлений путей и URL-адресов. - person Jason; 13.08.2014
comment
Привет, Джейсон, пропустил этот комментарий. Оказывается, ошибка произошла из-за того, что BillingState был передан как NULL, поскольку он находился за пределами США. Простое исправление (см. принятый ответ) решает проблему. - person JoJo; 19.08.2014

Чтобы отвечать на комментарии/ответы Джейсона, Omnipay обрабатывает несколько платежных шлюзов и поэтому преобразует переданные поля в правильные имена полей, ожидаемые конкретным шлюзом. В случае SagePay это:

protected function getBaseAuthorizeData()
{
    $this->validate('amount', 'card', 'transactionId');
    $card = $this->getCard();

    $data = $this->getBaseData();
    $data['Description'] = $this->getDescription();
    $data['Amount'] = $this->getAmount();
    $data['Currency'] = $this->getCurrency();
    $data['VendorTxCode'] = $this->getTransactionId();
    $data['ClientIPAddress'] = $this->getClientIp();
    $data['ApplyAVSCV2'] = $this->getApplyAVSCV2() ?: 0;
    $data['Apply3DSecure'] = $this->getApply3DSecure() ?: 0;

    // billing details
    $data['BillingFirstnames'] = $card->getFirstName();
    $data['BillingSurname'] = $card->getLastName();
    $data['BillingAddress1'] = $card->getBillingAddress1();
    $data['BillingAddress2'] = $card->getBillingAddress2();
    $data['BillingCity'] = $card->getBillingCity();
    $data['BillingPostCode'] = $card->getBillingPostcode();
    $data['BillingState'] = $card->getBillingCountry() === 'US' ? $card->getBillingState() : null;
    $data['BillingCountry'] = $card->getBillingCountry();
    $data['BillingPhone'] = $card->getBillingPhone();

    // shipping details
    $data['DeliveryFirstnames'] = $card->getFirstName();
    $data['DeliverySurname'] = $card->getLastName();
    $data['DeliveryAddress1'] = $card->getShippingAddress1();
    $data['DeliveryAddress2'] = $card->getShippingAddress2();
    $data['DeliveryCity'] = $card->getShippingCity();
    $data['DeliveryPostCode'] = $card->getShippingPostcode();
    $data['DeliveryState'] = $card->getShippingCountry() === 'US' ? $card->getShippingState() : null;
    $data['DeliveryCountry'] = $card->getShippingCountry();
    $data['DeliveryPhone'] = $card->getShippingPhone();
    $data['CustomerEMail'] = $card->getEmail();

    return $data;
}
person JoJo    schedule 08.08.2014

Поскольку эта ошибка была исправлена, я также столкнулся с ошибкой. Однако ошибка, о которой говорилось выше, теперь исправлена.

В моем случае проблема возникла из-за использования «DeliveryXXXX» вместо «ShippingXXXX». Как только я изменил все экземпляры «Доставка» на «Доставка», я перестал получать сообщение об ошибке.

person mickburkejnr    schedule 27.05.2016