PayPal Payment Gateway
✨ PayPal's still a fairly new gateway in Simple Commerce so if you spot any issues, please open an issue.
Simple Commerce supports accepting payments through PayPal in two forms: on-site and off-site. On-site is where the customer stays on your website for the checkout process and they see a PayPal embed where they can enter their payment information. Off-site is where you redirect the user to PayPal to complete the payment process there.
Configuration
First, you'll need to add PayPal to your simple-commerce.php
config file. You will also need to pass in client_id
, client_secret
and environment
variables.
To obtain API credentials (provided you're already logged into PayPal), go to the PayPal Developers site, navigate to 'My Apps & Credentials'.
You can then create a sandbox/live application. At the end of the app creation progress, you'll be given the client_id
and client_secret
values.
1'gateways' => [2 \DoubleThreeDigital\SimpleCommerce\Gateways\Builtin\PayPalGateway::class => [3 'client_id' => env('PAYPAL_CLIENT_ID'),4 'client_secret' => env('PAYPAL_CLIENT_SECRET'),5 'environment' => env('PAYPAL_ENVIRONMENT', 'production'),6 'mode' => 'offsite', // Either: offsite OR onsite7 ],8],
Make sure that PAYPAL_ENVIRONMENT
is set to sandbox
while you're in development. You don't want a mess on your hands because you accidentally autofilled your REAL card details. That would be bad. 😅
It's best practice to use
.env
file for any API keys you need, rather than referencing them directly in your config file. Review Statamic Docs.
You may also specify the 'mode' to run the PayPal gateway in. You can either run it in offsite
or onsite
mode.
Using as an off-site gateway
Payment flow
Here's a quick run down of how the whole process works:
- After filling out shipping info etc, the store redirects the customer to PayPal
- The customer enters their payment information on PayPal's checkout
- The customer is then redirected back to your site.
- If the payment was successful, a webhook is sent to your server.
Handing the user off to PayPal's checkout
To redirect the customer off to PayPal's checkout page, you can use the sc:checkout:paypal
tag.
1{{ sc:checkout:paypal redirect="/thanks" error_redirect="/payment-error" }}
However, bear in mind that where-ever you use that tag, the customer will be redirected away from your site. So it's probably best to have it sitting on it's own page.
Handling the redirect back to your site
On the return back to your site from PayPal, you can have customers redirected to seperate URLs, depending on whether the payment was successful or failed/cancelled.
The redirect
parameter on the sc:checkout:paypal
tag will handle the successful payment redirects.
Where as error_redirect
will handle any other payment states.
Using as an on-site gateway
Payment flow
- The customer goes to a Checkout page on your website. Somewhere on that page is a 'PayPal button'
- The 'PayPal button' then asks you to enter your card details, or login with PayPal
- Once the user has entered their details, the customer submits the checkout form
- When the checkout form is submitted, the payment will be marked as paid
- The user will then be redirect to a successful purchase screen
Templating
The payment form should be included inside your {{ sc:checkout }}
form, and any PayPal magic should also be wrapped in the {{ sc:gateways }}
tag to ensure you can make full use of your gateway's configuration values.
A rough example of a PayPal implementation is provided below.
1<div id="paypal-button"></div> 2<input id="paypal-payment-id" type="hidden" name="payment_id"> 3<input type="hidden" name="gateway" value="DoubleThreeDigital\SimpleCommerce\Gateways\Builtin\PayPalGateway"> 4<script src="https://www.paypal.com/sdk/js?client-id={{ gateway-config:client_id }}¤cy={{ result.currency_code }}"></script> 5<script> 6 paypal.Buttons({ 7 createOrder: () => { 8 return Promise.resolve('{{ result.id }}'); 9 },10 onApprove: (data, actions) => {11 document.getElementById('paypal-payment-id').value = data.orderID;12 document.getElementById('checkout-form').submit();13 },14 }).render('#paypal-button');15</script>
Handling PayPal's webhook
Whenever a payment is made with PayPal, it needs to be able to communicate that with Simple Commerce. It does this using 'webhooks', which are essentially POST
requests sent by PayPal to your server that provide details about the payment.
Unfortunatley, PayPal offers no way for Simple Commerce to configure the webhook on your behalf, so you'll need to add it yourself.
- In the PayPal Developers site, navigate to 'My Apps & Credentials'
- Click into the application being used for this site/environment.
- At the bottom of the page, you'll see the 'Webhooks' section, create a new webhook.
- The Webhook URL should be:
https://example.com/!/simple-commerce/gateways/paypal/webhook
- Under 'Event types', you should select 'All events'. You can then save the webhook.
You will also need to add the webhook's URL to your list of CSRF exceptions, which can be found in app/Http/Middleware/VerifyCsrfToken.php
.
1protected $except = [2 '/!/simple-commerce/gateways/paypal/webhook',3];
When you're going through the payment flow in your development environment, you will need to use something like Expose or Ngrok to proxy request to your local server. Otherwise, PayPal wouldn't be able to hit the webhook. You will also need to update the APP_URL
in your .env
.
Code highlighting provided by Torchlight.