tommed
tommed

Reputation: 1561

Apple Pay completeMerchantValidation cancels session

My backend successfully validates the merchant and a session is returned, but when I complete the validation on the browser, it immediately cancels the transaction. There are a few similar complaints on the Apple Dev forum, but none seem to have been answered; I'm hoping you guys can help!

Out of all the event handlers on the ApplePaymentSession object, only onvalidatemerchant is called, then as soon as completeMerchantValidation with a valid session object (see payload below), oncancel is triggered.

Session config (on browser)

    const session = new ApplePaySession(3, {
      currencyCode: 'GBP',
      countryCode: 'GB',
      merchantCapabilities: [ 'supports3DS' ],
      supportedNetworks: ['visa', 'masterCard', 'amex', 'discover' ],
      total: {
        type: 'final',
        label: 'My Product',
        amount: 9.99,
      },       
    });

Request (on backend)

    {
      merchantIdentifier: 'merchant.MY.FQDN',
      displayName: 'My Company Name',
      initiative: 'web',
      initiativeContext: 'MY.VERIFIED.FQDN',
    }

Response (from Apple to backend, then sent to completeMerchantValidation

    {
      "epochTimestamp": 1552090296444,
      "expiresAt": 1552093896444,
      "merchantSessionIdentifier": "LONG_STRING",
      "nonce": "XXXX",
      "merchantIdentifier": "SAME_AS_IN_MY_MERCHANT_ID_CERT",
      "domainName": "MY.VERIFIED.FQDN",
      "signature": "XXXXXX-VERY-LONG-STRING-XXXXX"
    }

I'm definitely sending this response into completeMerchantValidation as a JSON object and not a string, like so:

    console.log('session is a', typeof(result), result); // says: object
    session.completeMerchantValidation(result);

The domain name this is all happening from (and hosted on Firebase) is verified against this Merchant ID and I don't get any errors either in the backend or the browser console, no exception is thrown to catch, it just shows the Apple Pay tray, then says "Payment not complete" and hides the tray very quickly. Help!

UPDATE: Looking at the docs, it appears that startSession (which is being returned by onvalidatemerchant is being phased out, so I have tried replacing it with paymentSession (e.g. https://apple-pay-gateway-nc-pod5.apple.com/paymentservices/paymentSession); but I still get the same response and behaviour.

Upvotes: 3

Views: 5408

Answers (2)

Ray
Ray

Reputation: 11

I had the same issue where the payment sheet would display then go away without a chance to authorize the transaction. I made sure the domain was verified, the certificate was valid, and that I was actually receiving a response back from the server side request to Apple. Sorting through the process of elimination I came across certain interesting observations:

  • If the payment sheet disappeared immediately, it was usually due to a configuration issue with the server side request payload (for example, the "initiativeContext" was "something.com" when I was actually using "www.something.com" in the web browser address).
  • If the payment sheet disappeared after several seconds, it was usually due to a syntax issue or error in the client side JavaScript. In my case, I was not doing session.onpaymentmethodselected and session.completepaymentmethodselection correctly. So I removed all other Apple specific JS functions except for session.onvalidatemerchant and a subsequent call to session.completeMerchantValidation passing the Apple response from the server side request. It then worked.
  • If the Apple response from the server side request was in any way (even just the casing) changed from what Apple originally sent it would not work (for instance, "epochtimestamp":1668095263534," vs "epochTimestamp":1668095263534,").

Hope that helps.

Upvotes: 1

nicosuria
nicosuria

Reputation: 453

This solution may or may not work for you, but I was experiencing the same issue in that the session was being cancelled as soon as session.completeMerchantValidation() was called.

It boiled down to the merchantSession being created with a domainName value that was not verified (see: https://developer.apple.com/documentation/apple_pay_on_the_web/configuring_your_environment)

I used a local webserver broadcasting through Ngrok to validate a temporary URL by putting the apple-developer-merchantid-domain-association.txt file where it needed to be based on Apple Pay documentation.

After that, as long as I was using a sandbox iCloud account and a test Apple Pay card, passing the ngrok URL as the domainName value for the merchantSession request worked and Apple Pay finally started working locally. Note that I had to interact with my locally running web application through the ngrok url for Apple Pay to work.

Upvotes: 2

Related Questions