Zen Cart Logo
Forums / Addon Payment Modules / Stripe.com payment integration module

Stripe.com payment integration module

Views: 233,173

Results 381 to 400 of 679
30 Sep 2024, 9:03 PM
#381
gozzandes avatar

gozzandes

Zen Follower

Join Date:
Jul 2021
Location:
Fukuoka Japan
Posts:
131
Plugin Contributions:
0

Stripe.com payment integration module

[QUOTE=flappingfish;1403578]> flappingfish:

just had a pair of customers come in and use klarna for instore collection and the payment plans where setup and payment succeeded but it did not then register the payment success and directed to the "payment success" message above the payment form but pressing confirm demands fresh payment, no way to confirm the order after payment success :/

Could you please give me a few weeks?
Please try using version 2.0.5 temporarily. I think klarna works with this version, but it creates two payments, one incomplete and one successful.

30 Sep 2024, 9:13 PM
#382
gozzandes avatar

gozzandes

Zen Follower

Join Date:
Jul 2021
Location:
Fukuoka Japan
Posts:
131
Plugin Contributions:
0

Re: Stripe.com payment integration module

Could you try following code?

const stripe = Stripe (PublishableKey);

let elements;

initialize();
checkStatus();

document
  .querySelector("#payment-form")
  .addEventListener("submit", handleSubmit);

// Fetches a payment intent and captures the client secret
async function initialize(){
  const { clientSecret } = await clientS; 
  //   const { clientSecret } =await fetch("/create.php", {
  //   method: "POST",
  //   headers: { "Content-Type": "application/json" },
  //   body: JSON.stringify({ items }),
  // }).then((r) => r.json());

  
  elements = stripe.elements({ clientSecret });

  const paymentElementOptions = {
    layout: "tabs",
  };

  const paymentElement = elements.create("payment", paymentElementOptions);
  paymentElement.mount("#payment-element");
}

async function handleSubmit(e) {
  e.preventDefault();
  setLoading(true);

  const response = await stripe.confirmPayment({
    elements,
    confirmParams: {
      return_url: confirmationURL,
     },
    redirect: 'if_required'
   }
  )
  
   if (response.error) {
    showMessage(response.error.message);
   } else {
    showMessage(`Payment Succeeded: ${response.paymentIntent.id}`);

  }
  setLoading(false);
}

// Fetches the payment intent status after payment submission
async function checkStatus() {
  const clientSecret = new URLSearchParams(window.location.search).get(
    "payment_intent_client_secret"
  );

  if (!clientSecret) {
    return;
  }

  const { paymentIntent } = await stripe.retrievePaymentIntent(clientSecret);

  switch (paymentIntent.status) {
    case "succeeded":
      document.getElementById('checkoutConfirmDefaultHeading').textContent = 'Payment succeeded!.';
      document.getElementById("btn_submit").click();
      showMessage("Payment succeeded!");
      break;
    case "processing":
      document.getElementById('checkoutConfirmDefaultHeading').textContent='Your payment is processing.';
      showMessage("Your payment is processing.");
      break;
    case "requires_payment_method":
      document.getElementById('checkoutConfirmDefaultHeading').textContent='Your payment was not successful, please try again.';
      showMessage("Your payment was not successful, please try again.");
      break;
    default:
      document.getElementById('checkoutConfirmDefaultHeading').textContent='Something went wrong.';
      showMessage("Something went wrong.");
      break;
  }
}

// ------- UI helpers -------

function showMessage(messageText) {
  const messageContainer = document.querySelector("#payment-message");

  messageContainer.classList.remove("hidden");
  messageContainer.textContent = messageText;

  setTimeout(function () {
    messageContainer.classList.add("hidden");
    messageText.textContent = "";
  }, 4000);
}

// Show a spinner on payment submission
function setLoading(isLoading) {
  if (isLoading) {
    // Disable the button and show a spinner
    document.querySelector("#submit").disabled = true;
    document.querySelector("#spinner").classList.remove("hidden");
    document.querySelector("#button-text").classList.add("hidden");
  } else {
    document.querySelector("#submit").disabled = false;
    document.querySelector("#spinner").classList.add("hidden");
    document.querySelector("#button-text").classList.remove("hidden");
  }
}
30 Sep 2024, 9:29 PM
#383
gozzandes avatar

gozzandes

Zen Follower

Join Date:
Jul 2021
Location:
Fukuoka Japan
Posts:
131
Plugin Contributions:
0

Re: Stripe.com payment integration module

