thephpleague / omnipay-sagepay

Sage Pay driver for the Omnipay PHP payment processing library
MIT License
54 stars 78 forks source link

Get request parameters from the payment gateway object? #88

Closed RyanHipkiss closed 7 years ago

RyanHipkiss commented 7 years ago

When I dump out $gateway it shows the httpClient parameter and the httpRequest. I can't seem to track down how to return the httpRequest object because its a protected parameter?

judgej commented 7 years ago

I think that may just be the way Omnipay 2.x works, with the HTTP client kept very much out of your hands.

I did put a getHttpClient() method on this gateway driver because I needed to do some debugging that needed access to the client. But in general for other gateway drivers, I'm really not sure how you get at the client.

If you just want to see the details of the parameters you can try $request->getData() before you send the request. It may not be exactly what you are looking for, but it may be close enough for your needs. The request would be something like $request = $gateway->authorize([///]);.

RyanHipkiss commented 7 years ago

My thought process is that I'm calling like so:

$response = $this->getPaymentGateway()->purchase([
            'amount'        => $this->getCart()->getTotal(),
            'currency'      => $this->getCurrency(),
            'card'          => [
                'FirstName' => '',
                'LastName'  => '',
                'Email'     => '',
                'BillingFirstName' => '',
                'BillingLastName' => '',
                'BillingAddress1' => '',
                'BillingAddress2' => '',
                'BillingAddress3' => '',
                'BillingCity' => '',
                'BillingPostcode' => '',
                'BillingCountry' => '',
                'ShippingAddress1' => '',
                'ShippingAddress2' => '',
                'ShippingAddress3' => '',
                'ShippingCity' => '',
                'ShippingPostcode' => '',
                'ShippingCountry' => ''
            ],
            'cancelUrl'     => URL . '/order-cancelled',
            'returnUrl'     => URL . '/order-success',
            'transactionId' => $this->getPaymentGateway()->getTestMode() ? uniqid() : $this->getOrder()->getId(),
            'description'   => $this->getOrder()->getId(),
        ])->send();

When using the card details, it would be ideal if I could call something like:

$response = $this->getPaymentGateway()->purchase([
            'amount'        => $this->getCart()->getTotal(),
            'currency'      => $this->getCurrency(),
            'card'          => [
                'FirstName' => $this->getPaymentGateway()->getRequest()->getParam('first_name'),
                'LastName'  => '',
                ...
            ],
            'cancelUrl'     => URL . '/order-cancelled',
            'returnUrl'     => URL . '/order-success',
            'transactionId' => $this->getPaymentGateway()->getTestMode() ? uniqid() : $this->getOrder()->getId(),
            'description'   => WEB_NAME . ' Order #' . $this->getOrder()->getId(),
        ])->send();

With: $this->getPaymentGateway()->getRequest()->getParam('first_name') being the way of retrieving the parameter.

I was hoping it was something built into Omnipay, as you're need to pass through the card details, so why not let them be accessible from the request?

judgej commented 7 years ago

The payment gateway at this stage does not have these details. For Sagepay Server, when calling purchase(), you are sending all the details have have collected from the user by other means to Sagepay. Then the response you get from that should (if all the personal details are valid) then ask you to redirect the user so they can enter their credit card details.

If there are any validation errors in this data, then the response will give you an error code and error message (just one, message, unfortunately) and you need to give the user an opportunity to correct that data and submit again,

It is only with the latest Sagepay REST APi that you can start a transaction without knowing all the user personal details and get them to enter them solely on the gateway form. I have a library for handling that, but it's not an Omnipay driver (yet).

RyanHipkiss commented 7 years ago

I've managed to do this by creating my own simple gateway - that utilises others through the omnipay/common. See example:

use \Omnipay\Common\AbstractGateway;

class Gateway extends AbstractGateway
{
    private $gateway;

    public function __construct(AbstractGateway $gateway)
    {
        $this->gateway = $gateway;
    }

    public function getHttpRequest()
    {
        return $this->gateway->httpRequest->request;
    }

    public function getParams()
    {
        return $this->gateway->httpRequest->request->all();
    }

    public function getGateway()
    {
        return $this->gateway;
    }

    public function getName()
    {
        return 'Omnipay Extension';
    }
}

Then I can call this like:

$gateway = new Gateway(Omnipay::create('SagePay_Direct'));

$gateway->getGateway()->purchase([
    'card' => [
        'FirstName' => $gateway->getParams()['invoice']['first_name'],
    ]
]);

Where $gateway->getParams() is an array of my values submitted from the form.

Hopefully this helps anyone in the future.

judgej commented 7 years ago

Glad you found a solution.

Just to be clear, Omnipay tries not to get involved in the creation and receipt of POST data from forms in the application. It tries to stick to the communications with the gateway only. There are a few frameworks that wrap around Omnipay to provide the additional layer (forms, form handler, persistent storage of transactions etc.) This is why what you were looking for (if I understand correctly) was not already built in.