First Commit
This commit is contained in:
1 parent
5eb9dd037d
commit
2e62c0e60b
11877 files changed
+2035312
No files matched your search
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
/**
|
||||
* PayPal Pay Later Messaging — standalone promotional banner.
|
||||
* Shows text like "Pay in 4 payments of $X" near prices on product / cart pages.
|
||||
*
|
||||
* Usage — set $ppMessage before including:
|
||||
*
|
||||
* $ppMessage = [
|
||||
* 'school_name' => 'Springfield Elementary', // required — used to resolve merchant ID
|
||||
* 'amount' => '95.00', // required — string
|
||||
* 'currency' => 'USD', // optional, default USD
|
||||
* 'placement' => 'product', // product | cart | payment | home
|
||||
* 'page_type' => 'product-detail', // for SDK data-page-type attr
|
||||
* 'style' => [ // optional — PayPal Messages style object
|
||||
* 'layout' => 'text',
|
||||
* 'logo' => ['type' => 'inline'], // inline | primary | alternative | none
|
||||
* 'text' => ['size' => 13, 'color' => 'black'],
|
||||
* ],
|
||||
* ];
|
||||
* require_once '/path/to/ppp/paypal-paylater-message.php';
|
||||
*
|
||||
* Coordinates with paypal-checkout-widget.php via $GLOBALS['_pp_sdk_loaded'] so the
|
||||
* SDK is never loaded twice on the same page regardless of include order.
|
||||
*/
|
||||
|
||||
if (!isset($ppMessage) || !is_array($ppMessage)) {
|
||||
throw new RuntimeException('$ppMessage array must be set before including paypal-paylater-message.php');
|
||||
}
|
||||
|
||||
// -- Resolve merchant and check readiness -------------------------------------
|
||||
$_ppm_config = require __DIR__ . '/config.php';
|
||||
|
||||
// Kill-switch shared with the checkout widget: set 'paylater_messaging' => false
|
||||
// in config.php to disable Pay Later promo messaging everywhere (the SDK's
|
||||
// messaging component has thrown unhandled PAGE_TYPE exceptions in some envs).
|
||||
// Defaults to FALSE — see paypal-checkout-widget.php. A config predating this
|
||||
// key must not re-enable the SDK messaging crash.
|
||||
if (!(bool)($_ppm_config['paylater_messaging'] ?? false)) return;
|
||||
|
||||
$_ppm_merchantId = null;
|
||||
$_ppm_merchantsFile = __DIR__ . '/data/school_merchants.json';
|
||||
|
||||
if (file_exists($_ppm_merchantsFile)) {
|
||||
$_ppm_merchants = json_decode(file_get_contents($_ppm_merchantsFile), true) ?: [];
|
||||
$_ppm_record = $_ppm_merchants[$ppMessage['school_name']] ?? null;
|
||||
if ($_ppm_record) {
|
||||
if ($ppMessage['school_name'] === '') return;
|
||||
if ($ppMessage['school_name'] !== '' && ($GLOBALS['_pp_msg_skipped'][$ppMessage['school_name']] ?? false)) return;
|
||||
if ($_ppm_record['consent_revoked'] ?? false) return;
|
||||
if (isset($_ppm_record['paypal_ready']) && !$_ppm_record['paypal_ready']) return;
|
||||
$_ppm_merchantId = $_ppm_record['merchant_id'] ?? null;
|
||||
}
|
||||
}
|
||||
if (!$_ppm_merchantId) return;
|
||||
|
||||
// -- Unique container ID (counter prevents collisions when included multiple times) --
|
||||
$GLOBALS['_pp_msg_count'] = ($GLOBALS['_pp_msg_count'] ?? 0) + 1;
|
||||
$_ppm_containerId = 'pp-msg-' . $GLOBALS['_pp_msg_count'];
|
||||
|
||||
// -- Params --------------------------------------------------------------------
|
||||
$_ppm_clientId = $_ppm_config['client_id'];
|
||||
$_ppm_amount = $ppMessage['amount'];
|
||||
$_ppm_currency = strtoupper($ppMessage['currency'] ?? 'USD');
|
||||
$_ppm_placement = $ppMessage['placement'] ?? 'product';
|
||||
$_ppm_pageType = $ppMessage['page_type'] ?? 'product-details';
|
||||
|
||||
// PayPal's SDK rejects unknown data-page-type values ("Invalid page type"),
|
||||
// which aborts the whole SDK load. Map aliases and fall back to a safe value.
|
||||
$_ppmValidPageTypes = [
|
||||
'home', 'category', 'product-listing', 'search-results', 'product-details',
|
||||
'cart', 'mini-cart', 'checkout', 'order-review', 'order-confirmation',
|
||||
'account', 'profile', 'blog', 'about', 'contact', 'landing', 'marketing',
|
||||
'help', 'search', 'unknown',
|
||||
];
|
||||
$_ppmPageTypeAliases = ['product-detail' => 'product-details', 'product' => 'product-details'];
|
||||
$_ppm_pageType = $_ppmPageTypeAliases[$_ppm_pageType] ?? $_ppm_pageType;
|
||||
if (!in_array($_ppm_pageType, $_ppmValidPageTypes, true)) {
|
||||
$_ppm_pageType = 'product-details';
|
||||
}
|
||||
$_ppm_style = $ppMessage['style'] ?? [
|
||||
'layout' => 'text',
|
||||
'logo' => ['type' => 'inline'],
|
||||
'text' => ['size' => 13, 'color' => 'black'],
|
||||
];
|
||||
|
||||
// -- SDK: load once per page ---------------------------------------------------
|
||||
$_ppmSdkAlready = $GLOBALS['_pp_sdk_loaded'] ?? false;
|
||||
if (!$_ppmSdkAlready) {
|
||||
$GLOBALS['_pp_sdk_loaded'] = true;
|
||||
// Include the full component set (buttons,messages + applepay,googlepay) so the
|
||||
// checkout widget can share this SDK if it loads after us. The PayPal SDK can only
|
||||
// be loaded once per page, so if we omit applepay/googlepay here, paypal.Applepay /
|
||||
// paypal.Googlepay would be undefined in the widget and the wallet buttons vanish.
|
||||
$_ppm_sdkUrl = 'https://www.paypal.com/sdk/js'
|
||||
. '?client-id=' . urlencode($_ppm_clientId)
|
||||
. '&merchant-id=' . urlencode($_ppm_merchantId)
|
||||
. '¤cy=' . $_ppm_currency
|
||||
. '&components=buttons,applepay,googlepay';
|
||||
}
|
||||
?>
|
||||
|
||||
<?php /* NOTE: no data-page-type attribute — the SDK throws "Cannot set
|
||||
properties of undefined (setting 'PAGE_TYPE')" asynchronously when it
|
||||
is present (internal SDK bug). Optional analytics hint only. */ ?>
|
||||
<?php if (!$_ppmSdkAlready): ?>
|
||||
<script
|
||||
src="<?= htmlspecialchars($_ppm_sdkUrl) ?>"
|
||||
data-partner-attribution-id="EZSSOFTWAREINC_SP_PPCP"
|
||||
></script>
|
||||
<?php endif; ?>
|
||||
|
||||
<div id="<?= $_ppm_containerId ?>" class="pp-paylater-banner"></div>
|
||||
|
||||
<style>
|
||||
#<?= $_ppm_containerId ?>.pp-paylater-banner { min-height: 18px; margin: 4px 0 8px; }
|
||||
</style>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
var id = <?= json_encode('#' . $_ppm_containerId) ?>;
|
||||
// No placement/pageType — the SDK's placement?PAGE_TYPE mapping has crashed
|
||||
// with "Cannot set properties of undefined"; defaults are fine for text promos.
|
||||
var config = {
|
||||
amount: parseFloat(<?= json_encode($_ppm_amount) ?>),
|
||||
style: <?= json_encode($_ppm_style, JSON_UNESCAPED_UNICODE) ?>,
|
||||
};
|
||||
|
||||
function render() {
|
||||
if (window.paypal && window.paypal.Messages) {
|
||||
window.paypal.Messages(config).render(id);
|
||||
}
|
||||
}
|
||||
|
||||
// If SDK is already present (loaded above or by widget earlier on the page) render now.
|
||||
// Otherwise DOMContentLoaded is the safe fallback — by then all blocking scripts have run.
|
||||
if (window.paypal && window.paypal.Messages) {
|
||||
render();
|
||||
} else {
|
||||
document.addEventListener('DOMContentLoaded', render);
|
||||
}
|
||||
}());
|
||||
</script>
|
||||
Reference in new issue
Block a user