tyler tyler - 1 month ago 61
AngularJS Question

PayPal in context checkout with single page app (Angular)

I'm trying to use PayPal's in-context checkout in a single page app, but having issues whenever visiting a page with a PayPal button for the second time.

I've just lifted PayPal's sample code from here http://plnkr.co/edit/2GGEyNEFUPCZ7jIIGk9X?p=preview and put it onto a page in my app:

<div>
<div class="container">
<div class="row product">
<div class="col-md-4">
<h3>Toy Story Jessie T-Shirt</h3>
<p>
<a href="http://166.78.8.98/cgi-bin/aries.cgi?live=1&returnurl=http://166.78.8.98/cgi-bin/return.htm&cancelurl=http://166.78.8.98/cgi-bin/cancel.htm" id="t1">
</a>
</p>
</div>
</div>
<div class="row product">
<div class="col-md-4">
<h3>Toy Story Jessie T-Shirt</h3>
<p>
<form id="t2" class="ajaxasync" method="POST" action="http://166.78.8.98/cgi-bin/aries.cgi?live=1&returnurl=http://166.78.8.98/cgi-bin/return.htm&cancelurl=http://166.78.8.98/cgi-bin/cancel.htm">
</form>
</p>
</div>
</div>
</div>
<script>
window.paypalCheckoutReady = function() {
paypal.checkout.setup("6XF3MPZBZV6HU", {
environment: 'sandbox',
click: function(event) {
event.preventDefault();

paypal.checkout.initXO();
$.support.cors = true;
$.ajax({
url: "http://166.78.8.98/cgi-bin/aries.cgi?sandbox=1&direct=1&returnurl=http://166.78.8.98/cgi-bin/return.htm&cancelurl=http://166.78.8.98/cgi-bin/cancel.htm",
type: "GET",
data: '&ajax=1&onlytoken=1',
async: true,
crossDomain: true,

//Load the minibrowser with the redirection url in the success handler
success: function (token) {
var url = paypal.checkout.urlPrefix +token;
//Loading Mini browser with redirect url, true for async AJAX calls
paypal.checkout.startFlow(url);
},
error: function (responseData, textStatus, errorThrown) {
alert("Error in ajax post"+responseData.statusText);
//Gracefully Close the minibrowser in case of AJAX errors
paypal.checkout.closeFlow();
}
});
},
buttons: [
{ container: 't1' }, { container: 't2' }]
});
}
</script>

<script async src="//www.paypalobjects.com/api/checkout.js"></script>
</div>


This works great the first time I visit the page. However, on subsequent visits (without a hard reload in between), I get

Uncaught Error: Attempting to load postRobot twice on the same window


This is because it's trying to load the
checkout.js
script twice. So if I put a conditional to not run the
checkout.js
script on subsequent pageviews and instead jump straight to
paypal.checkout.setup
, I get

Error: You are calling paypal.checkout.setup() more than once. This function can only be called once per page load. Any further calls will be ignored.


And the button is never generated.

I need to maintain the in-context experience (the window that pops up) when the button is clicked. I've searched all through PayPal's docs and have inspected the object thoroughly in the console, but hoping I'm missing something.

How can I "reload" the button on a new page if I've already loaded
checkout.js
and called
paypal.checkout.setup()
on a prior page?

Answer

I ended up writing a directive to solve my own problem, as it does not appear that PayPal has any kind of single-page functionality.

paypal-checkout directive

The directive runs the PayPal instantiation code once, and then subsequent directive placements will simply show the already-primed button on future page/state loads.

Comments