Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with SagePay Forms #130

Closed
1stChoiceSpares opened this issue Mar 27, 2019 · 14 comments
Closed

Issue with SagePay Forms #130

1stChoiceSpares opened this issue Mar 27, 2019 · 14 comments
Labels

Comments

@1stChoiceSpares
Copy link

Sorry I am unable to understand your documentation. I have setup a function with the following code:

$gateway = OmniPay::create('SagePay\Form')->initialize([
            'vendor' => 'OurVendorID',
            'testMode' => true,
            'encryptionKey' => 'OurEncryptionKey',
        ]);
        $response = $gateway->purchase([
            'amount' => '99.99',
            'currency' => 'GBP',
            'transactionId' => 'FC-TEST01',
            'description' => 'Pizzas for everyone at PHPNE',
            'returnUrl' => 'https://example.com/success',
            'failureUrl' => 'https://example.com/failure'
        ]);

        $result = $gateway->completePurchase()->send();

This just results in an error about crypt:
Missing or invalid "crypt" parameter

Instead I then use the following from your documentation:

$crypt = $_GET['crypt']; // or supplied by your framework
$result = $gateway->completeAuthorize(['crypt' => $crypt])->send();

Again this gives an error relating to Crypt:
Undefined index: crypt

So then I try switching in code found in the test functions:

$crypt = '@BE1508740B97BEC235E9E8474168E3D4DEAD71C1395CDAC1A24F4784A71135AE797F5451F48EB2EAF5669EB3F6953F466FC3A03E5815E607C4DD18C03D7BDD61D176DB4DF131DC0F02DFC5145FFBA841651641BDAA405E72F4EF8849C2B2FD1F08763E3E66EAF3C479429A92014C7B8316F3B446BA09D28A821EE81C243E3DDD6F4C1F41D6ADEAC74D42B221645ADCC69E2F22ECDCAA010F63CCD02EAF0CE20F98439DAC7C31E528A7574656191150C1CC6CCD9FBEFCBFC9B34029FAB8F62DBC1C1618628FF0529B4E66B8AB857A79CC2FD0F14299A3505D22F964322755E6190EDD5BD42066D88154F950585236B6A2951D28BDA474E3FB17638DAA2F6304EAEA3AB9513DD0604D447000208D55DA4FDF544BEE00B5744170C1FC1E6DC6AADA07BEF6EB1FA46C14B99C3371491816A5C2CF7E03EDF6D58142767F7550DFFFE634FA56532605768FFEC1B20BEC32177816DDAB804149E9A301E495F11568F58896E90B1AC5776C2F12CE578955292F640A1E81213AAAA7856CD622FC241C65AC08215B94F933FD47050E0CFB2BFA85D7570A9D401B2366001AA377C50825B6D3893BDEC46D87F9121EC39DBF948F69399B8E842635556C7BC08E2E0C85CFA3EA2F9E4582ABDB3EB9668C83EDC34A5862F3CBC1A10935A189493D42D5C3FE4AF2BFF29B8464934B221B5A56B407F4E638B6766E6C706996A0252F2DDB30AFC8C1DA65F89987F4A9AA317BB104ED42F749DE3A43C39C515B67B3EA619D4092843DA551EEFC22CF672F53F753DEB93F1E8487BFE89C0100AFB9799238B24E523B0D6D53F824DEC0F6897F97FA507648D13276841B3B2E98030CBCD8E04F5E2C06C57BCC6F6C346440E620718F8877FFE969';

$result = $gateway->completeAuthorize(['crypt' => $crypt])->send();

This then results in a blank page.

I fee the documentation is missing some vital parts to get this working. Could you provide me with a basic example function that will redirect to SagePay forms?

@judgej
Copy link
Member

judgej commented Mar 27, 2019

On that last section, what does $result contain? Is it the result of the transaction? You may be getting an exception thrown if the $crypt value is not valid for your encryption key.

