У кого-нибудь есть рабочий пример Omnipay и Sagepay Server или Sagepay Direct (с 3D Secure)?

Я изо всех сил пытаюсь заставить работать любой из них, а в Omnipay не так много документации. Я успешно использовал его для других платежных шлюзов, но не для Sagepay. Я пытаюсь интегрировать его в CodeIgniter, но могу работать с примерами в других фреймворках — я уже в отчаянии!


person JoJo    schedule 31.03.2015    source источник
comment
Только что узнал, что симулятор больше не поддерживается, что я и использовал для тестирования. Я еще не знаю, является ли это причиной моих проблем, так как теперь мне нужно настроить партнерскую учетную запись для тестирования, но подумал, что обновлю ее на случай, если кто-то еще столкнется с этим.   -  person JoJo    schedule 01.04.2015
comment
Здесь также есть ветка, посвященная протоколам Sagepay 3 и Omnipay github.com/thephpleague/omnipay- sagepay/issues/19   -  person JoJo    schedule 01.04.2015
comment
Эта ветка направила меня на правильный путь: github.com/thephpleague/omnipay/issues/255< /а>   -  person JoJo    schedule 07.04.2015
comment
Я постараюсь привести пример, когда у меня будет рабочий код, чтобы спасти других от трудностей, когда в настоящее время не хватает документации/примеров для Omnipay/Sagepay.   -  person JoJo    schedule 07.04.2015
comment
Как и обещал, я поделился своим кодом в ответ на этот вопрос. Возможно, это был не очень хороший вопрос (поэтому я предполагаю причину отрицательного голосования), но в настоящее время существует мало документации для Omnipay и нет примера для Sagepay.   -  person JoJo    schedule 08.04.2015


Ответы (2)


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

<?php 

use Omnipay\Omnipay;

class PaymentGateway  {

    //live details
    private $live_vendor = 'xxx';
    //test details
    private $test_vendor= 'xxx';

    //payment settings
    private $testMode = true;
    private $api_vendor = '';
    private $gateway = null;

    public function __construct()
    {
        parent::__construct();
        //setup api details for test or live
        if ($this->testMode) :
            $this->api_vendor = $this->test_vendor;
        else :
            $this->api_vendor = $this->live_vendor;
        endif;

        //initialise the payment gateway
        $this->gateway = Omnipay::create('SagePay_Server');
        $this->gateway->setVendor($this->api_vendor);
        $this->gateway->setTestMode($this->testMode);



    }


    public function initiate()
    {

        //get order details
        $orderNo = customFunctionToGetOrderNo(); //get the order number from your system however you store and retrieve it

        $params = array(
            'description'=> 'Online order',
            'currency'=> 'GBP',
            'transactionId'=> $orderNo,
            'amount'=> customFunctionToGetOrderTotal($orderNo)
        );


        $customer = customFunctionToGetCustomerDetails($orderNo);

        $params['returnUrl'] = '/payment-gateway-process/' . $orderNo .  '/'; //this is the Sagepay NotificationURL

        $params['card'] = array(
            'firstName' => $customer['billing_firstname'],
            'lastName' => $customer['billing_lastname'],
            'email' => $customer['billing_email'],
            'billingAddress1' => $customer['billing_address1'],
            'billingAddress2' => $customer['billing_address2'],
            'billingCity' => $customer['billing_town'],
            'billingPostcode' => $customer['billing_postcode'],
            'billingCountry' => $customer['billing_country'],
            'billingPhone' => $customer['billing_telephone'],
            'shippingAddress1' => $customer['delivery_address1'],
            'shippingAddress2' => $customer['delivery_address2'],
            'shippingCity' => $customer['delivery_town'],
            'shippingPostcode' => $customer['delivery_postcode'],
            'shippingCountry' => $customer['delivery_country']
        );


        try {
            $response = $this->gateway->purchase($params)->send();


            if ($response->isSuccessful()) :

                //not using this part

            elseif ($response->isRedirect()) :

                $reference = $response->getTransactionReference();
                customFunctionToSaveTransactionReference($orderNo, $reference);
                $response->redirect();

            else :
                //do something with an error
                echo $response->getMessage();

            endif;

        } catch (\Exception $e) {

            //do something with this if an error has occurred
            echo 'Sorry, there was an error processing your payment. Please try again later.';
        }



    }


