Working on a website that has been integrated with Apple Pay for about a year now with no issues. We are noticing that we are always getting an error now for iOS 13 devices only. iOS 12 and under all work as expected.
Front end click handler:
<div class="btn btn-apple">
<div class="apple-pay-button apple-pay-button-white" lang="en" data-bind="click: intializeApplePaySession"></div>
</div>
JS click handler:
self.intializeApplePaySession = function() {
new RestClient(RestClient.POST, "/rest/model/someController", {},
//Success
function(data, textStatus, jqXHR) {
var session = new ApplePaySession(3,data.applePayPaymentRequest);
initializeCallbacks(session);
session.begin();
},
...
"Must create a new ApplePaySession from a user gesture handler." is always thrown at
var session = new ApplePaySession(3,data.applePayPaymentRequest);
for all iOS 13 devices. iOS 12 and below work fine with the same code.
From my debugging I can see that the event being handled is a MouseEvent which makes sense to me. Any ideas as to why this is being thrown?
Working on a website that has been integrated with Apple Pay for about a year now with no issues. We are noticing that we are always getting an error now for iOS 13 devices only. iOS 12 and under all work as expected.
Front end click handler:
<div class="btn btn-apple">
<div class="apple-pay-button apple-pay-button-white" lang="en" data-bind="click: intializeApplePaySession"></div>
</div>
JS click handler:
self.intializeApplePaySession = function() {
new RestClient(RestClient.POST, "/rest/model/someController", {},
//Success
function(data, textStatus, jqXHR) {
var session = new ApplePaySession(3,data.applePayPaymentRequest);
initializeCallbacks(session);
session.begin();
},
...
"Must create a new ApplePaySession from a user gesture handler." is always thrown at
var session = new ApplePaySession(3,data.applePayPaymentRequest);
for all iOS 13 devices. iOS 12 and below work fine with the same code.
From my debugging I can see that the event being handled is a MouseEvent which makes sense to me. Any ideas as to why this is being thrown?
Share Improve this question asked Oct 4, 2019 at 19:58 Paul HokePaul Hoke 1451 gold badge2 silver badges7 bronze badges4 Answers
Reset to default 7We are evolving away from letting websites make cross origin calls without the user's input.
One of the ways this has been locked down for a while is that you can't fire, for instance, a submit button for a form... unless you do it from a click() handler. So you can put a big shiny "Buy now" image on the page and submit the form from clicking on that image, but you can't just do a setTimeout(form.submit(), 100)
I think you've got the same class of thing going here. The REST call is in the click handler, but the apple pay call is in the callback to the REST call, and therefore not really in the click() handler.
Of course you're using the REST call to generate the data to pass to Apple. You may have to generate that data speculatively. But before doing that infrastructure work, I'd experiment with whether an async version of your click handler passes their sanity checks.
Working snippet following discussion with Jason and Brother Woodrow
Synchronous function to call backend and get current cart details. The reason we previously had this in the success callback is because we are using a SPA framework so the cart can change at any time. We cannot call this when the page loads or the data may be stale.
self.getApplePayData = function() {
var self = this;
new RestClient(RestClient.POST, "/rest/model/getApplePayPaymentRequest", {},
function(data, textStatus, jqXHR) {
self.applePayData = data;
},
....
self.intializeApplePaySession = function() {
var self = this;
self.getApplePayData();
var session = new ApplePaySession(3,self.applePayData.applePayPaymentRequest);
I think the key issue is that we were creating a new ApplePaySession from within the success callback of the rest call which Apple does not seem to want to be possible anymore.
Reference from the official documentation
You attempt to create the ApplePaySession outside of a user gesture handler. The exception error "Must create a new ApplePaySession from a user gesture handler" appears.
So in your case, you must create an apple pay session like
session = new window.ApplePaySession(version, request);
then create a request to the server and receive a response.
const data = async getSomeCheckoutData();
and you can proceed with payment throw apple pay
...
session.begin();
The main idea, it's, first of all, create a session. Then you can do requests and after it start apple pay session.
You must declare ApplePayInstance variable above class, to trick apple pay session, so that it consider it as gesture, Also don't call in promises
http://baiduhix.blogspot.com/2018/06/must-create-new-applepaysession-from.html