Appearance
Mollie and Square payments in a Laravel shop, without code
A shop that sells in the Netherlands or Belgium loses the sale the moment the checkout shows only a card form: the customer wanted iDEAL or Bancontact, the way they pay for everything else. A café in Toronto or a studio in Manchester already runs its counter on Square, and wants the website's orders in the same place, the same settlements, the same dashboard. A card form alone answers neither.
On a Laravel site each gateway is a project of its own: a redirect to the provider and a return that must say paid before the webhook has arrived, a webhook that must not be believed blindly, test and live keys that must never be mixed, refunds that have to find their way back, and a list of currencies with their own rules. kitloom/ has Mollie and Square as gateways beside PayPal: the keys go on one settings page, and the shop takes them like any other way to pay.
Ask the agent
With kitloom/ai connected, an agent whose user manages the payment settings reads the ways to pay (payments_): each gateway and offline method, whether it is on, the currencies it takes, whether it refunds, which credentials are still empty, and whether its webhook still needs setting up in the gateway's dashboard. So it answers:
- "Why does the checkout not offer Mollie?" — the API key is empty, or the method is off.
- "Is the Square webhook subscribed, or do we only find out when the payer comes back?"
- "Can we take yen with Square, and in what unit?"
It never sees a key's value and changes nothing here: who is paid is decided on a page a person opens. For everything else in the shop it has the shop's own tools.
Mollie: one key
Payments → Settings shows every way to pay on one page. The Mollie section:
- Enabled puts Mollie on the checkout; Title is what the payer sees there.
- API key from the Mollie dashboard, under Developers → API keys. There is no sandbox switch: a key starting with
test_takes test payments, where Mollie shows a page to choose the outcome and no money moves, and a key starting withlive_takes real ones once Mollie has approved the account. The key is kept encrypted with the application key and never shown back. - The webhook needs nothing from you. There is no address to copy and nothing to register: the site gives Mollie its address with every payment. Mollie's notification only names the payment, unsigned, so the site fetches that payment from Mollie with your key and settles it by what Mollie says. A notification nobody at Mollie sent changes nothing.
Which methods the payer is offered — card, iDEAL, Bancontact, SEPA, Klarna and the rest — is set in Mollie, under Settings → Website profiles → Payment methods, test and live each with their own list. The shop takes whatever you switched on there.
At the checkout the payer is sent to Mollie's page, picks a method, pays and comes back. The site asks Mollie at once, so the page they land on already says paid. A payment the payer cancelled, or one that expired unpaid, is cancelled; open and pending ones wait. A refund from the payment's screen goes back through Mollie, in full or in part, and Mollie pays it out with its next run; a refund made in Mollie's dashboard, or a chargeback, comes in by the same webhook and is recorded on the payment once.
Currencies: AUD, BGN, BRL, CAD, CHF, CZK, DKK, EUR, GBP, HKD, HUF, ILS, ISK, JPY, MXN, NOK, NZD, PHP, PLN, RON, SEK, SGD, TWD, USD and ZAR; JPY and ISK in whole units. iDEAL, Bancontact and SEPA take euros only, and Mollie offers the payer the methods that take the payment's currency.
Square: a token, a location, one subscription
The Square section of the same page:
- Access token from your application on developer.squareup.com, under Credentials. The switch at the top there says Sandbox or Production, each with its own token. Kept encrypted, never shown back.
- Location ID from Locations in the same application, or from the Square Dashboard under Settings → Locations: the shop the payments go to. A location takes payments in its own country's currency only — a US location, dollars.
- sandbox on goes with the Sandbox token: test payments with Square's test card numbers, no money moves. For the real shop paste the Production token and turn it off. A token of one with the switch of the other is refused as unauthorized, which is the first thing to check when nothing works.
- The webhook. Square tells the site when a payment completes or a refund settles, even if the payer closed the tab. Copy the Webhook address the page shows, add a subscription with it under Webhooks → Subscriptions in the application — Sandbox or Production, as the token — with the
payment.,created payment.,updated refund.andcreated refund.events, and paste the subscription's Signature key back. Every notification is checked against it; without it every notification is refused and Square tries again for a while. Sandbox and Production need a subscription each.updated
Save, and Square is a way to pay. The payer is sent to a Square checkout page for the amount, pays by card or a wallet Square offers there, and comes back; the site reads the order from Square there and then. A card Square declined leaves the link open, so the payer may try another card on it; a link nobody paid within a day is cancelled by the reconciliation, and one paid late after all is paid. A refund from the payment's screen goes back to the Square payment, waits while the card network has it, and is settled by Square's refund..
Currencies: USD, CAD, GBP, EUR, AUD and JPY — Square's markets, each in the location's own currency; JPY in whole yen.
Test first, live when ready
Both gateways start in test: a test_ key at Mollie, the Sandbox token and switch at Square. The checkout works end to end, orders are placed and marked paid, refunds go back, and no money moves. Going live is pasting the live key or the Production token on the same page, with no deploy: what is saved there wins over config/ and the environment.
For a Laravel developer
Mollie is on Mollie's Payments API v2, Square on Square's Checkout API (payment links), both through Laravel's HTTP client, no SDK. Payments are for any model, not only the shop's orders: an invoice or a booking implements Payable, takes the Has trait, and sends the payer on its way.
php
return $order->pay('mollie')->redirect(); // or 'square': on the return the payment is settled and $order->paid() is calledThe engine underneath is fomvasss/laravel-billing with its payments table and its other gateways — Stripe, Paddle, Monobank, LiqPay, WayForPay, Hutko. Each payment fires Payment, Payment, Payment and Payment with the payment and its payable; fulfil on Payment, never on the payer's return. The webhooks run on the queue, and pending payments past their link's lifetime are reconciled every fifteen minutes by the scheduler. It comes with both admins, Filament and Nova.
Watch it
Two short lessons from the admin, narrated:
Try it
Open a sandbox in one click, with no sign-up: Filament or Nova. Every detail of both gateways — the outcomes, refunds, the currencies, the agent's tool — is in the Payments guide; PayPal has a post of its own, Accept PayPal in a Laravel shop, and how the shop came over from WooCommerce is in WooCommerce to Laravel.