laravel-paypal icon indicating copy to clipboard operation
laravel-paypal copied to clipboard

Create PayPal Checkout order?

Open Fossil01 opened this issue 1 year ago • 1 comments

I am missing something here and the examples shown in the README are only for subscriptions. I'm using the v3.0 branch. I came here since PayPal does not seem to offer any up to date PHP SDK at this point, which seems wild to me.

I'm trying to create a one-time order. So I use $provider->createOrder($data);, then get the URL from that response and redirect the user there.

The response from PayPal with the URLs is like this:

array:4 [▼
  "id" => "REMOVED"
  "status" => "PAYER_ACTION_REQUIRED"
  "payment_source" => array:1 [▼
    "paypal" => []
  ]
  "links" => array:2 [▼
    0 => array:3 [▼
      "href" => "https://api.sandbox.paypal.com/v2/checkout/orders/REMOVED"
      "rel" => "self"
      "method" => "GET"
    ]
    1 => array:3 [▼
      "href" => "https://www.sandbox.paypal.com/checkoutnow?token=REMOVED"
      "rel" => "payer-action"
      "method" => "GET"
    ]
  ]
]

The user pays the order and then nothing seems to happen (in the PayPal sandbox). No webhooks, nothing. I have a webhook configured in PayPal Sandbox.

I am being redirected to my return_url with some URL parameters. I was thinking the return_url is just supposed to show a success page while PayPal will fire a webhook in the background indicating the payment was successful. Not sure which one that should be as their docs are horrible, but I am guessing it should be PAYMENT.CAPTURE.COMPLETED.

I have since found this page where they use the return_url params to capture the payment. (https://medium.com/geekculture/paypal-payment-gateway-integration-with-laravel-ebebc7ccf470) but this seems a bit off to me. Why would there be another manual step after the user completed their business on the PayPal Checkout pages?

Also when I do get a webhook it does not seem to validate, as there's never an event_type present:

        $provider = new PayPalClient;
        $token = $provider->getAccessToken();
        $provider->setAccessToken($token);

        // Verify the webhook request
        $response = $provider->verifyWebhook($request->all());

        if ($response && isset($response['event_type'])) {
            return match ($response['event_type']) {
                'PAYMENT.CAPTURE.COMPLETED' => $this->handlePaymentSucceeded($response),
                default => response('Invalid event type.', 400),
            };
        }

Any pointers would be great. Also is this using PayPal v1 or v2 API?

Fossil01 avatar Oct 30 '23 19:10 Fossil01

Yes, there is another step after creating the order, which is capturing the payment. You have to do that in the return URL depending on the response. In your case above, PAYER_ACTION_REQUIRED is returned, so you have to redirect to user to the returned paypal url and let them finish whatever paypal needs from them. Then, after they return, check that the order has been successfully created, and try to capture the payment using capturePaymentOrder().

This package uses v2, where endpoints are available. Some v1 are still in use and even required by paypal even though they are marked as deprecated. Don't ask me why ...

josefbehr avatar Nov 02 '23 13:11 josefbehr