It does not work.
sorry.
Could you give me a few weeks?
and Try version 2.0.5.

30 Sep 2024, 10:26 PM
#384
gozzandes avatar

gozzandes

Zen Follower

Join Date:
Jul 2021
Location:
Fukuoka Japan
Posts:
131
Plugin Contributions:
0

Re: Stripe.com payment integration module

Could you try following code?

const stripe = Stripe (PublishableKey);

let elements;

initialize();
checkStatus();

document
  .querySelector("#payment-form")
  .addEventListener("submit", handleSubmit);

// Fetches a payment intent and captures the client secret
async function initialize(){
  const { clientSecret } = await clientS; 
  //   const { clientSecret } =await fetch("/create.php", {
  //   method: "POST",
  //   headers: { "Content-Type": "application/json" },
  //   body: JSON.stringify({ items }),
  // }).then((r) => r.json());

  
  elements = stripe.elements({ clientSecret });

  const paymentElementOptions = {
    layout: "tabs",
  };

  const paymentElement = elements.create("payment", paymentElementOptions);
  paymentElement.mount("#payment-element");
}

async function handleSubmit(e) {
  e.preventDefault();
  setLoading(true);

  const response = await stripe.confirmPayment({
    elements,
    confirmParams: {
      return_url: confirmationURL,
     },
    redirect: 'if_required'
   }
  )
  
   if (response.error) {
    showMessage(response.error.message);
   } else {
    showMessage(`Payment Succeeded: ${response.paymentIntent.id}`);
    document.getElementById("btn_submit").click();
  }
  setLoading(false);
}

// Fetches the payment intent status after payment submission
async function checkStatus() {
  const clientSecret = new URLSearchParams(window.location.search).get(
    "payment_intent_client_secret"
  );

  if (!clientSecret) {
    return;
  }

  const { paymentIntent } = await stripe.retrievePaymentIntent(clientSecret);

  switch (paymentIntent.status) {
    case "succeeded":
      document.getElementById('checkoutConfirmDefaultHeading').textContent = 'Payment succeeded!.';
      showMessage("Payment succeeded!");
      document.getElementById("btn_submit").click();
      break;
    case "processing":
      document.getElementById('checkoutConfirmDefaultHeading').textContent='Your payment is processing.';
      showMessage("Your payment is processing.");
      break;
    case "requires_payment_method":
      document.getElementById('checkoutConfirmDefaultHeading').textContent='Your payment was not successful, please try again.';
      showMessage("Your payment was not successful, please try again.");
      break;
    default:
      document.getElementById('checkoutConfirmDefaultHeading').textContent='Something went wrong.';
      showMessage("Something went wrong.");
      break;
  }
}

// ------- UI helpers -------

function showMessage(messageText) {
  const messageContainer = document.querySelector("#payment-message");

  messageContainer.classList.remove("hidden");
  messageContainer.textContent = messageText;

  setTimeout(function () {
    messageContainer.classList.add("hidden");
    messageText.textContent = "";
  }, 4000);
}

// Show a spinner on payment submission
function setLoading(isLoading) {
  if (isLoading) {
    // Disable the button and show a spinner
    document.querySelector("#submit").disabled = true;
    document.querySelector("#spinner").classList.remove("hidden");
    document.querySelector("#button-text").classList.add("hidden");
  } else {
    document.querySelector("#submit").disabled = false;
    document.querySelector("#spinner").classList.add("hidden");
    document.querySelector("#button-text").classList.remove("hidden");
  }
}
1 Oct 2024, 12:23 PM
#385
flappingfish avatar

flappingfish

Zen Follower

Join Date:
Nov 2020
Posts:
312
Plugin Contributions:
2

Re: Stripe.com payment integration module

Gozzandes:

Could you try following code?

const stripe = Stripe (PublishableKey);

let elements;

initialize();
checkStatus();

document
.querySelector("#payment-form")
.addEventListener("submit", handleSubmit);

// Fetches a payment intent and captures the client secret
async function initialize(){
const { clientSecret } = await clientS;
// const { clientSecret } =await fetch("/create.php", {
// method: "POST",
// headers: { "Content-Type": "application/json" },
// body: JSON.stringify({ items }),
// }).then((r) => r.json());

elements = stripe.elements({ clientSecret });

const paymentElementOptions = {
layout: "tabs",
};

const paymentElement = elements.create("payment", paymentElementOptions);
paymentElement.mount("#payment-element");
}

async function handleSubmit(e) {
e.preventDefault();
setLoading(true);

const response = await stripe.confirmPayment({
elements,
confirmParams: {
return_url: confirmationURL,
},
redirect: 'if_required'
}
)

if (response.error) {
showMessage(response.error.message);
} else {
showMessage(Payment Succeeded: ${response.paymentIntent.id});
document.getElementById("btn_submit").click();
}
setLoading(false);
}

// Fetches the payment intent status after payment submission
async function checkStatus() {
const clientSecret = new URLSearchParams(window.location.search).get(
"payment_intent_client_secret"
);

if (!clientSecret) {
return;
}

const { paymentIntent } = await stripe.retrievePaymentIntent(clientSecret);

switch (paymentIntent.status) {
case "succeeded":
document.getElementById('checkoutConfirmDefaultHeading').textContent = 'Payment succeeded!.';
showMessage("Payment succeeded!");
document.getElementById("btn_submit").click();
break;
case "processing":
document.getElementById('checkoutConfirmDefaultHeading').textContent='Your payment is processing.';
showMessage("Your payment is processing.");
break;
case "requires_payment_method":
document.getElementById('checkoutConfirmDefaultHeading').textContent='Your payment was not successful, please try again.';
showMessage("Your payment was not successful, please try again.");
break;
default:
document.getElementById('checkoutConfirmDefaultHeading').textContent='Something went wrong.';
showMessage("Something went wrong.");
break;
}
}

// ------- UI helpers -------

function showMessage(messageText) {
const messageContainer = document.querySelector("#payment-message");

messageContainer.classList.remove("hidden");
messageContainer.textContent = messageText;

setTimeout(function () {
messageContainer.classList.add("hidden");
messageText.textContent = "";
}, 4000);
}

// Show a spinner on payment submission
function setLoading(isLoading) {
if (isLoading) {
// Disable the button and show a spinner
document.querySelector("#submit").disabled = true;
document.querySelector("#spinner").classList.remove("hidden");
document.querySelector("#button-text").classList.add("hidden");
} else {
document.querySelector("#submit").disabled = false;
document.querySelector("#spinner").classList.add("hidden");
document.querySelector("#button-text").classList.remove("hidden");
}
}


Just tested now and that did the trick thankyou :)

Klarna, clearpay and card payments work as expected, could possibly benefit from a pop up to confirm the order is processing between the redirect from payment succeeded to order confirmation page for people with slow connections? The payment form shows below the payment succeeded message, i waited momentarily knowing it may take a few moments, slightly confusing for folk but functional though :)
2 Oct 2024, 11:09 AM
#386
gozzandes avatar

gozzandes

Zen Follower

Join Date:
Jul 2021
Location:
Fukuoka Japan
Posts:
131
Plugin Contributions:
0

Re: Stripe.com payment integration module

A message will be displayed after a successful payment.
To change this message, change the code of line6 TEXT_PAYMENT_STRIPE_SUCCESS in \includes\languages----------\modules\payment\lang.stripe.php.

Fixed checkout.js

const stripe = Stripe (PublishableKey);

let elements;

initialize();
checkStatus();

document
  .querySelector("#payment-form")
  .addEventListener("submit", handleSubmit);

// Fetches a payment intent and captures the client secret
async function initialize(){
  const { clientSecret } = await clientS; 
  //   const { clientSecret } =await fetch("/create.php", {
  //   method: "POST",
  //   headers: { "Content-Type": "application/json" },
  //   body: JSON.stringify({ items }),
  // }).then((r) => r.json());

  
  elements = stripe.elements({ clientSecret });

  const paymentElementOptions = {
    layout: "tabs",
  };

  const paymentElement = elements.create("payment", paymentElementOptions);
  paymentElement.mount("#payment-element");
}

async function handleSubmit(e) {
  e.preventDefault();
  setLoading(true);

  const response = await stripe.confirmPayment({
    elements,
    confirmParams: {
      return_url: confirmationURL,
     },
    redirect: 'if_required'
   }
  )
  
   if (response.error) {
    showMessage(response.error.message);
   } else {
    document.getElementById('checkoutConfirmDefaultHeading').textContent = PaymentSuccess;
    showMessage(PaymentSuccess);
    document.getElementById("btn_submit").click();
}
  setLoading(false);
}

// Fetches the payment intent status after payment submission
async function checkStatus() {
  const clientSecret = new URLSearchParams(window.location.search).get(
    "payment_intent_client_secret"
  );

  if (!clientSecret) {
    return;
  }

  const { paymentIntent } = await stripe.retrievePaymentIntent(clientSecret);

  switch (paymentIntent.status) {
    case "succeeded":
      document.getElementById('checkoutConfirmDefaultHeading').textContent = PaymentSuccess;
      showMessage(PaymentSuccess);
      document.getElementById("btn_submit").click();
      break;
    case "processing":
      document.getElementById('checkoutConfirmDefaultHeading').textContent='Your payment is processing.';
      showMessage("Your payment is processing.");
      break;
    case "requires_payment_method":
      document.getElementById('checkoutConfirmDefaultHeading').textContent='Your payment was not successful, please try again.';
      showMessage("Your payment was not successful, please try again.");
      break;
    default:
      document.getElementById('checkoutConfirmDefaultHeading').textContent='Something went wrong.';
      showMessage("Something went wrong.");
      break;
  }
}

// ------- UI helpers -------

function showMessage(messageText) {
  const messageContainer = document.querySelector("#payment-message");

  messageContainer.classList.remove("hidden");
  messageContainer.textContent = messageText;

  setTimeout(function () {
    messageContainer.classList.add("hidden");
    messageText.textContent = "";
  }, 4000);
}

// Show a spinner on payment submission
function setLoading(isLoading) {
  if (isLoading) {
    // Disable the button and show a spinner
    document.querySelector("#submit").disabled = true;
    document.querySelector("#spinner").classList.remove("hidden");
    document.querySelector("#button-text").classList.add("hidden");
  } else {
    document.querySelector("#submit").disabled = false;
    document.querySelector("#spinner").classList.add("hidden");
    document.querySelector("#button-text").classList.remove("hidden");
  }
}
15 Oct 2024, 5:19 AM
#387
gozzandes avatar

gozzandes

Zen Follower

Join Date:
Jul 2021
Location:
Fukuoka Japan
Posts:
131
Plugin Contributions:
0

Re: Stripe.com payment integration module

Please rewrite the contents of includes/checkout.js with this code until ver2.1.5 is available for download.

const stripe = Stripe (PublishableKey);

let elements;

initialize();
checkStatus();

document
  .querySelector("#payment-form")
  .addEventListener("submit", handleSubmit);

// Fetches a payment intent and captures the client secret
async function initialize(){
  const { clientSecret } = await clientS; 
  //   const { clientSecret } =await fetch("/create.php", {
  //   method: "POST",
  //   headers: { "Content-Type": "application/json" },
  //   body: JSON.stringify({ items }),
  // }).then((r) => r.json());

  
  elements = stripe.elements({ clientSecret });

  const paymentElementOptions = {
    layout: "tabs",
  };

  const paymentElement = elements.create("payment", paymentElementOptions);
  paymentElement.mount("#payment-element");
}

async function handleSubmit(e) {
  e.preventDefault();
  setLoading(true);

  const response = await stripe.confirmPayment({
    elements,
    confirmParams: {
      return_url: confirmationURL,
     },
    redirect: 'if_required'
   }
  )
  
   if (response.error) {
    showMessage(response.error.message);
   } else {
    document.getElementById('checkoutConfirmDefaultHeading').textContent = PaymentSuccess;
    showMessage(PaymentSuccess);
    document.getElementById("btn_submit").click();
}
  setLoading(false);
}

// Fetches the payment intent status after payment submission
async function checkStatus() {
  const clientSecret = new URLSearchParams(window.location.search).get(
    "payment_intent_client_secret"
  );

  if (!clientSecret) {
    return;
  }

  const { paymentIntent } = await stripe.retrievePaymentIntent(clientSecret);

  switch (paymentIntent.status) {
    case "succeeded":
      document.getElementById('checkoutConfirmDefaultHeading').textContent = PaymentSuccess;
      showMessage(PaymentSuccess);
      document.getElementById("btn_submit").click();
      break;
    case "processing":
      document.getElementById('checkoutConfirmDefaultHeading').textContent='Your payment is processing.';
      showMessage("Your payment is processing.");
      break;
    case "requires_payment_method":
      document.getElementById('checkoutConfirmDefaultHeading').textContent='Your payment was not successful, please try again.';
      showMessage("Your payment was not successful, please try again.");
      break;
    default:
      document.getElementById('checkoutConfirmDefaultHeading').textContent='Something went wrong.';
      showMessage("Something went wrong.");
      break;
  }
}

// ------- UI helpers -------

function showMessage(messageText) {
  const messageContainer = document.querySelector("#payment-message");

  messageContainer.classList.remove("hidden");
  messageContainer.textContent = messageText;

  setTimeout(function () {
    messageContainer.classList.add("hidden");
    messageText.textContent = "";
  }, 4000);
}

// Show a spinner on payment submission
function setLoading(isLoading) {
  if (isLoading) {
    // Disable the button and show a spinner
    document.querySelector("#submit").disabled = true;
    document.querySelector("#spinner").classList.remove("hidden");
    document.querySelector("#button-text").classList.add("hidden");
  } else {
    document.querySelector("#submit").disabled = false;
    document.querySelector("#spinner").classList.add("hidden");
    document.querySelector("#button-text").classList.remove("hidden");
  }
}
17 Oct 2024, 3:34 PM
#388
flappingfish avatar

flappingfish

Zen Follower

Join Date:
Nov 2020
Posts:
312
Plugin Contributions:
2

Re: Stripe.com payment integration module

Gozzandes:

Please rewrite the contents of includes/checkout.js with this code until ver2.1.5 is available for download.

const stripe = Stripe (PublishableKey);

let elements;

initialize();
checkStatus();

document
.querySelector("#payment-form")
.addEventListener("submit", handleSubmit);

// Fetches a payment intent and captures the client secret
async function initialize(){
const { clientSecret } = await clientS;
// const { clientSecret } =await fetch("/create.php", {
// method: "POST",
// headers: { "Content-Type": "application/json" },
// body: JSON.stringify({ items }),
// }).then((r) => r.json());

elements = stripe.elements({ clientSecret });

const paymentElementOptions = {
layout: "tabs",
};

const paymentElement = elements.create("payment", paymentElementOptions);
paymentElement.mount("#payment-element");
}

async function handleSubmit(e) {
e.preventDefault();
setLoading(true);

const response = await stripe.confirmPayment({
elements,
confirmParams: {
return_url: confirmationURL,
},
redirect: 'if_required'
}
)

if (response.error) {
showMessage(response.error.message);
} else {
document.getElementById('checkoutConfirmDefaultHeading').textContent = PaymentSuccess;
showMessage(PaymentSuccess);
document.getElementById("btn_submit").click();
}
setLoading(false);
}

// Fetches the payment intent status after payment submission
async function checkStatus() {
const clientSecret = new URLSearchParams(window.location.search).get(
"payment_intent_client_secret"
);

if (!clientSecret) {
return;
}

const { paymentIntent } = await stripe.retrievePaymentIntent(clientSecret);

switch (paymentIntent.status) {
case "succeeded":
document.getElementById('checkoutConfirmDefaultHeading').textContent = PaymentSuccess;
showMessage(PaymentSuccess);
document.getElementById("btn_submit").click();
break;
case "processing":
document.getElementById('checkoutConfirmDefaultHeading').textContent='Your payment is processing.';
showMessage("Your payment is processing.");
break;
case "requires_payment_method":
document.getElementById('checkoutConfirmDefaultHeading').textContent='Your payment was not successful, please try again.';
showMessage("Your payment was not successful, please try again.");
break;
default:
document.getElementById('checkoutConfirmDefaultHeading').textContent='Something went wrong.';
showMessage("Something went wrong.");
break;
}
}

// ------- UI helpers -------

function showMessage(messageText) {
const messageContainer = document.querySelector("#payment-message");

messageContainer.classList.remove("hidden");
messageContainer.textContent = messageText;

setTimeout(function () {
messageContainer.classList.add("hidden");
messageText.textContent = "";
}, 4000);
}

// Show a spinner on payment submission
function setLoading(isLoading) {
if (isLoading) {
// Disable the button and show a spinner
document.querySelector("#submit").disabled = true;
document.querySelector("#spinner").classList.remove("hidden");
document.querySelector("#button-text").classList.add("hidden");
} else {
document.querySelector("#submit").disabled = false;
document.querySelector("#spinner").classList.add("hidden");
document.querySelector("#button-text").classList.remove("hidden");
}
}


done :smile:
10 Nov 2024, 4:23 PM
#389
flappingfish avatar

flappingfish

Zen Follower

Join Date:
Nov 2020
Posts:
312
Plugin Contributions:
2

Re: Stripe.com payment integration module

i found a slight quirk, if you head to the checkout confirmation page with a different payment method selected (for me it was in store credit card option via zxpos and standard checkout option) it throws an undefined stripe select warning. i slightly amended includes/modules/pages/checkout_confirmation/jscript_stripe.php to prevent the error...

