Re: Stripe.com payment integration module
Quote:
Originally Posted by
flappingfish
I've run into an issue today, just received the following email....
Code:
Why are we contacting you?
We’re following up to remind you of the importance of keeping your promotional material in line with UK Financial Promotion regulations, and how Klarna’s On-site Messaging (OSM) can help. When advertising Klarna's BNPL products you MUST follow Klarna’s Rules for your advert to be compliant with the laws around advertising credit in the UK, and therefore approved by Klarna. If you are not the decision-maker or the individual responsible for implementing our OSM tool, please forward this email to the appropriate party within your organisation immediately.
Why is this important?
Compliance not only safeguards your business from regulatory risks but also builds customer trust. With Klarna’s OSM, you can ensure that your promotions meet UK regulations without the need for custom ads.
The benefits of On-site Messaging
•
Guaranteed compliance: Automatically adheres to local regulations.
•
Time-saving: Eliminates the need for creating custom promotions.
•
Consistency: Provides clear Klarna payment options to customers.
•
Enhanced Shopping Experience: Delivers dynamic, relevant offers to your customers.
Your responsibility
When advertising Klarna's BNPL products, it's essential to comply with our advertising guidelines. Non-compliance may result in regulatory breaches if you're not FCA-authorised.
Next steps
To continue benefiting from compliant and effective promotions, please ensure you’ve implemented On-site Messaging.
Klarna for Business
looking on stripe it took a search for klarna in the search bar on their developers tab to get to a mini article where it states the following....
Code:
Klarna branding
Let your customers know you accept payments with Klarna by including the Payment Method Messaging Element on your product and cart pages. You must comply with Klarna’s marketing compliance guides.
If you’re in the UK, there are FCA regulatory requirements in the UK regarding advertising Klarna’s BNPL payment methods. Failure to comply can result in criminal charges. As per these requirements, you must only advertise Klarna with messaging approved by Klarna. You can find Klarna approved messaging in Klarna’s UK Financial Promotion Rules.
I also tried klarna's website first and found that they have been messing around with code and have issues with their htaccess and cors rules that is blocking the code snippets i suppossedly need from popping up, it seems to be region specific snippets, although stripe may have made a dynamic version for their api/sdk?
You need to complain to Stripe, so far as I know you have no control over Klarna messages created by Stripe.
Re: Stripe.com payment integration module
Quote:
Originally Posted by
marton_1
You need to complain to Stripe, so far as I know you have no control over Klarna messages created by Stripe.
I figured it out, sort of, realised i didnt have stripe installed on my testing sandbox so its got a TODO comment and hardcoded publishable key
the code is dynamically pulled from stripe and injected into the following div...
Code:
<div id="payment-method-messaging-element"></div>
it loads and does the calculations as expected, the TODO is self explanatory. This particular edit covers the "tpl_product_info.php" in includes/templates/your_template_folder/templates/ but should also be presented in the basket with the price set as the total basket price and i think i have covered the issue then?
i'm not happy with the location of the div, the page is a bit funky from playing around with it yesterday trying to improve its layout... BUT, it works :)
Code:
* @version $Id: Steve 2021 Jun 14 Modified in v1.5.8-alpha $
*/
//require(DIR_WS_MODULES . '/debug_blocks/product_info_prices.php');
//require_once(DIR_WS_LANGUAGES . $_SESSION['language'] . '/modules/payment/stripe.php');
// TODO test without hardcoding credentials double check language definition url and uncomment above require statement
define('MODULE_PAYMENT_STRIPE_PUBLISHABLE_KEY', 'pk_live_add_your_pk_live_here');
?>
<script src="https://js.stripe.com/v3/"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
// Set your publishable key. Replace with your live key in production.
const stripe = Stripe('<?php echo MODULE_PAYMENT_STRIPE_PUBLISHABLE_KEY; ?>', {
locale: 'en-GB' // Sets the locale to British English
});
// Get the product price dynamically from the span with id "productPrices"
const priceElement = document.querySelector('#productPrices');
if (!priceElement) {
console.error('Price element not found. Ensure the id "productPrices" exists.');
return;
}
// Extract and convert the price to pence
const productPrice = parseFloat(priceElement.innerText.replace(/[^\d.]/g, '')) * 100;
// Check if price was extracted correctly
if (isNaN(productPrice)) {
console.error('Failed to extract the product price. Check the price format.');
return;
}
// Create an instance of Stripe Elements
const elements = stripe.elements();
// Payment Method Messaging Element options
const options = {
amount: productPrice, // Use dynamically fetched product price
currency: 'GBP', // Set to British Pounds
countryCode: 'GB', // Country code for the UK
};
// Create the Payment Method Messaging Element
const paymentMessageElement = elements.create('paymentMethodMessaging', options);
// Mount the element to a container with the specified ID
paymentMessageElement.mount('#payment-method-messaging-element');
});
</script>
<div class="centerColumn product-info" id="productGeneral">
<!--bof Form start-->
<?php echo zen_draw_form('cart_quantity', zen_href_link(zen_get_info_page($_GET['products_id']), zen_get_all_get_params(array('action')) . 'action=add_product', $request_type), 'post', 'enctype="multipart/form-data" id="addToCartForm"') . "\n"; ?>
<!--eof Form start-->
<?php if ($messageStack->size('product_info') > 0) echo $messageStack->output('product_info'); ?>
<!--bof Category Icon -->
<?php if ($module_show_categories != 0) { ?>
<?php
/**
* display the category icons
*/
//require($template->get_template_dir('/tpl_modules_category_icon_display.php',DIR_WS_TEMPLATE, $current_page_base,'templates'). '/tpl_modules_category_icon_display.php'); ?>
<?php } ?>
<!--eof Category Icon -->
<!--bof Prev/Next top position -->
<?php if (PRODUCT_INFO_PREVIOUS_NEXT == 1 or PRODUCT_INFO_PREVIOUS_NEXT == 3) { ?>
<?php
/**
* display the product previous/next helper
*/
require($template->get_template_dir('/tpl_products_next_previous.php',DIR_WS_TEMPLATE, $current_page_base,'templates'). '/tpl_products_next_previous.php'); ?>
<?php } ?>
<!--eof Prev/Next top position-->
<div id="prod-info-top" class="container-fluid-mobile <?php echo ( $elevatezoom_style == 'pro' ) ? 'container-mobile-airSticky' : ''; ?>">
<div class="row <?php echo ( $elevatezoom_style == 'pro' ) ? 'airSticky_stop-block' : ''; ?>">
<div id="pinfo-left" class="<?php echo $prod_info_img_class; ?> hidden-xs group">
<!--bof Main Product Image -->
<?php if (!empty($products_image)) { ?>
<?php require($template->get_template_dir('/tpl_modules_additional_images.php',DIR_WS_TEMPLATE, $current_page_base,'templates'). '/tpl_modules_additional_images.php'); ?>
<?php } ?>
</div>
<div class="tt-mobile-product-layout col-12 visible-xs">
<div class="tt-mobile-product-slider arrow-location-center slick-animated-show-js">
<div><?php echo wt_image(addslashes($products_image_large), addslashes($products_name), MEDIUM_IMAGE_WIDTH, MEDIUM_IMAGE_HEIGHT, 'data-zoom-image="' . addslashes($products_image_large) . '"'); ?></div>
<?php
if ( is_array( $list_box_contents ) > 0 ) {
for ( $row = 0; $row < sizeof( $list_box_contents ); $row++ ) {
for ( $col = 0; $col < sizeof( $list_box_contents[$row] ); $col++ ) {
if ( isset( $list_box_contents[$row][$col]['text']['large'] ) ) {
echo '<div ' . wt_stringify_atts( $list_box_contents[$row][$col]['params'] ) . '>' . $list_box_contents[$row][$col]['text']['large'] . '</div>';
}
}
}
}
?>
</div>
</div>
<h1 id="productName" class="tt-title productGeneral"><?php echo $products_name; ?></h1>
<div class="tt-price">
<span id="productPrices" class="productGeneral new-price">
<?php
// base price
if ($show_onetime_charges_description == 'true') {
$one_time = '<span >' . TEXT_ONETIME_CHARGE_SYMBOL . TEXT_ONETIME_CHARGE_DESCRIPTION . '</span><br>';
} else {
$one_time = '';
}
echo $one_time . ((zen_has_product_attributes_values((int)$_GET['products_id']) and $flag_show_product_info_starting_at == 1) ? TEXT_BASE_PRICE : '') . zen_get_products_display_price((int)$_GET['products_id']);
?>
</span>
</div>
<div id="payment-method-messaging-element"></div>
if anyone decides to go ahead and implement this you need the div id and to locate it where you please. alot of this code wont match up to what you may have, the important pieces are....
Code:
//require_once(DIR_WS_LANGUAGES . $_SESSION['language'] . '/modules/payment/stripe.php');
// TODO test without hardcoding credentials double check language definition url and uncomment above require statement
define('MODULE_PAYMENT_STRIPE_PUBLISHABLE_KEY', 'pk_live_add_your_pk_live_here');
?>
<script src="https://js.stripe.com/v3/"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
// Set your publishable key. Replace with your live key in production.
const stripe = Stripe('<?php echo MODULE_PAYMENT_STRIPE_PUBLISHABLE_KEY; ?>', {
locale: 'en-GB' // Sets the locale to British English
});
// Get the product price dynamically from the span with id "productPrices"
const priceElement = document.querySelector('#productPrices');
if (!priceElement) {
console.error('Price element not found. Ensure the id "productPrices" exists.');
return;
}
// Extract and convert the price to pence
const productPrice = parseFloat(priceElement.innerText.replace(/[^\d.]/g, '')) * 100;
// Check if price was extracted correctly
if (isNaN(productPrice)) {
console.error('Failed to extract the product price. Check the price format.');
return;
}
// Create an instance of Stripe Elements
const elements = stripe.elements();
// Payment Method Messaging Element options
const options = {
amount: productPrice, // Use dynamically fetched product price
currency: 'GBP', // Set to British Pounds
countryCode: 'GB', // Country code for the UK
};
// Create the Payment Method Messaging Element
const paymentMessageElement = elements.create('paymentMethodMessaging', options);
// Mount the element to a container with the specified ID
paymentMessageElement.mount('#payment-method-messaging-element');
});
</script>
and your div....
<div id="payment-method-messaging-element"></div>
which might take some experimenting with until you locate it where you like... do be careful and backup your tpl_display_product_info.php before making any changes :cool:
SIDENOTE: if you are not in the uk you need to edit the currency and country code :)
Re: Stripe.com payment integration module
Quote:
Originally Posted by
flappingfish
I figured it out, sort of, realised i didnt have stripe installed on my testing sandbox so its got a TODO comment and hardcoded publishable key
the code is dynamically pulled from stripe and injected into the following div...
Code:
<div id="payment-method-messaging-element"></div>
it loads and does the calculations as expected, the TODO is self explanatory. This particular edit covers the "tpl_product_info.php" in includes/templates/your_template_folder/templates/ but should also be presented in the basket with the price set as the total basket price and i think i have covered the issue then?
i'm not happy with the location of the div, the page is a bit funky from playing around with it yesterday trying to improve its layout... BUT, it works :)
Code:
* @version $Id: Steve 2021 Jun 14 Modified in v1.5.8-alpha $
*/
//require(DIR_WS_MODULES . '/debug_blocks/product_info_prices.php');
//require_once(DIR_WS_LANGUAGES . $_SESSION['language'] . '/modules/payment/stripe.php');
// TODO test without hardcoding credentials double check language definition url and uncomment above require statement
define('MODULE_PAYMENT_STRIPE_PUBLISHABLE_KEY', 'pk_live_add_your_pk_live_here');
?>
<script src="https://js.stripe.com/v3/"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
// Set your publishable key. Replace with your live key in production.
const stripe = Stripe('<?php echo MODULE_PAYMENT_STRIPE_PUBLISHABLE_KEY; ?>', {
locale: 'en-GB' // Sets the locale to British English
});
// Get the product price dynamically from the span with id "productPrices"
const priceElement = document.querySelector('#productPrices');
if (!priceElement) {
console.error('Price element not found. Ensure the id "productPrices" exists.');
return;
}
// Extract and convert the price to pence
const productPrice = parseFloat(priceElement.innerText.replace(/[^\d.]/g, '')) * 100;
// Check if price was extracted correctly
if (isNaN(productPrice)) {
console.error('Failed to extract the product price. Check the price format.');
return;
}
// Create an instance of Stripe Elements
const elements = stripe.elements();
// Payment Method Messaging Element options
const options = {
amount: productPrice, // Use dynamically fetched product price
currency: 'GBP', // Set to British Pounds
countryCode: 'GB', // Country code for the UK
};
// Create the Payment Method Messaging Element
const paymentMessageElement = elements.create('paymentMethodMessaging', options);
// Mount the element to a container with the specified ID
paymentMessageElement.mount('#payment-method-messaging-element');
});
</script>
<div class="centerColumn product-info" id="productGeneral">
<!--bof Form start-->
<?php echo zen_draw_form('cart_quantity', zen_href_link(zen_get_info_page($_GET['products_id']), zen_get_all_get_params(array('action')) . 'action=add_product', $request_type), 'post', 'enctype="multipart/form-data" id="addToCartForm"') . "\n"; ?>
<!--eof Form start-->
<?php if ($messageStack->size('product_info') > 0) echo $messageStack->output('product_info'); ?>
<!--bof Category Icon -->
<?php if ($module_show_categories != 0) { ?>
<?php
/**
* display the category icons
*/
//require($template->get_template_dir('/tpl_modules_category_icon_display.php',DIR_WS_TEMPLATE, $current_page_base,'templates'). '/tpl_modules_category_icon_display.php'); ?>
<?php } ?>
<!--eof Category Icon -->
<!--bof Prev/Next top position -->
<?php if (PRODUCT_INFO_PREVIOUS_NEXT == 1 or PRODUCT_INFO_PREVIOUS_NEXT == 3) { ?>
<?php
/**
* display the product previous/next helper
*/
require($template->get_template_dir('/tpl_products_next_previous.php',DIR_WS_TEMPLATE, $current_page_base,'templates'). '/tpl_products_next_previous.php'); ?>
<?php } ?>
<!--eof Prev/Next top position-->
<div id="prod-info-top" class="container-fluid-mobile <?php echo ( $elevatezoom_style == 'pro' ) ? 'container-mobile-airSticky' : ''; ?>">
<div class="row <?php echo ( $elevatezoom_style == 'pro' ) ? 'airSticky_stop-block' : ''; ?>">
<div id="pinfo-left" class="<?php echo $prod_info_img_class; ?> hidden-xs group">
<!--bof Main Product Image -->
<?php if (!empty($products_image)) { ?>
<?php require($template->get_template_dir('/tpl_modules_additional_images.php',DIR_WS_TEMPLATE, $current_page_base,'templates'). '/tpl_modules_additional_images.php'); ?>
<?php } ?>
</div>
<div class="tt-mobile-product-layout col-12 visible-xs">
<div class="tt-mobile-product-slider arrow-location-center slick-animated-show-js">
<div><?php echo wt_image(addslashes($products_image_large), addslashes($products_name), MEDIUM_IMAGE_WIDTH, MEDIUM_IMAGE_HEIGHT, 'data-zoom-image="' . addslashes($products_image_large) . '"'); ?></div>
<?php
if ( is_array( $list_box_contents ) > 0 ) {
for ( $row = 0; $row < sizeof( $list_box_contents ); $row++ ) {
for ( $col = 0; $col < sizeof( $list_box_contents[$row] ); $col++ ) {
if ( isset( $list_box_contents[$row][$col]['text']['large'] ) ) {
echo '<div ' . wt_stringify_atts( $list_box_contents[$row][$col]['params'] ) . '>' . $list_box_contents[$row][$col]['text']['large'] . '</div>';
}
}
}
}
?>
</div>
</div>
<h1 id="productName" class="tt-title productGeneral"><?php echo $products_name; ?></h1>
<div class="tt-price">
<span id="productPrices" class="productGeneral new-price">
<?php
// base price
if ($show_onetime_charges_description == 'true') {
$one_time = '<span >' . TEXT_ONETIME_CHARGE_SYMBOL . TEXT_ONETIME_CHARGE_DESCRIPTION . '</span><br>';
} else {
$one_time = '';
}
echo $one_time . ((zen_has_product_attributes_values((int)$_GET['products_id']) and $flag_show_product_info_starting_at == 1) ? TEXT_BASE_PRICE : '') . zen_get_products_display_price((int)$_GET['products_id']);
?>
</span>
</div>
<div id="payment-method-messaging-element"></div>
if anyone decides to go ahead and implement this you need the div id and to locate it where you please. alot of this code wont match up to what you may have, the important pieces are....
Code:
//require_once(DIR_WS_LANGUAGES . $_SESSION['language'] . '/modules/payment/stripe.php');
// TODO test without hardcoding credentials double check language definition url and uncomment above require statement
define('MODULE_PAYMENT_STRIPE_PUBLISHABLE_KEY', 'pk_live_add_your_pk_live_here');
?>
<script src="https://js.stripe.com/v3/"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
// Set your publishable key. Replace with your live key in production.
const stripe = Stripe('<?php echo MODULE_PAYMENT_STRIPE_PUBLISHABLE_KEY; ?>', {
locale: 'en-GB' // Sets the locale to British English
});
// Get the product price dynamically from the span with id "productPrices"
const priceElement = document.querySelector('#productPrices');
if (!priceElement) {
console.error('Price element not found. Ensure the id "productPrices" exists.');
return;
}
// Extract and convert the price to pence
const productPrice = parseFloat(priceElement.innerText.replace(/[^\d.]/g, '')) * 100;
// Check if price was extracted correctly
if (isNaN(productPrice)) {
console.error('Failed to extract the product price. Check the price format.');
return;
}
// Create an instance of Stripe Elements
const elements = stripe.elements();
// Payment Method Messaging Element options
const options = {
amount: productPrice, // Use dynamically fetched product price
currency: 'GBP', // Set to British Pounds
countryCode: 'GB', // Country code for the UK
};
// Create the Payment Method Messaging Element
const paymentMessageElement = elements.create('paymentMethodMessaging', options);
// Mount the element to a container with the specified ID
paymentMessageElement.mount('#payment-method-messaging-element');
});
</script>
and your div....
<div id="payment-method-messaging-element"></div>
which might take some experimenting with until you locate it where you like... do be careful and backup your tpl_display_product_info.php before making any changes :cool:
SIDENOTE: if you are not in the uk you need to edit the currency and country code :)
slight mistake that only showed when i moved it to my live site, stripe pk is already defined globally so these lines aren't necessary...
Code:
//require_once(DIR_WS_LANGUAGES . $_SESSION['language'] . '/modules/payment/stripe.php');
// TODO test without hardcoding credentials double check language definition url and uncomment above require statement
define('MODULE_PAYMENT_STRIPE_PUBLISHABLE_KEY', 'pk_live_add_your_pk_live_here');
Re: Stripe.com payment integration module
I've fixed Stripe secure payment module 1.3.4 and uploaded as a version 1.3.5.
It works for One-page checkout.
but
Credit card payment and
USD or CAN or GBP or EUR only.
:D
Re: Stripe.com payment integration module
For those of us looking at the Plugins and seeing version 2.1.5 as the latest version, can you enlighten us as to where we can find 1.3.5?
thanx
Re: Stripe.com payment integration module
Quote:
Originally Posted by
dbltoe
For those of us looking at the Plugins and seeing version 2.1.5 as the latest version, can you enlighten us as to where we can find 1.3.5?
thanx
2.1.5
1. Stripe form is embedded in the checkout confirmation page.
2. Compared to version 1, it has better security because customers enter card information directly into Stripe server without using $_post.
3.A lot of payment methods are acceptable. For example Credit card, Apple pay, Google pay, iDEAL, Paypal and so on.
4.One-page checkout is not available.
1.3.5
1. Credit card payment only.
2. One-page checkout is available.
Version 1.3.5 has been fixed in Zen Cart 1.5.8 to the extent that no errors occur, so please be sure to test it.
Please wait until it is available for download.Please wait until it is available for download.
Re: Stripe.com payment integration module
Quote:
Originally Posted by
Gozzandes
2.1.5
1. Stripe form is embedded in the checkout confirmation page.
2. Compared to version 1, it has better security because customers enter card information directly into Stripe server without using $_post.
3.A lot of payment methods are acceptable. For example Credit card, Apple pay, Google pay, iDEAL, Paypal and so on.
4.One-page checkout is not available.
1.3.5
1. Credit card payment only.
2. One-page checkout is available.
Version 1.3.5 has been fixed in Zen Cart 1.5.8 to the extent that no errors occur, so please be sure to test it.
Please wait until it is available for download.Please wait until it is available for download.
I was misunderstanding the one-page checkout module.
Word "stripe" should be added into the admin page one-page checkout setting=>Payment Methods Requiring Confirmation.
I can build stripe module version 2 for One-page checkout payment.
Please wait 1week.
Re: Stripe.com payment integration module
Quote:
Originally Posted by
Gozzandes
I was misunderstanding the one-page checkout module.
Word "stripe" should be added into the admin page one-page checkout setting=>Payment Methods Requiring Confirmation.
I can build stripe module version 2 for One-page checkout payment.
Please wait 1week.
Please don't forget the following changes to each of the three versions, they break the install if you have a prefix set:
/www/includes/payment/stripe.php
PHP Code:
$db-> execute("DROP TABLE IF EXISTS stripe ;");
$db-> execute("CREATE TABLE " . DB_PREFIX . " stripe(id INT(11) AUTO_INCREMENT PRIMARY KEY,customers_id INT(11),Stripe_Customers_id VARCHAR(32))");
to
PHP Code:
$db-> execute("DROP TABLE IF EXISTS " . DB_PREFIX . "stripe ;");
$db-> execute("CREATE TABLE " . DB_PREFIX . "stripe(id INT(11) AUTO_INCREMENT PRIMARY KEY,customers_id INT(11),Stripe_Customers_id VARCHAR(32))");
The DROP table directive doesn't automatically try to find DB_PREFIX . stripe and the CREATE TABLE directory includes a space before PREFIX. I submitted the above change to the plugin directory but not sure if it'll make it in time.
Re: Stripe.com payment integration module
Thank you for your advice.
I've just fixed it and uploaded.
Re: Stripe.com payment integration module
The next modification will be "Payment succeeded" message.
Administrator can change the message in the admin page.
and
I'll change the location of the payment form from bottom to under the billing address.
<HR>
Nihon Yokane corporation