PayPal & PHP Video Tutorial: Paypal Standard Checkout Payment

We are going to discover today how to use the Paypal Standard Checkout which allows you to integrate a PayPal payment button directly on our site.

Create a payment

The first step is to generate a payment button call using the JavaScript SDK. We will use a intent=authorize so as not to instantiate the payment directly in order to be able to capture the server-side payment afterwards.

    public function ui(Cart $cart): string
    {
        $clientId = PAYPAL_ID;
        $order = json_encode([
            'purchase_units' => [
                [
                    'description' => 'Panier tutoriel grafikart',
                    'items'       => array_map(function ($product) {
                        return [
                            'name'        => $product['name'],
                            'quantity'    => 1,
                            'unit_amount' => [
                                'value'         => number_format($product['price'] / 100, 2, '.', ""), // Mes sommes sont en centimes d'euros
                                'currency_code' => 'EUR',
                            ]
                        ];
                    }, $cart->getProducts()),
                    'amount'      => [
                        'currency_code' => 'EUR',
                        'value'         => number_format($cart->getTotal() / 100, 2, '.', ""),
                        'breakdown'     => [
                            'item_total' => [
                                'currency_code' => 'EUR',
                                'value'         => number_format($cart->getTotal() / 100, 2, '.', "")
                            ]
                        ]
                    ]
                ]
            ]
        ]);
        return <<<HTML
        <script src="https://www.paypal.com/sdk/js?client-id={$clientId}&currency=EUR&intent=authorize"></script>
        <div id="paypal-button-container"></div>
        <script>
          paypal.Buttons({
            // Sets up the transaction when a payment button is clicked
            createOrder: (data, actions) => {
              return actions.order.create({$order});
            },
            // Finalize the transaction after payer approval
            onApprove: async (data, actions) => {
              const authorization = await actions.order.authorize()
              const authorizationId = authorization.purchase_units[0].payments.authorizations[0].id
              await fetch('/paypal.php', {
                method: 'post',
                headers: {
                  'content-type': 'application/json'
                },
                body: JSON.stringify({authorizationId})
              })
              alert('Votre paiement a bien été enregistré')
            }
          }).render('#paypal-button-container');
        </script>
    HTML;
    }

When clicking on the button a popup will open with the Paypal payment interface (and the site will remain in the background). Once the user has entered this information and confirmed the payment, the popup will close and the method present in the onApprove will be called.

Capture payment

Once the user has authorized the payment, we will retrieve an authorization ID that we can use to capture the payment by communicating with the paypal API. You can use Paypal’s PHP SDK for this. paypal/paypal-checkout-sdk.

    public function handle(ServerRequestInterface $request, Cart $cart): void
    {
        if ($this->sandbox) {
            $environment = new \PayPalCheckoutSdk\Core\SandboxEnvironment($this->clientId, $this->clientSecret);
        } else {
            $environment = new \PayPalCheckoutSdk\Core\ProductionEnvironment($this->clientId, $this->clientSecret);
        }
        $client = new \PayPalCheckoutSdk\Core\PayPalHttpClient($environment);
        $authorizationId = $request->getParsedBody()['authorizationId'];
        $request = new \PayPalCheckoutSdk\Payments\AuthorizationsGetRequest($authorizationId);
        $authorizationResponse = $client->execute($request);
        if ($authorizationResponse->result->amount->value !== number_format($cart->getTotal() / 100, 2, '.', "")) {
            throw new PaymentAmountMissmatchException($amount, $cart->getTotal());
        }

        // On peut récupérer l'Order créé par le bouton
        $orderId = $authorizationResponse->result->supplementary_data->related_ids->order_id;
        // $request = new OrdersGetRequest($orderId);
        // $orderResponse = $client->execute($request);

        // Vérifier si le stock est dispo

        // Verrouiller le produit (retirer du stock pour éviter une commande en parallèle entre temps)

        // Sauvegarder les informations de l'utilisateur

        // On capture l'autorisation
        $request = new AuthorizationsCaptureRequest($authorizationId);
        $response = $client->execute($request);
        if ($response->result->status !== 'COMPLETED') {
            throw new \Exception();
        }

And There you go ! It’s up to you to add your own logic on top of this system.