Skip to content

Commit

Permalink
Feature: add sample integration for off-site gateways (#66)
Browse files Browse the repository at this point in the history
* feature: add initial classes for an off-site gateway sample

* wip

* feature: add off-site gateway simulation page

* refactor: change file name and add comments

* refactor: add description parameter

* doc: add comments

* feature: add webhook notification logic

* refactor: change OffSiteGatewayWebhookNotification properties

* fix: property name

* feature: add webhook sample logic

* refactor: change async job search parameter

* refactor: change hook name

* refactor: add rel attribute

* doc: add comments about DTO

* doc: replace unreleased tags

* refactor: rename gateway

* doc: add comment about event handler classes

* refactor: change messages

* refactor: rename logo

* feature: add refund support

* doc: update comments
  • Loading branch information
glaubersilva authored Oct 1, 2024
1 parent 1f44c14 commit bbd1de1
Show file tree
Hide file tree
Showing 13 changed files with 863 additions and 0 deletions.
2 changes: 2 additions & 0 deletions give-addon-boilerplate.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use GiveAddon\Addon\Environment;
use GiveAddon\Domain\AddonServiceProvider;
use GiveAddon\FormExtension\FormExtensionServiceProvider;
use GiveAddon\OffSiteGateway\OffSiteGatewayServiceProvider;

/**
* Plugin Name: ADDON_NAME
Expand Down Expand Up @@ -52,6 +53,7 @@ function () {
if (Environment::giveMinRequiredVersionCheck()) {
give()->registerServiceProvider(AddonServiceProvider::class);
give()->registerServiceProvider(FormExtensionServiceProvider::class);
give()->registerServiceProvider(OffSiteGatewayServiceProvider::class);
}
}
);
Expand Down
34 changes: 34 additions & 0 deletions src/OffSiteGateway/DataTransferObjects/OffSiteGatewayPayment.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace GiveAddon\OffSiteGateway\DataTransferObjects;

/**
* This Data Transfer Object class converts the gateway API response (when creating a new payment) to a local
* object where we know what properties can be accessed. The fromArray() method is where the conversion from
* the gateway API response to an object of this class is made. You should edit this method according to the
* gateway you are integrating since the API response probably should differ.
*
* @since 1.0.0
*/
class OffSiteGatewayPayment
{
/**
* @var string
*/
public $merchantPaymentId;

/**
* @var string
*/
public $gatewayPaymentId;

public static function fromArray(array $data): OffSiteGatewayPayment
{
$self = new self();

$self->gatewayPaymentId = $data['gatewayPaymentId'] ?? '';
$self->merchantPaymentId = $data['merchantPaymentId'] ?? '';

return $self;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace GiveAddon\OffSiteGateway\DataTransferObjects;

/**
* This Data Transfer Object class converts the gateway webhook notification to a local object where we know
* what properties can be accessed. The fromRequest() method is where the conversion from the gateway webhook
* notification to an object of this class is made. You should edit this method according to the gateway you
* are integrating since the webhook notification attributes probably should differ.
*
* @since 1.0.0
*/
class OffSiteGatewayWebhookNotification
{
/**
* @var string
*/
public $gatewayNotificationType;

/**
* @var string
*/
public $gatewayPaymentStatus;

/**
* @var string
*/
public $gatewayPaymentId;

/**
* @var string
*/
public $merchantPaymentId;

/**
* @since 1.0.0
*/
public static function fromRequest(array $request): OffSiteGatewayWebhookNotification
{
$self = new self();

$self->gatewayNotificationType = $request['notification_type'] ?? '';
$self->gatewayPaymentStatus = $request['payment_status'] ?? '';
$self->gatewayPaymentId = $request['payment_id'] ?? '';
$self->merchantPaymentId = $request['merchant_payment_id'] ?? '';

return $self;
}
}
112 changes: 112 additions & 0 deletions src/OffSiteGateway/Gateway/OffSiteCheckoutPageSimulation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<?php

namespace GiveAddon\OffSiteGateway\Gateway;

/**
* IMPORTANT: you don't need to keep this file in your integration; this is just a sample to demonstrate how off-site gateway integrations should work.
*
* @since 1.0.0
*/
class OffSiteCheckoutPageSimulation
{
/**
* @since 1.0.0
*/
public function __invoke()
{
if ( ! isset($_GET['off-site-gateway-simulation'])) {
return;
}

/**
* We need to do this workaround because the legacy forms submit logic tries to redirect URLs from
* the same site inside the donation form iframe instead of using the parent page as the reference.
*/
if ($this->isLegacyFormReferrer()) {
echo '<script>window.top.location.href ="' . home_url($_SERVER['REQUEST_URI']) . '";</script>';
exit();
}

ob_start();

$this->loadOffSiteGatewaySimulationMarkup();

echo ob_get_clean();

exit();
}

/**
* @since 1.0.0
*/
private function isLegacyFormReferrer(): bool
{
//V2 referrer: https://example.com/give/v2-tests?giveDonationFormInIframe=1
//V3 referrer: https://example.com/?givewp-route=donation-form-view&form-id=1350
return strpos($_SERVER['HTTP_REFERER'], 'giveDonationFormInIframe') !== false;
}

/**
* @since 1.0.0
*/
private function loadOffSiteGatewaySimulationMarkup()
{
?>
<style>
.container {
font-family: "Open Sans", Helvetica, Arial, sans-serif;
max-width: 800px;
margin: 60px auto;
}
a {
font-size: 1.5rem;
}
</style>
<div class="container">
<h1>Off-site Checkout Page Simulation</h1>
<p>
Gateway Payment ID: <strong><?php
echo $_GET['gatewayPaymentId'] ?? ' -'; ?></strong>
</p>
<p>
Donation amount: <strong><?php
echo isset($_GET['amount']) ? $_GET['amount']['currency'] . ' ' . $_GET['amount']['value'] : ' -'; ?></strong>
</p>
<p>
Description: <strong><?php
echo $_GET['description'] ?? ' -'; ?></strong>
</p>
<hr />
<p>
<strong>Click on the links below to simulate off-site gateway actions:</strong>
</p>
<a style="color:#696969;font-weight:bold;font-size: 1.2rem" target="_blank" rel="noopener noreferrer"
href="<?php
echo add_query_arg([
'notification_type' => 'one-time',
'payment_status' => 'complete',
'payment_id' => $_GET['gatewayPaymentId'],
'merchant_payment_id' => $_GET['merchantPaymentId'],
],
$_GET['webhookUrl']) ?>">
Send Webhook Notification To Change Donation Status To Complete ⭷
</a>
<p>
🛈 Some gateways send webhook notifications to change the transaction status a few hours after the
payment process is finished, and others can send them even before the user is redirected back to the
referrer's website — the action above simulates this last scenario.
</p>
<a style="color:green;font-weight: bold;" href="<?php
echo $_GET['returnUrl'] ?>">Success Payment</a> | <a style="color:red;font-weight: bold;" href="<?php
echo $_GET['cancelUrl'] ?>">Canceled Payment</a>
<br />
<br />
<p>
⚠️ This page is being loaded directly from your website to demonstrate how off-site gateways work. In
real-world integrations, this page should be the checkout page provided by the gateway you are
integrating, so users can complete or cancel the payment and be redirected back to your site.
</p>
</div>
<?php
}
}
Loading

0 comments on commit bbd1de1

Please sign in to comment.