Laravel Omnipay - The transactionReference parameter is required
Asked Answered
A

2

11

I'm working with the open source ticket system called Attendize.

They already have the payment provider Stripe integrated. Now I'm trying to make this work with the payment provider Mollie.

The problem is I keep stumbling on this error:

enter image description here

My code looks like this:

$transaction_data += [
    'transactionId' => $event_id . date('YmdHis'),
    'returnUrl' => route('showEventCheckoutPaymentReturn', [
        'event_id'              => $event_id,
        'is_payment_successful' => 1
    ]),
];

$apiKey = "test_gSDS4xNA96AfNmmdwB3fAA47******";
$gateway->setApiKey($apiKey);


$transaction = $gateway->purchase($transaction_data);

$response = $transaction->send();

if ($response->isSuccessful()) {

    session()->push('ticket_order_' . $event_id . '.transaction_id',
        $response->getTransactionReference());

    return $this->completeOrder($event_id);

} elseif ($response->isRedirect()) {
    /*
     * As we're going off-site for payment we need to store some data in a session so it's available
     * when we return
     */
    session()->push('ticket_order_' . $event_id . '.transaction_data', $transaction_data);
    Log::info("Redirect url: " . $response->getRedirectUrl());

    $return = [
        'status'       => 'success',
        'redirectUrl'  => $response->getRedirectUrl(),
        'message'      => 'Redirecting to ' . $ticket_order['payment_gateway']->provider_name
    ];

    // GET method requests should not have redirectData on the JSON return string
    if($response->getRedirectMethod() == 'POST') {
        $return['redirectData'] = $response->getRedirectData();
    }

    return response()->json($return);

} else {
    // display error to customer
    return response()->json([
        'status'  => 'error',
        'message' => $response->getMessage(),
    ]);
}

When I debug my code he's going into the elseif ($response->isRedirect()) {. I am being redirected to Mollie and a can do a successful payment. But when I am being redirect back to http://myurl.dev/e/1/checkout/success?is_payment_successful=1 I'm getting the error.

UPDATE:

In my return function I have the following code:

public function showEventCheckoutPaymentReturn(Request $request, $event_id)
{
    if ($request->get('is_payment_cancelled') == '1') {
        session()->flash('message', 'You cancelled your payment. You may try again.');
        return response()->redirectToRoute('showEventCheckout', [
            'event_id'             => $event_id,
            'is_payment_cancelled' => 1,
        ]);
    }

    $ticket_order = session()->get('ticket_order_' . $event_id);
    $gateway = Omnipay::create($ticket_order['payment_gateway']->name);

    $gateway->initialize($ticket_order['account_payment_gateway']->config + [
            'testMode' => config('attendize.enable_test_payments'),
        ]);

    $transaction = $gateway->completePurchase($ticket_order['transaction_data'][0]);

    $response = $transaction->send();

    if ($response->isSuccessful()) {
        session()->push('ticket_order_' . $event_id . '.transaction_id', $response->getTransactionReference());
        return $this->completeOrder($event_id, false);
    } else {
        session()->flash('message', $response->getMessage());
        return response()->redirectToRoute('showEventCheckout', [
            'event_id'          => $event_id,
            'is_payment_failed' => 1,
        ]);
    }

}

The problem (error) is with $response = $transaction->send();.

The array $ticket_order['transaction_data'][0] contains this:

Array
(
    [amount] => 80
    [currency] => EUR
    [description] => Order for customer: [email protected]
    [transactionId] => 120170529082422
    [returnUrl] => http://eventy.dev/e/1/checkout/success?is_payment_successful=1
)

UPDATE 2:

I've added $gateway->setApiKey($apiKey); in my return function. But the problem is that my response is NOT successful. So he doesn't go into $response->isSuccessful(). When I dump my $response variable just before he checks if it's successful it shows this: https://pastebin.com/NKCsxJ7B.

You can see there's an error like this:

[error] => Array ( [type] => request [message] => The payment id is invalid )

The payment in Mollie looks like this:

enter image description here

UPDATE 3:

In my return function I tried to check the status of the response object like this : $response->status(). This gave me the following error:

Call to undefined method Omnipay\Mollie\Message\CompletePurchaseResponse::status()

Then I tried $response->getStatus() but this gave me nothing back.

Asymptotic answered 24/5, 2017 at 6:8 Comment(2)
The code you are posting here is the code that creates the payment. This code is working, as you are being redirected to Mollie. Can you also post the code from http://myurl.dev/e/1/checkout/success?is_payment_successful=1? You are probably not passing the payment ID correctly when getting the payment status.Dys
@Daan, I've updated my topic with my return function.Asymptotic
F
2

