Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apple Pay plugin: "The data couldn't‚ [...] isn't in the correct format." #125

Open
KATT opened this issue May 1, 2021 · 11 comments
Open

Comments

@KATT
Copy link

KATT commented May 1, 2021

Environment:

  • Using Vue.
  • Simulator on iPhone 11 / iOS 14.5

Setup

Registering the button in my main.js like this:

import { ApplePayBtn } from '@nativescript/apple-pay';
Vue.registerElement('ApplePayBtn', () => ApplePayBtn, {});

In component

Using the button like this:

<ApplePayBtn @tap="buy" buttonType="Buy" />

When clicking the button, here's my buy code (commented some stuff out as we haven't reached that point yet)

methods.buy:

async buy(args) {
    console.log('buy', args.object)

    const applePayBtn = args.object // as ApplePayBtn;
    applePayBtn.once(ApplePayEvents.DidAuthorizePaymentHandler, async (args /*: AuthorizePaymentEventData*/) => {
        // ❌ We never get here as the app crashes before
        console.log('DidAuthorizePaymentHandler', ApplePayEvents.DidAuthorizePaymentHandler);

        // this is where you do backend processing with your payment provider (Stripe, PayPal, etc.)
        // this payload is just a sample, your payload to a provider will likely be different
        // you can see here how to access the encrypted values from Apple Pay inside the `args.data.paymentData`
        const payloadToBackend = {
            transaction_type: 'purchase',
            merchant_ref: args.data.paymentData.header.transactionId,
            method: '3DS',
            '3DS': {
                // merchantIdentifier: <SomeIdentifierFromPaymentProvider>,
                // data: args.data.paymentData.data,
                // signature: args.data.paymentData.signature,
                // version: args.data.paymentData.version,
                // header: args.data.paymentData.header
            }
        };

    });


    // these are the items your customer is paying for
    const paymentItems = [
        {
            amount: 20.50,
            label: 'Balance',
            type: ApplePayPaymentItemType.Final,
        },
    ]// as ApplePayItems[];

    const request = {
        paymentItems,
        merchantId: appleMerchantID, // the merchant ID for this app
        merchantCapabilities: ApplePayMerchantCapability.ThreeDS,
        countryCode: 'US',
        currencyCode: 'USD',
        shippingContactFields: [],
        billingContactFields: [],
        supportedNetworks: [ApplePayNetworks.Amex, ApplePayNetworks.Visa, ApplePayNetworks.Discover, ApplePayNetworks.MasterCard],
    } // as ApplePayRequest;

    // `createPaymentRequest` will call into the Apple Pay SDK and present the user with the payment sheet for the configuration provided
    await applePayBtn.createPaymentRequest(request).catch((err) => {
        console.log('Apple Pay Error', err);
    });

After clicking the button createPaymentRequest() seem to create it all right because the Apple Pay stuff comes up but after selecting payment method

Full error

***** Fatal JavaScript exception - application has been terminated. *****
NativeScript encountered a fatal error: Uncaught Error: The data couldn’t be read because it isn’t in the correct format.
at
PKPaymentAuthorizationViewControllerDelegateImpl.paymentAuthorizationViewControllerDidAuthorizePaymentHandler(file: src/webpack:/tappy/node_modules/@nativescript/apple-pay/payment-authorization-view-controller-delegate.ios.js:42:0)
(CoreFoundation) *** Terminating app due to uncaught exception 'NativeScript encountered a fatal error: Uncaught Error: The data couldn’t be read because it isn’t in the correct format.
at
PKPaymentAuthorizationViewControllerDelegateImpl.paymentAuthorizationViewControllerDidAuthorizePaymentHandler(file: src/webpack:/tappy/node_modules/@nativescript/apple-pay/payment-authorization-view-controller-delegate.ios.js:42:0)
', reason: '(null)'
*** First throw call stack:
(
0   CoreFoundation                      0x0000000114497fba __exceptionPreprocess + 242
1   libobjc.A.dylib                     0x0000000114341ff5 objc_exception_throw + 48
2   NativeScript                        0x000000010cd28914 _ZN3tns21NativeScriptException15OnUncaughtErrorEN2v85LocalINS1_7MessageEEENS2_INS1_5ValueEEE + 914
3   NativeScript                        0x000000010d188f65 _ZN2v88internal14MessageHandler25ReportMessageNoExceptionsEPNS0_7IsolateEPKNS0_15MessageLocationENS0_6HandleINS0_6ObjectEEENS_5LocalINS_5ValueEEE + 341
4   NativeScript                        0x000000010d188dd4 _ZN2v88internal14MessageHandler1
@KATT
Copy link
Author

KATT commented May 2, 2021

Also planning to hook this up to Stripe as the next step - has anyone done this? - I imagine I just pass that something of that object to a backend function that talks to Stripe.

@asharghi
Copy link
Contributor

asharghi commented May 2, 2021

I'm currently using this one for Stripe: https://github.com/triniwiz/nativescript-plugins/tree/master/packages/nativescript-stripe

But would be nice to have one single plugin for payment

@KATT
Copy link
Author

KATT commented May 2, 2021

I've been trying to integrate that but running into problems with 3dsecure and right now we just need a "Pay with Apple Pay"-button anyway. (if you have a couple hours this week and want to do get freelance $, let me know, my contact details is in my bio)

@NathanWalker
Copy link
Contributor

@KATT when you get a chance could you try something? Open this file:

code node_modules/@nativescript/apple-pay/payment-authorization-view-controller-delegate.ios.js

On line 42, change it to this:

var pData = NSJSONSerialization.JSONObjectWithDataOptionsError(payment.token.paymentData, NSJSONReadingOptions.MutableContainers);

Save that and try in your app directly to see if any better. If you still see issue, that error is usually related to an unfinished json string (still receiving the full json data) - see here for few more suggestions you could try - if you find one the fixes your case we can add some extra condition handling in there:
https://stackoverflow.com/questions/37825284/the-data-couldn-t-be-read-because-it-isn-t-in-the-correct-format

@KATT
Copy link
Author

KATT commented May 9, 2021

@NathanWalker no visible change on that unfortunately - crashes as well.

***** Fatal JavaScript exception - application has been terminated. *****
NativeScript encountered a fatal error: Uncaught Error: The data couldn’t be read because it isn’t in the correct format.
at
PKPaymentAuthorizationViewControllerDelegateImpl.paymentAuthorizationViewControllerDidAuthorizePaymentHandler(file: src/webpack:/tappy/node_modules/@nativescript/apple-pay/payment-authorization-view-controller-delegate.ios.js:42:0)
(CoreFoundation) *** Terminating app due to uncaught exception 'NativeScript encountered a fatal error: Uncaught Error: The data couldn’t be read because it isn’t in the correct format.
at
PKPaymentAuthorizationViewControllerDelegateImpl.paymentAuthorizationViewControllerDidAuthorizePaymentHandler(file: src/webpack:/tappy/node_modules/@nativescript/apple-pay/payment-authorization-view-controller-delegate.ios.js:42:0)
', reason: '(null)'
*** First throw call stack:
(
0   CoreFoundation                      0x0000000112a65fba __exceptionPreprocess + 242
1   libobjc.A.dylib                     0x000000011290fff5 objc_exception_throw + 48
2   NativeScript                        0x000000010b2f6914 _ZN3tns21NativeScriptException15OnUncaughtErrorEN2v85LocalINS1_7MessageEEENS2_INS1_5ValueEEE + 914
3   NativeScript                        0x000000010b756f65 _ZN2v88internal14MessageHandler25ReportMessageNoExceptionsEPNS0_7IsolateEPKNS0_15MessageLocationENS0_6HandleINS0_6ObjectEEENS_5LocalINS_5ValueEEE + 341
4   NativeScript                        0x000000010b756dd4 _ZN2v88internal14MessageHandler1

@bradmartin
Copy link
Collaborator

@KATT - did you solve this? As for integrating with Stripe, if that is your approach, Stripe would be your payment processor with this workflow, this plugin provides the Apple Pay button (official API from Apple) and Apple handles the confirmation of the transaction with the user info on the device. Outside of that, is where you'd need your payment processor (Stripe, FirstData, etc.) to handle the actual payment/charge of the card.

Do you have your merchant ID for apple pay setup? The README links to the steps Apple forces you to do in order to use the Apple Pay APIs. Without following those steps, it is possible the error/crash is happening because your Apple Dev account isn't setup correctly.

@mahmoudajawad
Copy link

mahmoudajawad commented Sep 20, 2021

@NathanWalker, @bradmartin , I'm hitting the same issue now. I applied the change you suggested but still getting the error. Btw, I'm on simulator, is that an issue? Also, I added log messages in the file you referred to, and the error is definitely happening at line 42.

UPDATE: To answer Brad earlier question to OP, yes I made sure the merchant ID is updated in xcode and reflecting correctly, as well as using the same id in the code snippet.

@KATT
Copy link
Author

KATT commented Sep 20, 2021

We stopped using NativeScript altogether after we got the MVP in place - we used this third party plugin.

I've unsubscribed from this issue - feel free to close it.

@bradmartin
Copy link
Collaborator

@NathanWalker, @bradmartin , I'm hitting the same issue now. I applied the change you suggested but still getting the error. Btw, I'm on simulator, is that an issue? Also, I added log messages in the file you referred to, and the error is definitely happening at line 42.

UPDATE: To answer Brad earlier question to OP, yes I made sure the merchant ID is updated in xcode and reflecting correctly, as well as using the same id in the code snippet.

It has been a couple months since I worked on this but from Apple docs:

Note

Not all Apple Pay features are supported in the iOS simulator. Testing Apple Pay is unsupported in the watchOS simulator.

@mahmoudajawad
Copy link

@bradmartin, thank for your reply. I'll spare sometime for testing on an iphone later, but wanted to hear from you first. I'll have a look and revert back here with what I find.

@bradmartin
Copy link
Collaborator

I know the plugin should be working fine, one of the pain points i had in developing this was the encryption of the data to the payment provider. Testing this with all the various providers isn't something that can be done simply so I only know 100% that Payeezy/FirstData works 100% with this plugin. So it's possible other providers might have different encryption needs on the data.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants