I'm following the stripe server integration guide here. My server creates a stripe session, and returns:
<HTML lang=en><HEAD><TITLE>Payments</TITLE></HEAD>
<BODY>
<H1>Loading.....</H1>
loading stripe
<SCRIPT src="https://js.stripe.com/v3/"></SCRIPT>
done loading stripe
<SCRIPT type=text/javascript>
try {
document.writeln('creating Stripe object');
// error occurs here, Stripe is undefined
var stripe = Stripe('<PUBLIC KEY GOES HERE>');
document.writeln('redirecting to checkout');
stripe.redirectToCheckout({
sessionId: '<SESSION ID GOES HERE>'
}).then(function (result) {
});
document.writeln('done calling javascript');
}
catch(error) {
document.writeln('error occurred: ' + error.message);
}
</SCRIPT>
<H1>....DONE</H1></BODY></HTML>
NOTE: the public key and session id have been redacted
This works fine when loaded by firefox/ie explorer, but when using wxWidgets Webview which uses ie explorer as it's backend it throws
The value of the property 'Stripe' is null or undefined, not a Function object
wxpython webview code:
import wx, traceback
from wx.html2 import WebView, EVT_WEBVIEW_ERROR, EVT_WEBVIEW_LOADED, EVT_WEBVIEW_NAVIGATING, EVT_WEBVIEW_NEWWINDOW, \
WEBVIEWIE_EMU_IE11
html = """<HTML lang=en><HEAD><TITLE>Payments</TITLE></HEAD>
<BODY>
<H1>Loading.....</H1>
loading stripe
<SCRIPT src="https://js.stripe.com/v3/"></SCRIPT>
done loading stripe
<SCRIPT type=text/javascript>
try {
document.writeln('creating Stripe object');
// error occurs here, Stripe is undefined
var stripe = Stripe('<PUBLIC KEY GOES HERE>');
document.writeln('redirecting to checkout');
stripe.redirectToCheckout({
sessionId: '<SESSION ID GOES HERE>'
}).then(function (result) {
});
document.writeln('done calling javascript');
}
catch(error) {
document.writeln('error occurred: ' + error.message);
}
</SCRIPT>
<H1>....DONE</H1></BODY></HTML> """
class Main(wx.Frame):
def __init__(self):
super().__init__(parent=None, size=(1000, 800))
self._times_loaded = 0
self.webview = WebView.New(self) # type: WebView
self.webview.Bind(EVT_WEBVIEW_ERROR, self.on_error)
self.webview.Bind(EVT_WEBVIEW_LOADED, self.on_loaded)
self.webview.Bind(EVT_WEBVIEW_NAVIGATING, self.on_navigate)
self.webview.Bind(EVT_WEBVIEW_NEWWINDOW, self.on_new_window)
# wx.CallAfter(self.load_gateway)
wx.CallAfter(self.load_html)
self.Show()
# def load_gateway(self, evt=None):
# self.webview.LoadURL(url)
def load_html(self):
self.webview.SetPage(html, "www.stripe.com")
def reset_page(self):
self.webview.SetPage(self.webview.GetPageSource(), url)
# def redirect_to_checkout(self):
# # stripe.
# session= stripe.checkout.session.Session.create(test_stripe_public_key)
def on_error(self, evt):
print(f"error occurred: {evt}")
def on_navigate(self, evt):
print("on navigate")
def on_loaded(self, evt):
print("loaded")
self._times_loaded += 1
def on_new_window(self, evt):
print("new window event")
try:
app = wx.App()
frame = Main()
app.MainLoop()
except:
input(traceback.format_exc())
For some reason the first script at https://js.stripe.com/v3/ doesn't create the Stripe
object when called with the ie explorer emulator.
I assumed it was an issue with an unsupported user-agent so I replaced all user-Agent references in the stripe script with
Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
which didn't work. I tried to read through https://js.stripe.com/v3/ to see why Stripe would be undefined. My javascript skills are pretty weak and it is clearly minified/obfuscated so I'm having a difficult time understanding how and why Stripe
would be undefined. It looks like it's declared dynamically, but what about the emulated browser is causing it to be undefined?
--------------Update 9-23-19---------------
After @duck suggested it might be a problem with my script running before the stripe script was loaded I changed the html to sequence the redirect function to run after stripe was loaded:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Payments</title>
</head>
<body>
<script type="text/javascript">
function redirectToCheckout(evt){
try {
document.writeln('loading stripe.js')
var stripe = Stripe('REDACTED');
document.writeln('redirecting to checkout');
stripe.redirectToCheckout({
sessionId: 'REDACTED'
}).then(function (result) {
});
document.writeln('done calling javascript');
}
catch(error) {
document.writeln('error occurred: ' + error.message);
}
}
//source: https://stackoverflow.com/questions/950087/how-do-i-include-a-javascript-file-in-another-javascript-file
function loadScript(url, callback)
{
// Adding the script tag to the head as suggested before
//document.writeln('loading stripe script');
console.log('loading stripe script');
var head = document.head;
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
// Then bind the event to the callback function.
// There are several events for cross browser compatibility.
script.onreadystatechange = callback;
script.onload = callback;
// Fire the loading
head.appendChild(script);
}
function loadStripe(evt){
loadScript('https://js.stripe.com/v3/', redirectToCheckout);
}
var onloadScript = loadStripe;
if(window.attachEvent) {
window.attachEvent('onload', onloadScript);
} else {
if(window.onload) {
var curronload = window.onload;
var newonload = function(evt) {
curronload(evt);
onloadScript(evt);
};
window.onload = newonload;
} else {
window.onload = onloadScript;
}
}
</script>
Page loaded
</body>
</html>