Okay, the process is:

  1. That first section of code you posted will create a $result that is a redirect object. Use it to redirect to Sage Pay. The redirect will be a POST, and a very quick and dirty way of doing that will be to use $result->redirect(); This will output a self-POSTing form and send the user off to Sage Pay to enter their card details.
  2. The next part of the code is to handle the result when the user returns from Sage Pay. It will be in a different endpoint on your site. Set up the $gateway object in the same way as before then execute the code to check the result. When the user returns from Sage Pay the URL you supplied as the return URL will have the crypt parameter. Just issue $result = $gateway->completeAuthorize()->send(); as a minimum and the gateway driver will attempt to find the crypt parameter for you. You can pass it in as a parameter just in case you have a framework that gets in the way, but normally it should work.

send() in step 1 does not actually send anything remotely, but it gives you can object with all the details of the redirect that you need to execute to send the user off.

send() in step 2 does not actually send anything either, but reads the payment result from the current URL and decodes it to give you the result of the payment.

The user flow is not explained fully, I agree, so it should be read in conjunction with the description of the flow in the Sage Pay documentation. Feel free to add to the documentation if you think it will help others, once you are familiar with what it is that is missing. I hope the above helps.

@judgej
Copy link
Member

judgej commented Mar 27, 2019

Another way to do the redirect could be a bit of PHP code like this, which will give the user a button to press to go to the Sage Pay site:

echo '<form method="'.$result->getRedirectMethod().'" action="'.$result->getRedirectUrl().'" accept-charset="UTF-8">';
foreach ($result->getRedirectData() as $name => $value) {
    echo '<input type="hidden" name="'.$name.'" value="'.htmlspecialchars($value).'" />';
}
echo '<p><button type="submit">Go To Sage Pay</button></p>';
echo '</form>';

The above form could POST to an iframe if you like. It's completely your choice, and Omnipay does not try to limit how you can set up your front end. The above would work with most Omnipay drivers for other gateways that redirect the user to their site to enter card details. Sage Pay form needs the user to enter details into a form hosted by Sage Pay. They do have a token-based JavaScript API too (Sage Pay Pi) but that is handled by a different driver.

@1stChoiceSpares
Copy link
Author

Thanks for your response, I believe I might be having an issue with the creation of the 'crypt'.

I have tried to add:

$response->redirect();

But this gives me the error:
'This response does not support redirection.'

How do you go about generating the crypt value? I did find the following code:
$crypt = openssl_encrypt($response, 'aes-128-cbc', $key, OPENSSL_RAW_DATA, $key);

$key being my encryption key but I the error is along the lines of the $response must be a string.

Sorry about this, payment methods confuse me to no end!

@1stChoiceSpares
Copy link
Author

1stChoiceSpares commented Mar 27, 2019

I have the out put of my result here, any thoughts on where I am going wrong? Thanks:

Omnipay\SagePay\Message\Response Object ( [request:protected] => Omnipay\SagePay\Message\Form\CompletePurchaseRequest Object ( [service:protected] => [VPSProtocol:protected] => 3.00 [liveEndpoint:protected] => https://live.sagepay.com/gateway/service [testEndpoint:protected] => https://test.sagepay.com/gateway/service [parameters:protected] => Symfony\Component\HttpFoundation\ParameterBag Object ( [parameters:protected] => Array ( [vendor] => REDACTED [testMode] => [referrerId] => [language] => [useOldBasketFormat] => [exitOnResponse] => [apply3DSecure] => [useAuthenticate] => [accountType] => [encryptionKey] => REDACTED [cryptx] => @BE1508740B97BEC235E9E8474168E3D4DEAD71C1395CDAC1A24F4784A71135AE797F5451F48EB2EAF5669EB3F6953F466FC3A03E5815E607C4DD18C03D7BDD61D176DB4DF131DC0F02DFC5145FFBA841651641BDAA405E72F4EF8849C2B2FD1F08763E3E66EAF3C479429A92014C7B8316F3B446BA09D28A821EE81C243E3DDD6F4C1F41D6ADEAC74D42B221645ADCC69E2F22ECDCAA010F63CCD02EAF0CE20F98439DAC7C31E528A7574656191150C1CC6CCD9FBEFCBFC9B34029FAB8F62DBC1C1618628FF0529B4E66B8AB857A79CC2FD0F14299A3505D22F964322755E6190EDD5BD42066D88154F950585236B6A2951D28BDA474E3FB17638DAA2F6304EAEA3AB9513DD0604D447000208D55DA4FDF544BEE00B5744170C1FC1E6DC6AADA07BEF6EB1FA46C14B99C3371491816A5C2CF7E03EDF6D58142767F7550DFFFE634FA56532605768FFEC1B20BEC32177816DDAB804149E9A301E495F11568F58896E90B1AC5776C2F12CE578955292F640A1E81213AAAA7856CD622FC241C65AC08215B94F933FD47050E0CFB2BFA85D7570A9D401B2366001AA377C50825B6D3893BDEC46D87F9121EC39DBF948F69399B8E842635556C7BC08E2E0C85CFA3EA2F9E4582ABDB3EB9668C83EDC34A5862F3CBC1A10935A189493D42D5C3FE4AF2BFF29B8464934B221B5A56B407F4E638B6766E6C706996A0252F2DDB30AFC8C1DA65F89987F4A9AA317BB104ED42F749DE3A43C39C515B67B3EA619D4092843DA551EEFC22CF672F53F753DEB93F1E8487BFE89C0100AFB9799238B24E523B0D6D53F824DEC0F6897F97FA507648D13276841B3B2E98030CBCD8E04F5E2C06C57BCC6F6C346440E620718F8877FFE969 ) ) [httpClient:protected] => Omnipay\Common\Http\Client Object ( [httpClient:Omnipay\Common\Http\Client:private] => Http\Adapter\Guzzle6\Client Object ( [client:Http\Adapter\Guzzle6\Client:private] => GuzzleHttp\Client Object ( [config:GuzzleHttp\Client:private] => Array ( [handler] => GuzzleHttp\HandlerStack Object ( [handler:GuzzleHttp\HandlerStack:private] => Closure Object ( [static] => Array ( [default] => Closure Object ( [static] => Array ( [default] => GuzzleHttp\Handler\CurlMultiHandler Object ( [factory:GuzzleHttp\Handler\CurlMultiHandler:private] => GuzzleHttp\Handler\CurlFactory Object ( [handles:GuzzleHttp\Handler\CurlFactory:private] => Array ( ) [maxHandles:GuzzleHttp\Handler\CurlFactory:private] => 50 ) [selectTimeout:GuzzleHttp\Handler\CurlMultiHandler:private] => 1 [active:GuzzleHttp\Handler\CurlMultiHandler:private] => [handles:GuzzleHttp\Handler\CurlMultiHandler:private] => Array ( ) [delays:GuzzleHttp\Handler\CurlMultiHandler:private] => Array ( ) ) [sync] => GuzzleHttp\Handler\CurlHandler Object ( [factory:GuzzleHttp\Handler\CurlHandler:private] => GuzzleHttp\Handler\CurlFactory Object ( [handles:GuzzleHttp\Handler\CurlFactory:private] => Array ( ) [maxHandles:GuzzleHttp\Handler\CurlFactory:private] => 3 ) ) ) [parameter] => Array ( [$request] => [$options] => ) ) [streaming] => GuzzleHttp\Handler\StreamHandler Object ( [lastHeaders:GuzzleHttp\Handler\StreamHandler:private] => Array ( ) ) ) [parameter] => Array ( [$request] => [$options] => ) ) [stack:GuzzleHttp\HandlerStack:private] => Array ( [0] => Array ( [0] => Closure Object ( [parameter] => Array ( [$handler] => ) ) [1] => prepare_body ) ) [cached:GuzzleHttp\HandlerStack:private] => ) [allow_redirects] => Array ( [max] => 5 [protocols] => Array ( [0] => http [1] => https ) [strict] => [referer] => [track_redirects] => ) [http_errors] => 1 [decode_content] => 1 [verify] => 1 [cookies] => [headers] => Array ( [User-Agent] => GuzzleHttp/6.3.3 curl/7.60.0 PHP/7.1.20 ) ) ) ) [requestFactory:Omnipay\Common\Http\Client:private] => Http\Message\MessageFactory\GuzzleMessageFactory Object ( ) ) [httpRequest:protected] => Symfony\Component\HttpFoundation\Request Object ( [attributes] => Symfony\Component\HttpFoundation\ParameterBag Object ( [parameters:protected] => Array ( ) ) [request] => Symfony\Component\HttpFoundation\ParameterBag Object ( [parameters:protected] => Array ( ) ) [query] => Symfony\Component\HttpFoundation\ParameterBag Object ( [parameters:protected] => Array ( ) ) [server] => Symfony\Component\HttpFoundation\ServerBag Object ( [parameters:protected] => Array ( [REDIRECT_STATUS] => 200 [HTTP_HOST] => dev.1stchoice.lan [HTTP_CONNECTION] => keep-alive [HTTP_CACHE_CONTROL] => max-age=0 [HTTP_UPGRADE_INSECURE_REQUESTS] => 1 [HTTP_USER_AGENT] => Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36 [HTTP_DNT] => 1 [HTTP_ACCEPT] => text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 [HTTP_REFERER] => http://dev.1stchoice.lan/sagecheckout/confirm [HTTP_ACCEPT_ENCODING] => gzip, deflate [HTTP_ACCEPT_LANGUAGE] => en-US,en;q=0.9 [HTTP_COOKIE] => _ga=GA1.2.985968222.1545147037; cookieconsent_status=dismiss; remember_web_59ba36addc2b2f9401580f014c7f58ea4e30989d=eyJpdiI6Iit4Y0JyVjVYNGpHQUxIb01ZbzR6Smc9PSIsInZhbHVlIjoibjFEeEZQSmZveHVwXC9DdGNXaTVaNHI2eFJscGNXdkxDdlJUaVVXYXRYYUw4ditKQ3d0VUxtUWo5ZmdmRzg0V1JYMU0rc3BLYVRzaUFqbHVvRit5ZVV4blQxa09oM2RZdXRpdXpcL1ZwalVFOD0iLCJtYWMiOiJlMGJkNTI2ODlmN2IzYzcxNGNlN2U2MWZjMGU1OTNhNDczODIyM2U3ODY0MDA3YzkzMWQxYTQ1NTNkYTMwOTkwIn0%3D; _gid=GA1.2.1755130210.1553515611; _gat=1; 1stchoice_session=eyJpdiI6InJFS3U5NUNIUFMwbm8wTnkzM1ZKZnc9PSIsInZhbHVlIjoiSWhOOGFCS3R3NVwvVTlMSUFSWTVaMUthc05UUXVJYTVvdnR1dGc3V2xcL2tzcWJaVWN6ekFMb3BmSzBcL2x0TzQzVyIsIm1hYyI6ImVhNTA1ZDlmY2ZlMzIyMDRkMjdhYTRlZjhjN2JhMzE1NjIwOGQyOGFmY2I4NDYxYzExOTk2ZTQ0ZjIzOTQ1OTQifQ%3D%3D [PATH] => /usr/bin:/bin:/usr/sbin:/sbin [SERVER_SIGNATURE] => [SERVER_SOFTWARE] => Apache/2.2.34 (Unix) mod_wsgi/3.5 Python/2.7.13 PHP/7.1.20 mod_ssl/2.2.34 OpenSSL/1.0.2o DAV/2 mod_fastcgi/mod_fastcgi-SNAP-0910052141 mod_perl/2.0.9 Perl/v5.24.0 [SERVER_NAME] => dev.1stchoice.lan [SERVER_ADDR] => 10.1.10.19 [SERVER_PORT] => 80 [REMOTE_ADDR] => 10.1.10.19 [DOCUMENT_ROOT] => /Applications/MAMP/htdocs/1stchoice/staging/public_html [SERVER_ADMIN] => [email protected] [SCRIPT_FILENAME] => /Applications/MAMP/htdocs/1stchoice/staging/public_html/index.php [REMOTE_PORT] => 64998 [REDIRECT_URL] => /sagepay/create/FC-569882E [GATEWAY_INTERFACE] => CGI/1.1 [SERVER_PROTOCOL] => HTTP/1.1 [REQUEST_METHOD] => GET [QUERY_STRING] => [REQUEST_URI] => /sagepay/create/FC-569882E [SCRIPT_NAME] => /index.php [PHP_SELF] => /index.php [REQUEST_TIME_FLOAT] => 1553709168.31 [REQUEST_TIME] => 1553709168 [argv] => Array ( ) [argc] => 0 ) ) [files] => Symfony\Component\HttpFoundation\FileBag Object ( [parameters:protected] => Array ( ) ) [cookies] => Symfony\Component\HttpFoundation\ParameterBag Object ( [parameters:protected] => Array ( [_ga] => GA1.2.985968222.1545147037 [cookieconsent_status] => dismiss [remember_web_59ba36addc2b2f9401580f014c7f58ea4e30989d] => eyJpdiI6Iit4Y0JyVjVYNGpHQUxIb01ZbzR6Smc9PSIsInZhbHVlIjoibjFEeEZQSmZveHVwXC9DdGNXaTVaNHI2eFJscGNXdkxDdlJUaVVXYXRYYUw4ditKQ3d0VUxtUWo5ZmdmRzg0V1JYMU0rc3BLYVRzaUFqbHVvRit5ZVV4blQxa09oM2RZdXRpdXpcL1ZwalVFOD0iLCJtYWMiOiJlMGJkNTI2ODlmN2IzYzcxNGNlN2U2MWZjMGU1OTNhNDczODIyM2U3ODY0MDA3YzkzMWQxYTQ1NTNkYTMwOTkwIn0= [_gid] => GA1.2.1755130210.1553515611 [_gat] => 1 [1stchoice_session] => eyJpdiI6InJFS3U5NUNIUFMwbm8wTnkzM1ZKZnc9PSIsInZhbHVlIjoiSWhOOGFCS3R3NVwvVTlMSUFSWTVaMUthc05UUXVJYTVvdnR1dGc3V2xcL2tzcWJaVWN6ekFMb3BmSzBcL2x0TzQzVyIsIm1hYyI6ImVhNTA1ZDlmY2ZlMzIyMDRkMjdhYTRlZjhjN2JhMzE1NjIwOGQyOGFmY2I4NDYxYzExOTk2ZTQ0ZjIzOTQ1OTQifQ== ) ) [headers] => Symfony\Component\HttpFoundation\HeaderBag Object ( [headers:protected] => Array ( [host] => Array ( [0] => dev.1stchoice.lan ) [connection] => Array ( [0] => keep-alive ) [cache-control] => Array ( [0] => max-age=0 ) [upgrade-insecure-requests] => Array ( [0] => 1 ) [user-agent] => Array ( [0] => Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36 ) [dnt] => Array ( [0] => 1 ) [accept] => Array ( [0] => text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 ) [referer] => Array ( [0] => http://dev.1stchoice.lan/sagecheckout/confirm ) [accept-encoding] => Array ( [0] => gzip, deflate ) [accept-language] => Array ( [0] => en-US,en;q=0.9 ) [cookie] => Array ( [0] => _ga=GA1.2.985968222.1545147037; cookieconsent_status=dismiss; remember_web_59ba36addc2b2f9401580f014c7f58ea4e30989d=eyJpdiI6Iit4Y0JyVjVYNGpHQUxIb01ZbzR6Smc9PSIsInZhbHVlIjoibjFEeEZQSmZveHVwXC9DdGNXaTVaNHI2eFJscGNXdkxDdlJUaVVXYXRYYUw4ditKQ3d0VUxtUWo5ZmdmRzg0V1JYMU0rc3BLYVRzaUFqbHVvRit5ZVV4blQxa09oM2RZdXRpdXpcL1ZwalVFOD0iLCJtYWMiOiJlMGJkNTI2ODlmN2IzYzcxNGNlN2U2MWZjMGU1OTNhNDczODIyM2U3ODY0MDA3YzkzMWQxYTQ1NTNkYTMwOTkwIn0%3D; _gid=GA1.2.1755130210.1553515611; _gat=1; 1stchoice_session=eyJpdiI6InJFS3U5NUNIUFMwbm8wTnkzM1ZKZnc9PSIsInZhbHVlIjoiSWhOOGFCS3R3NVwvVTlMSUFSWTVaMUthc05UUXVJYTVvdnR1dGc3V2xcL2tzcWJaVWN6ekFMb3BmSzBcL2x0TzQzVyIsIm1hYyI6ImVhNTA1ZDlmY2ZlMzIyMDRkMjdhYTRlZjhjN2JhMzE1NjIwOGQyOGFmY2I4NDYxYzExOTk2ZTQ0ZjIzOTQ1OTQifQ%3D%3D ) ) [cacheControl:protected] => Array ( [max-age] => 0 ) ) [content:protected] => [languages:protected] => [charsets:protected] => [encodings:protected] => [acceptableContentTypes:protected] => [pathInfo:protected] => [requestUri:protected] => [baseUrl:protected] => [basePath:protected] => [method:protected] => [format:protected] => [session:protected] => [locale:protected] => [defaultLocale:protected] => en [isHostValid:Symfony\Component\HttpFoundation\Request:private] => 1 [isForwardedValid:Symfony\Component\HttpFoundation\Request:private] => 1 ) [response:protected] => Omnipay\SagePay\Message\Response Object *RECURSION* [currencies:protected] => [zeroAmountAllowed:protected] => 1 [negativeAmountAllowed:protected] => ) [data:protected] => Array ( ) )

@judgej
Copy link
Member

judgej commented Mar 27, 2019

Have you got the purpose of steps 1 and 2 that I posted earlier? What I'm seeing here looks like they are mushed together. Only step 1 creates a redirect object. You need to focus on that first - setting up the data, then redirecting the user to Sage Pay. The completeAuthorize() is something you do when the user returns to your success URL.

Are you getting the initial redirect?

@judgej
Copy link
Member

judgej commented Mar 27, 2019

Here, play with this, it runs the code in the documentation:

https://omnipay.acadweb.co.uk/sagepay3x/test3.php

@1stChoiceSpares
Copy link
Author

Ah! I see what you mean. I think I was misunderstanding there. I will have a play and get back to you, cheers, had a moment of clarity now.

@judgej
Copy link
Member

judgej commented Mar 27, 2019

Needs a diagram really. This may help just to set the picture: https://www.sagepay.co.uk/support/12/36/sage-pay-form In that diagram, $gateway->purchase() sets up an object to handle flow "2", and $getway->completeAuthorize() handles what comes back in flow "3", sorry "4". It's the simplest of all the Sage Pay payment methods, as it is just two steps - send the user off with an encrypted payment request, and get the user back carrying their encrypted payment result. This package does all the encryption and decryption for you, based on a encryption key that Sage Pay supplies for you (log into your control panel as the admin - only the admin can do it - to generate a key).

@1stChoiceSpares
Copy link
Author

Thanks very much :) I'll have another crack at it tonight and see what I can get working.

judgej added a commit to academe/omnipay-sagepay that referenced this issue Mar 27, 2019
judgej added a commit that referenced this issue Mar 27, 2019
Issue #130 documentation changes
@1stChoiceSpares
Copy link
Author

Thanks I think I have the process clear in my head now. I am coming up with this error though:

LOG.error: Call to undefined method Omnipay\SagePay\Message\Form\PurchaseRequest::redirect()

I must not have included something correctly although I do have:
use Omnipay\Omnipay;

At the top of my controller. Any idea what I have missed out?

@judgej
Copy link
Member

judgej commented Mar 28, 2019

redirect() is in the purchase response, not the request.

Remember $response = $request->send() where $request = $gateway->purchase().

@1stChoiceSpares
Copy link
Author

Thanks! I have it redirecting to sagepay as expected. Now just got to get my success function working.

Thanks very much for all your help :)

@judgej
Copy link
Member

judgej commented Mar 30, 2019

No problem. Please close this issue when you are ready, and feel free to contribute to the documentation, even if it is just one line - everything helps.

@judgej
Copy link
Member

judgej commented Jun 18, 2019

Closing as answered.

@judgej judgej closed this as completed Jun 18, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants