I am trying to set up Stripe payments in such a way that it doesn't take the user out of the GAS custom modal. The modal is triggered when the user clicks a button to become a premium member in a custom sidebar the Add-On provides.
As far as I know Apps Script do not allow for redirects, so the stripe example below doesn't work as it depends on the user getting redirected to stripe's payment portal.
This is the example: https://stripe.com/docs/payments/checkout/client-subscription#enable-checkout
At one point it should redirect the user to a Stripe page for the payment gateway.
<div class="container">
<div class="row">
<h5>Free</h5>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quae vitae illum, commodi facilis labore
dicta? Culpa corporis qui veritatis exercitationem fuga cumque, ad ex ea quod dolorem esse
consequuntur a?</p>
</div>
<div class="row">
<h5>Premium</h5>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Quia voluptatem nostrum nulla doloremque
impedit obcaecati nesciunt illum quidem sapiente nihil, tempore suscipit error nam numquam, culpa
facilis minus, eum repudiandae!</p>
<button id="checkout-button-plan_" target="_top" class="btn-small">1 year
- 12€</button>
<label for="checkout-button-plan_">30 days free, cancel any time</label>
<div id="error-message"></div>
</div>
</div>
<script>
(function () {
var stripe = Stripe('pk_test_');
var checkoutButton = document.getElementById('checkout-button-plan_');
checkoutButton.addEventListener('click', function () {
// When the customer clicks on the button, redirect
// them to Checkout.
stripe.redirectToCheckout({
items: [{
plan: 'plan_GGOGMuQ5nh',
quantity: 1
}],
// Do not rely on the redirect to the successUrl for fulfilling
// purchases, customers may not always reach the success_url after
// a successful payment.
// Instead use one of the strategies described in
// https://stripe.com/docs/payments/checkout/fulfillment
successUrl: 'https://demo.org/success',
cancelUrl: 'https://demo.org/canceled',
})
.then(function (result) {
if (result.error) {
// If `redirectToCheckout` fails due to a browser or network
// error, display the localized error message to your customer.
var displayError = document.getElementById('error-message');
displayError.textContent = result.error.message;
}
});
});
})();
</script>
Right now the action is blocked since the modal doesn't have the permission to redirect the user.
- What (if this is even possible anymore with Stripe) is the proper way of doing this in GAS, completing the payment all from within the modal?
- What would be your suggested approach if the above is blocked or simply not practical?
I'm right now leaning towards dealing with payments in a separate web page altogether. I am not in favor of sending the user away from the Spreadsheet though, and would like to avoid it if possible, while still retaining the possibility of allowing for SCA-regulated payments.
Thanks in advance for any insights!
Update: Error message
v3:1 Unsafe JavaScript attempt to initiate navigation for frame with origin 'https://docs.google.com' from frame with URL 'https://n-xdlpqop7hu3az75jfccpm6uaaujayexlmqjnkoq-1lu-script.googleusercontent.com/userCodeAppPanel'. The frame attempting navigation of the top-level window is sandboxed, but the flag of 'allow-top-navigation' or 'allow-top-navigation-by-user-activation' is not set.
(anonymous) @ v3:1
v3:1 Unsafe JavaScript attempt to initiate navigation for frame with origin 'https://docs.google.com' from frame with URL 'https://[...]script.googleusercontent.com/userCodeAppPanel'. The frame attempting navigation of the top-level window is sandboxed, but the flag of 'allow-top-navigation' or 'allow-top-navigation-by-user-activation' is not set.
(anonymous) @ v3:1
v3:1 Uncaught (in promise) DOMException: Failed to set the 'href' property on 'Location': The current window does not have permission to navigate the target frame to 'https://checkout.stripe.com/pay/ppage_[...]'.
at https://js.stripe.com/v3:1:120966
at new Promise (<anonymous>)
at sc (https://js.stripe.com/v3:1:120728)
at ws (https://js.stripe.com/v3:1:137767)
at https://js.stripe.com/v3:1:139074
Update: Markup + JS used to open modal
Markup in sidebar:
<footer class="page-footer">
<div class="container">
<div class="row">
<div class="center">
<b>Free version</b>| <a href="">Support</a>
</div>
<div class="center">
<button class="btn-small grey lighten-3 teal-text" onclick="showSubscriptionModal(event)">Upgrade
membership </button>
</div>
</div>
</div>
</footer>
<script>
function showSubscriptionModal(event) {
alert("called!");
google.script.run.showSubscriptionModal();
}
</script>
JS in codefile:
const showSubscriptionModal = () => {
const template = HtmlService.createTemplateFromFile('subscription');
const html = template.evaluate().setTitle('Subscription and Payments');
SpreadsheetApp.getUi().showModalDialog(html, 'Subscription and Payments');
};
export default showSubscriptionModal;