    public function processPayment($orderNo)
    {

        $params = array(
            'description'=> 'Online order',
            'currency'=> 'GBP',
            'transactionId'=> $orderNo,
            'amount'=> customFunctionToGetOrderTotal($orderNo)
        );

        $customer = customFunctionToGetCustomerDetails($orderNo);


        $transactionReference = customFunctionToGetTransactionReference($orderNo);


        try {
            $response = $this->gateway->completePurchase(array(
                'transactionId' => $orderNo,
                'transactionReference' => $transactionReference,
            ))->send();

            customFunctionToSaveStatus($orderNo, array('payment_status' => $response->getStatus()));
            customFunctionToSaveMessage($orderNo, array('gateway_response' => $response->getMessage()));

            //encrypt it to stop anyone being able to view other orders
            $encodeOrderNo = customFunctionToEncodeOrderNo($orderNo);
            $response->confirm('/payment-gateway-response/' . $encodeOrderNo);

        } catch(InvalidResponseException $e) {
            // Send "INVALID" response back to SagePay.
            $request = $this->gateway->completePurchase(array());
            $response = new \Omnipay\SagePay\Message\ServerCompleteAuthorizeResponse($request, array());

            customFunctionToSaveStatus($orderNo, array('payment_status' => $response->getStatus()));
            customFunctionToSaveMessage($orderNo, array('gateway_response' => $response->getMessage()));

            redirect('/payment-error-response/');
        }



    }


    public function paymentResponse($encodedOrderNo)
    {
        $orderNo = customFunctionToDecode($encodedOrderNo);
        $sessionOrderNo = customFunctionToGetOrderNo(); 
        if ($orderNo != $sessionOrderNo) :
            //do something here as someone is trying to fake a successful order
        endif;
        $status = customFunctionToGetOrderStatus($orderNo);

        switch(strtolower($status)) :
            case 'ok' :
                customFunctionToHandleSuccess($orderNo);
            break;

            case 'rejected' :
            case 'notauthed' :
                //do something to handle failed payments
            break;

            case 'error' :
               //do something to handle errors

            break;

            default:

                //do something if it ever reaches here

        endswitch;


    }

 }
person JoJo    schedule 08.04.2015
comment
Я вижу, что номер заказа зашифрован в возвращаемом URL. Другой способ — не указывать какие-либо параметры для этого URL-адреса, а полагаться на то, что orderNo был сохранен в сеансе до вызова обработчика уведомлений. Редирект при ошибке тоже неправильный — здесь никакой редирект не сработает. Вместо этого вы должны вызвать $response->error('your url', 'your optional message');, и это вернет URL-адрес SagePay, который затем отправит пользователя на этот URL-адрес для вас. - person Jason; 07.07.2015

Вчера вечером я говорил об этом и разместил рабочие демо-скрипты на github здесь:

https://github.com/academe/OmniPay-SagePay-Demo

SagePay Direct — это разовое действие: OmniPay отправляет детали транзакции и получает немедленный ответ.

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

Все это есть в скриптах по ссылкам выше. authorize.php выполнит авторизацию. Отредактируйте это, чтобы использовать SagePay\Direct или SagePay\Server, чтобы увидеть, как это работает. Обработчик уведомлений для SagePay\Server — это sagepay-confirm.php, который в конечном итоге отправляет пользователя в final.php, где результат может быть прочитан из транзакции, хранящейся в базе данных.

Все сценарии прокомментированы и должны иметь смысл, но не стесняйтесь задавать дополнительные вопросы о них здесь или в системе отслеживания проблем этого репозитория github.

Однако я не пробовал SagePay\Direct с 3D-Secure. Сценарии могут нуждаться в некоторой модификации для поддержки этого, если предположить, что эта комбинация вещь.

person Jason    schedule 17.06.2015