#intelligence-applepay-manual

1 messages · Page 1 of 1 (latest)

marble cradle
#

hello! catching up one sec, I'm ~familiar with tis

willow veldt
#

Thank you!

marble cradle
#

so this depends on a few things but mainly yes that your JSON formatting is not correct

let's start here

why are you making the /v1/tokens request manually? and where from? (iOS native? web?)

willow veldt
#

Okay,... not sure about the why question... it's a custom application..........

marble cradle
#

sure but where is the custom application built

#

is it an iOS app? a web app? a desktop app?

willow veldt
#

Let me give some details

#

It's PHP based, with a Javascript frontend. The JS front end sends the token to the backend which is where the CURL call to the Stripe server takes place to exchange the token

marble cradle
#

ok so it is web based

#

how are you implementing Apple Pay? via Apple Pay JS library?

willow veldt
#

No. Full manual

marble cradle
#

why?

willow veldt
#

Because

#

I can provide you with a transaction reference, if you can check my POST request for me please

#

From what I understand I can also run the /v1/tokens request from the browser as long as I supply the publishable key in the header... so I may try that as an alternate

#

Thanks for your time looking into this

marble cradle
#

sorry I'm not questioning why you're making a request to /v1/tokens

#

I'm asking why doing it manually

#

and not using PaymentRequest Button

#

which is the recommended and simplest way to do Apple Pay with Strie

#

Stirpe

willow veldt
#

okay, thanks for your concern, but it's not relevant here.....

#

there are a lot of custom applications out there where dependencies are not used

#

I've paid enough and my client has paid way more than me, in service fees, to Stripe so that we can just use the API as we wish

#

And as a customer for years this is the only time I've had an issue with the API lacking documentation for a feature that is part of transactional payment flow

marble cradle
#

sure but that seems irrelevant, I'm not asking you to pay more to use PaymentRequest Button!
I'm just saying, you're using a really niche part of the product becuase there's a pre-built UI component for you that does Apple Pay -> Stripe Token for you.

willow veldt
#

No, but like, not every project can use that library

#

So there are going to be edge cases where pk_token to stripe_token call is necessary

#

I tried it in the github/stripe-php library but bypassed the library in order to eliminate potential blindspots in troubleshooting

marble cradle
#

So there are going to be edge cases where pk_token to stripe_token call is necessary
I think we're misunderstanding each other

#

why would there be edge cases where you don't use PaymentRequest Button?
have you looked into that?
any website that can use JS can use Stripe.js and hence PaymentRequest Button
(and all websites using Stripe should from a PCI compliance perspective)

willow veldt
#

Yup and we are PCI compliant

#

So could you please look into a reference transaction I have in the logs?

#

I can DM you the identifiers

#

But before I DM you them, is that in your scope of power--can you see them?

marble cradle
#

Yup and we are PCI compliant
ah ok

So there are going to be edge cases where pk_token to stripe_token call is necessary
sure but that doesn't change my answer, PRButton calls the /v1/tokens endpoint for you, if there are edge cases, Stripe has handled them for you

again, let's disagree and debug the actual request

here is what I need you to do so I can look into the actual params you pass (cause certain params are redacted on my end like the entire pk_token param)

willow veldt
#

I can provide a the token sample from a dev log

marble cradle
#

1/ make a new /v1/tokens request but whatever you pass in the pk_token: param, pass the exact same thing as pk_token_dummy: param
and then send me the Request ID from https://dashboard.stripe.com/test/logs/

#

I can provide a the token sample from a dev log
I'll need a new one with the addition above

willow veldt
#

ok no problem, give me about five minutes

marble cradle
#

np!

#

I'm around

willow veldt
#

DM'd, thanks for looking

marble cradle
#

ok you can send it here next time, it isn't sensitive

#

looking

willow veldt
#

I realize that but just doing so as not to link my account with my clients in public, that's all

marble cradle
#

it won't though as no one can look up the request ID aside from someone who works at Stripe and has the right set permissions i.e. my team who operates here on Discord

#

ah perfect I see the request, lemme refresh my memory on what that pk_token hash should contain, I think you're sending the whole object when you want to send just the field, checking

willow veldt
#

thank you

marble cradle
#

what are you doing with the PKToken values on your end? before passing it under pk_token
the value in pk_token is not correctly base64 encoded
e.g. I'm seeing white spaces and \\ characters in the string so something is off there

willow veldt
#

I saw the whitespace characters too. Didn't look correct. Will paste some code

#

markdown test

marble cradle
#

you can do three backticks for code too
like

console.log("hello")
willow veldt
#

yeah i was just making sure it worked, not familiar with discord

#

it's taking me a few minutes to put together a snippet, standby

#

I have to pay for discord to send long messages....

#
<script>
    apple_pay_info = {};

    ap.onpaymentauthorized = (( event ) => {
        try {
            console.log( 'onpaymentauthorized' );
            console.log( JSON.stringify( event.payment ) );

            apple_pay_info = event.payment;
            form_submit();
        }
    });

    function form_submit() {
        // Submit form and pk_token

        payload = {
            form    : {},
            payment    : {
                token : apple_pay_info
            }
        }

        // XHR POST request to our server
    }
