diff --git a/CHANGELOG.md b/CHANGELOG.md index f84e5a6..dc731a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project are documented here. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.3.0] + +### Added + +- **Embedded checkout (iframe)** — a new gateway option that shows the GetPayIn checkout inside your site in an iframe instead of redirecting to it. When enabled, the plugin sends `iframe=1` on the v2 `init` call so the returned (Laravel-signed) `checkout_url` carries the flag, embeds it, and listens for the checkout's signed `paylink_payment` postMessage to move the top window to the shop's return (success) or error (failure) URL. The listener accepts messages only from the configured GetPayIn origin, so a foreign frame cannot spoof an outcome. Applies to one-off payments only; recurring subscriptions always redirect (the recurring init endpoint does not sign the flag). + ## [1.2.1] ### Fixed diff --git a/README.md b/README.md index 5602909..ec4dcc1 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ Works with all five Vik plugins: ## Features - Hosted checkout redirect (`beginTransaction` → GetPayIn) with idempotent invoice creation +- Optional **embedded checkout** — render the hosted checkout in an iframe on your site (one-off payments), with a signed `postMessage` return - Capture now, or **authorize** and capture later from the dashboard - Fixed **installments** (2–24) on the hosted checkout - **Recurring subscriptions** — creates a mandate and charges the order total every cycle @@ -62,6 +63,7 @@ the **GetPayIn** gateway, and fill in: | **Hash token** | Your integration's signing secret. Used server-side only to sign requests and verify webhooks — never exposed to the browser. | | **Base URL** | GetPayIn host. Defaults to `https://pay.getpayin.com`. | | **Payment action** | `Capture` (charge immediately) or `Authorize` (hold now, capture later). | +| **Embedded checkout** | `Yes` embeds the GetPayIn checkout in an iframe on your site instead of redirecting to it; `No` (default) redirects. Requires your integration **Origin** to exactly match this site's URL. One-off payments only — recurring subscriptions always redirect. | | **Installments** | `Yes` to offer fixed installments, with the **Number of installments** (2–24). Requires installments enabled on your account. | | **Payment type** | `One-off` for a single payment, or `Recurring subscription` to create a mandate. | | **Recurring interval / count / total cycles / consent text** | For recurring: the billing period (`month`/`week`/`day`/`year`), how many intervals between charges, an optional cap on the number of charges, and the consent statement shown to the payer. | @@ -78,7 +80,10 @@ the **GetPayIn** gateway, and fill in: order. One-off payments go to `{base_url}/api/v2/integration/init`; recurring payments go to `{base_url}/api/v2/integration/recurring/init` (which also returns a `mandate_id`). The customer is redirected to the returned - `checkout_url`. + `checkout_url` — or, with **Embedded checkout** enabled for a one-off payment, + the plugin sends `iframe=1` on `init` and renders that `checkout_url` in an + iframe, then moves the top window to the return/error URL when the checkout + posts its signed `paylink_payment` message. 2. **Payment** — The customer pays on GetPayIn's hosted checkout. 3. **Confirmation** — GetPayIn calls the plugin's webhook. The plugin verifies the body signature (fail-closed) and, on `success=1` with a paid/authorized status, diff --git a/languages/vikpaylink.pot b/languages/vikpaylink.pot index 5a439e8..318794f 100644 --- a/languages/vikpaylink.pot +++ b/languages/vikpaylink.pot @@ -2,7 +2,7 @@ # This file is distributed under the GPL-2.0-or-later license. msgid "" msgstr "" -"Project-Id-Version: GetPayIn for VikWP 1.2.0\n" +"Project-Id-Version: GetPayIn for VikWP 1.3.0\n" "Report-Msgid-Bugs-To: https://github.com/GetPayin-Tech/paylink-vikwp/issues\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -19,6 +19,9 @@ msgstr "" msgid "Consent Text//Shown to the payer when they authorise recurring charges. Required for recurring payments." msgstr "" +msgid "Embedded Checkout//Show the GetPayIn checkout embedded in your site (iframe) instead of redirecting to it. Your integration Origin must exactly match this site's URL. One-off payments only — recurring subscriptions always redirect." +msgstr "" + msgid "Hash Token//The signing secret from the same screen. It is used to sign requests and verify webhooks, and never leaves your server." msgstr "" @@ -55,6 +58,9 @@ msgstr "" msgid "Total Cycles//Optional. Stop after this many charges. Leave empty for an open-ended subscription." msgstr "" +msgid "Trouble viewing the checkout? Open it in this window" +msgstr "" + msgid "We could not start the GetPayIn checkout. Please try again or contact the store." msgstr "" diff --git a/paylink.php b/paylink.php index 6c86079..3e47bdd 100644 --- a/paylink.php +++ b/paylink.php @@ -94,6 +94,11 @@ protected function buildAdminParameters() 'type' => 'select', 'options' => array('Capture', 'Authorize'), ), + 'iframe_enabled' => array( + 'label' => __('Embedded Checkout//Show the GetPayIn checkout embedded in your site (iframe) instead of redirecting to it. Your integration Origin must exactly match this site\'s URL. One-off payments only — recurring subscriptions always redirect.', 'vikpaylink'), + 'type' => 'select', + 'options' => array('No', 'Yes'), + ), 'installments_enabled' => array( 'label' => __('Installments//Offer fixed installments on the GetPayIn checkout. Requires installments enabled on your account.', 'vikpaylink'), 'type' => 'select', @@ -147,6 +152,23 @@ protected function beginTransaction() return; } + if ($this->iframeEnabled()) { + $this->renderIframe($checkoutUrl); + } else { + $this->renderRedirect($checkoutUrl); + } + } + + /** + * Renders the full-page redirect to the hosted GetPayIn checkout, with a "Pay Now" + * link as the no-JavaScript fallback. + * + * @param string $checkoutUrl The hosted checkout URL. + * + * @return void + */ + protected function renderRedirect($checkoutUrl) + { $safeUrl = htmlspecialchars($checkoutUrl, ENT_QUOTES, 'UTF-8'); echo '
' + . '' + . __('Trouble viewing the checkout? Open it in this window', 'vikpaylink') . '
' + . '