<?php 
// Check if Stripe is active and if $stripe_select is defined and true
if (defined('MODULE_PAYMENT_STRIPE_STATUS') && MODULE_PAYMENT_STRIPE_STATUS === 'True' && isset($stripe_select) && $stripe_select === 'True') { 
?>
    <link rel="stylesheet" href="checkout_confirmation.css" />
    <script src="https://js.stripe.com/v3/"></script>
    <script src="includes/checkout.js" defer></script>
<?php 
} 
?>

basically checking stripe was chosen as the payment method and its module status is true instead of just checking it is set to true. error log was as follows....

[10-Nov-2024 16:01:05 UTC] Request URI: /checkout_confirmation, IP address: my ip address, Language id 1
#1 include(/includes/modules/pages/checkout_confirmation/jscript_stripe.php) called at [/includes/templates/wokiee/wt_common/tpl_wt_before_body_end.php:53]
#2 require(/includes/templates/wokiee/wt_common/tpl_wt_before_body_end.php) called at [/includes/templates/wokiee/common/tpl_main_page.php:239]
#3 require(/includes/templates/wokiee/common/tpl_main_page.php) called at [/index.php:96]
--> PHP Warning: Undefined variable $stripe_select in /includes/modules/pages/checkout_confirmation/jscript_stripe.php on line 1.
15 Nov 2024, 11:37 AM
#390
flappingfish avatar

flappingfish

Zen Follower

Join Date:
Nov 2020
Posts:
312
Plugin Contributions:
2

Re: Stripe.com payment integration module

I've run into an issue today, just received the following email....

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....

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?

15 Nov 2024, 1:24 PM
#391
marton_1 avatar

marton_1

Totally Zenned

Join Date:
Apr 2013
Location:
eglisau switzerland
Posts:
568
Plugin Contributions:
0

Re: Stripe.com payment integration module

flappingfish:

I've run into an issue today, just received the following email....

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....
> 
> ```
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.

15 Nov 2024, 1:57 PM
#392
flappingfish avatar

flappingfish

Zen Follower

Join Date:
Nov 2020
Posts:
312
Plugin Contributions:
2

Re: Stripe.com payment integration module

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...

<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 :)

 * @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....

//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 :)

15 Nov 2024, 3:53 PM
#393
flappingfish avatar

flappingfish

Zen Follower

Join Date:
Nov 2020
Posts:
312
Plugin Contributions:
2

Re: Stripe.com payment integration module

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...

<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 :) > > ``` * @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....
> ```
//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...

//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');
30 Nov 2024, 10:22 AM
#394
gozzandes avatar

gozzandes

Zen Follower

Join Date:
Jul 2021
Location:
Fukuoka Japan
Posts:
131
Plugin Contributions:
0

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

2 Dec 2024, 9:15 PM
#395
dbltoe avatar

dbltoe

Totally Zenned

Join Date:
Jan 2004
Location:
N of San Antonio TX
Posts:
9,763
Plugin Contributions:
9

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

3 Dec 2024, 12:29 PM
#396
gozzandes avatar

gozzandes

Zen Follower

Join Date:
Jul 2021
Location:
Fukuoka Japan
Posts:
131
Plugin Contributions:
0

Re: Stripe.com payment integration module

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.

5 Dec 2024, 11:12 AM
#397
gozzandes avatar

gozzandes

Zen Follower

Join Date:
Jul 2021
Location:
Fukuoka Japan
Posts:
131
Plugin Contributions:
0

Re: Stripe.com payment integration module

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.

6 Dec 2024, 3:36 PM
#398
retched avatar

retched

Totally Zenned

Join Date:
Jun 2007
Location:
Bronx, New York, United States
Posts:
942
Plugin Contributions:
3

Re: Stripe.com payment integration module

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

$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

$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.

7 Dec 2024, 2:57 AM
#399
gozzandes avatar

gozzandes

Zen Follower

Join Date:
Jul 2021
Location:
Fukuoka Japan
Posts:
131
Plugin Contributions:
0

Re: Stripe.com payment integration module

Thank you for your advice.
I've just fixed it and uploaded.

11 Dec 2024, 7:46 AM
#400
gozzandes avatar

gozzandes

Zen Follower

Join Date:
Jul 2021
Location:
Fukuoka Japan
Posts:
131
Plugin Contributions:
0

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](https://www.yokane.co.jp/)