This might have something to do with this ticket: https://github.com/thephpleague/omnipay-eway/issues/13

To solve this check I would suggest checking status code with

if ($request->status() == 201) {
    //successful created
}

My theory is that it is checking against 200

The function is defined here:

https://github.com/thephpleague/omnipay-mollie/blob/master/src/Message/AbstractResponse.php

  public function isSuccessful()
    {
        return !$this->isRedirect() && !isset($this->data['error']);
    }

It will probably fail because you expect a redirect!

201 because of my Postman test below enter image description here

Forecastle answered 10/7, 2017 at 19:13 Comment(8)
And where do I do the check?Asymptotic
You have code that says: if ($response->isSuccessful()) { in your question, just replace it with the appropriate status code check. It does not have to be 201, it depends on the request. Maybe it's even better to just check if the code starts with a 2 (means success in http land)Forecastle
Then I'm getting the error "Method code does not exist.".Asymptotic
After reading the code again it says the name is getCode() github.com/thephpleague/omnipay-multisafepay/blob/master/src/…Forecastle
Then I'm getting null back, what it should give back because there's no error.Asymptotic
Than just check for that as a "workaround"? If it is a string there is a problem. It's kinda ugly code, but out of your scope.Forecastle
Thanks, now I'm checking if its null, if thats not ok then I say it wasn't successful.Asymptotic
Sure, you've got it! :)Asymptotic
C
4

What @Daan said in his comment is correct, you are getting the error from the landing page, not the page that creates the transaction.

On that landing page you will have a call like this:

$omnipay->completePurchase($data);

In that @data array you need to include the 'transactionReference' field which should be one of the POST parameters that your http://myurl.dev/e/1/checkout/success?is_payment_successful=‌​1 URL received.

Probably a useful debugging aid is to have the code at that URL print out or log the entire $_POST array and you can use that to check what parameter you need to pull from that array. It varies a bit between gateways.

Cockatrice answered 28/5, 2017 at 6:20 Comment(6)
Great, thanks for doing that, and I can now see what your problem is. This parameter: [transactionId] => 120170529082422 needs to be passed as a transactionReference. So you will need to store the $ticket_order['transaction_data'][0] into an array and then modify the array like this $myArray['transactionReference'] = $myArray['transactionId']; Don't bother with removing any parameters, omnipay will ignore the parameters that it doesn't need.Cockatrice
I've added the transactionReference. But now I'm going into the else when I check if the response is successful. When I check the message I get "Unauthorized request".Asymptotic
Did you include the $gateway->setApiKey($apiKey); line in your return function?Dys
@Daan, Now I did this, but now I'm getting the message "The payment id is invalid".Asymptotic
Are you sure you used the same API key and testmode in both the scripts?Dys
@Daan, yes. I've updated my topic with my response object. You can see there's an error array in the object.Asymptotic
F
2

This might have something to do with this ticket: https://github.com/thephpleague/omnipay-eway/issues/13

To solve this check I would suggest checking status code with

if ($request->status() == 201) {
    //successful created
}

My theory is that it is checking against 200

The function is defined here:

https://github.com/thephpleague/omnipay-mollie/blob/master/src/Message/AbstractResponse.php

  public function isSuccessful()
    {
        return !$this->isRedirect() && !isset($this->data['error']);
    }

It will probably fail because you expect a redirect!

201 because of my Postman test below enter image description here

Forecastle answered 10/7, 2017 at 19:13 Comment(8)
And where do I do the check?Asymptotic
You have code that says: if ($response->isSuccessful()) { in your question, just replace it with the appropriate status code check. It does not have to be 201, it depends on the request. Maybe it's even better to just check if the code starts with a 2 (means success in http land)Forecastle
Then I'm getting the error "Method code does not exist.".Asymptotic
After reading the code again it says the name is getCode() github.com/thephpleague/omnipay-multisafepay/blob/master/src/…Forecastle
Then I'm getting null back, what it should give back because there's no error.Asymptotic
Than just check for that as a "workaround"? If it is a string there is a problem. It's kinda ugly code, but out of your scope.Forecastle
Thanks, now I'm checking if its null, if thats not ok then I say it wasn't successful.Asymptotic
Sure, you've got it! :)Asymptotic

© 2022 - 2024 — McMap. All rights reserved.