</script>```
#
$apple_pay_token     = json_decode( $_POST[ 'payload' ][ 'payment' ][ 'token' ] );
$pk_token             = json_encode( $apple_pay_token[ 'paymentData' ] );

$array = [
    'pk_token'                     => $pk_token,
    'pk_token_dummy'             => $pk_token,
    'pk_token_transaction_id'    => $apple_pay_token[ 'transactionIdentifier' ],
    'pk_token_payment_network'    => $apple_pay_token[ 'paymentMethod' ][ 'network' ],
    'pk_token_instrument_name'    => $apple_pay_token[ 'paymentMethod' ][ 'displayName' ]
];

$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL            , 'https://api.stripe.com/v1/tokens' );
curl_setopt( $ch, CURLOPT_PROTOCOLS        , CURLPROTO_HTTPS );

    curl_setopt( $ch, CURLOPT_HTTPHEADER    , [
        'Authorization: Bearer ' . $stripe_api_key,
        'Content-Type: application/x-www-form-urlencoded'
    ]);

curl_setopt( $ch, CURLOPT_POST            , 1        );
curl_setopt( $ch, CURLOPT_POSTFIELDS    , http_build_query(  $array ) );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true     );

$response = curl_exec( $ch );
?>```
#

(removed some debug stuff)

marble cradle
#

I have to pay for discord to send long messages....
oh TIL, I've only used Discord for Stripe work so I probably have Discord benefits/QoL features that I'm not aware of

willow veldt
#

that's all right, I think it's a great way to make money

marble cradle
#

try using utf8.encode so

$pk_token             = utf8.encode( $apple_pay_token[ 'paymentData' ]);```

instead of 

$pk_token = json_encode( $apple_pay_token[ 'paymentData' ] );

willow veldt
#

Error, this is a private paste or is pending moderation. If this paste belongs to you, please login to Pastebin to view it.

#

Thanks, however the utf8_encode function built into PHP works only on strings.

I'm implementing a javascript call using our public key to the /tokens endpoint, to have the device do this. That way, we can just send a Stripe token into our system and simplify the process. It may work using this method versus the other. I have verified that the Apple Pay key is different between the device and what I receive in my POST data.

marble cradle
#

however the utf8_encode function built into PHP works only on strings.
oh wait you're in PHP land ... sorry

#

I'm implementing a javascript call using our public key to the /tokens endpoint, to have the device do this.
yep that would work

#

so which one are you doing, client-side or server-side in PHP?

willow veldt
#

Server side php

#

I'm going to shift gears and try this method. Will leave this chat open in case of any continuation

marble cradle
#

here's a heavily redacted/trimmed version of what pk_token should look like:

    pk_token="{\"version\":\"EC_v1\",\"data\":\"luaIKmCnRj6gaZvh16W/ax0hR2QSduQ==\",\"signature\":\"MIAGCSqGSIMn+jyDTK4pQx76g4b4/HSCU/LmEgSKAAAAAAAAA==\",\"header\":{\"ephemeralPublicKey\":\"MFkwokRN3XpOsr3OTR5SCnymtNGm7+vy4oW6W6/fu7oZSeiH5NKL2pYZ6ogCBxOcA==\",\"publicKeyHash\":\"kcExetztJN3qV9QrqohW8M=\",\"transactionId\":\"d88ecfbd1ef6e1a6f56217595b6\"}}"
#

though data and signature are going to be really long fields

#

just to calrify:

I'm implementing a javascript call using our public key to the /tokens endpoint, to have the device do this.
you mentioned this but then
Server side php
those are opposite no

#

you can make this call from your JS code directly to /v1/tokens too

willow veldt
#

so no, the webserver is running nginx + php, with the front-end using some javascript libraries, as this is a web app

#

cross-platform, cross-browser, that kind of deal

#

but excellent, i am not sure why I didn't think of it in the first place, I suppose the logic is to have the server translate the token to catch errors (easierly)

willow veldt
#
exchange_token = (( apple_token ) => {
    return new Promise(( resolve, reject ) => {
        try {
            console.log( 'exchange token' );
            url = 'https://api.stripe.com/v1/tokens';

            delete request;
            request = new XMLHttpRequest();

            token = new URLSearchParams({
                'pk_token'                     : JSON.stringify( apple_token.paymentData ),
                'pk_token_dummy'            : JSON.stringify( apple_token.paymentData ),
                'pk_token_transaction_id'     : apple_token.transactionIdentifier,
                'pk_token_payment_network'     : apple_token.paymentMethod.network,
                'pk_token_instrument_name'     : apple_token.paymentMethod.displayName
            });

            console.log( JSON.stringify( token.toString() ) );

            request.onload = (() => {
                console.log( request.responseText );
                resolve( JSON.parse( request.responseText ) );
            });

            request.onerror = reject;
            request.open( 'POST', url );
            request.setRequestHeader( 'Authorization', 'Bearer ' + stripe_pk );
            request.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
            request.send( token.toString() );
        }
        catch( e ) {
            console.error( e );
        }
    });
});
#

Working exchange_token function, for the record, and for other eyes searching

cold citrus
#

hurrayy! so glad to hear you got it working

willow veldt
#

thanks. I've got an invalid cert issue at the moment but it's probably unreleated

#

Overall I'm satisfied with the quality of Stripe documentation -- I generally have no issues. I do think there's room for additional details on this type of transaction within the /tokens endpoint -- perhaps a section dedicated to exchanging an Apple Pay token and explaining the various idiosyncrasies related to data types within this transaction.

cold citrus
#

That's fair - I'll raise that as feedback to the team. In general, we don't really surface the details of this flow (exchanging the apple pay token) since it's not something we recommend often and we don't want new users stumbling upon it.

willow veldt
#

I'd just put a notice that it's for Advanced Users Only or something