stripe-react-native icon indicating copy to clipboard operation
stripe-react-native copied to clipboard

Display Issuing Card PIN code

Open quentinNpApnl opened this issue 1 year ago • 8 comments

Is your feature request related to a problem? Please describe. As a React Native developer, I find it challenging to display the PIN of an issuing card in my application using the existing React Native SDK. Currently, there is no straightforward way to retrieve and display the card's PIN through the SDK.

Describe the solution you'd like I would like the React Native SDK to include a dedicated method or component that allows developers to securely fetch and display the PIN of an issuing card.

Describe alternatives you've considered I have considered using a WebView to load the card issuing PIN code following those steps on the browser side, which would allow me to display the card's PIN within my React Native application. However, this approach might not provide the same level of user experience, and security as a native solution would, and it could be more challenging to implement.

Additional context The ability to display an issuing card's PIN is an essential feature for financial applications, especially those offering card management features to their users.

quentinNpApnl avatar Apr 06 '23 14:04 quentinNpApnl

hey everyone

this is my issues as well, any progress on that ?

december1990 avatar Sep 28 '23 16:09 december1990

@december1990 Hi ! I had to use a Webview and through the props injectedJavascriptBeforeContentLoaded I used Stripe.js library on browser side to make so request and be able to display the PIN code.

Here is the code I injected.

window.addEventListener(
        'DOMContentLoaded',
        async () => {
            window.ReactNativeWebView.postMessage('started');
            function apiRequest(path, body = null) {
                let method = 'GET';
                const headers = {
                   /* Headers */
                };
                
                if(null !== body) {
                    headers['Content-Type'] = 'application/json';
                    method = 'POST';
                    body = JSON.stringify(body);
                }
                return fetch('${apiUrl}' + path, {body, headers, method})
                    .then(response => {
                        if(response.ok) {
                            return response.json();
                        }

                        return Promise.reject('HTTP request failed.');
                    })
                ;
            }
            // First, fetch card ID from API
            let response = await apiRequest('/user/card'); // Getting user's card ID and Connect account ID.
    
            if('string' !== typeof response.cardId || 'string' !== typeof response.accountId) {
                window.ReactNativeWebView.postMessage('error');
            }
            
            const {cardId, accountId} = response;

            // Then, get nonce
            const stripe = Stripe('${stripePublicKey}', {stripeAccount: accountId});
            
           // Create ephemeral key nonce : https://stripe.com/docs/issuing/cards/pin-management
            const nonceResult = await stripe.createEphemeralKeyNonce({
                issuingCard: cardId,
            });

            const nonce = nonceResult.nonce;
            
            // Next, generate ephemeral key secret
            response = await apiRequest('/card/ephemeral-key', {nonce, cardId, accountId});
            
            if('string' !== typeof response.ephemeralKeySecret) {
                window.ReactNativeWebView.postMessage('error');
            }
            
            const ephemeralKeySecret = response.ephemeralKeySecret;

            // Finally, display pin code
            try {
                const number = stripe.elements().create('issuingCardPinDisplay', {
                    issuingCard: cardId,
                    nonce: nonce,
                    ephemeralKeySecret: ephemeralKeySecret,
                    style: {
                      base: {
                        color: '#000',
                        fontSize: '32px',
                        iconColor: '#c4f0ff',
                        textAlign: 'center',
                        fontFamily: 'Epilogue, sans-serif',
                        fontWeight: '700',
                        letterSpacing: '4px',
                      },
                    }
                  });
                  window.ReactNativeWebView.postMessage('ready');
                  number.mount('#pin-code');
            } catch (e) {
                window.ReactNativeWebView.postMessage(JSON.stringify(e,null,2));
            }
        },
        {once: true, passive: true}
        );

And the Webview :

                        <WebView
                            source={{uri : 'your uri'}}
                            containerStyle={{ flex: 1, }}
                            onMessage={(event) => { setLoading(
                                event?.nativeEvent?.data === 'started' ? true : false
                            ) }}
                            injectedJavaScriptBeforeContentLoaded={injectJavascript(token)} // here is the JS code you must inject
                            javaScriptEnabled={true}
                            onError={(syntheticEvent) => {
                                const {nativeEvent} = syntheticEvent
                                console.warn('WebView error: ', nativeEvent)
                            }}
                        />

I hope it can help !

quentinNpApnl avatar Sep 29 '23 06:09 quentinNpApnl

@quentinNpApnl thank you for that, in order to show card detail, I guess we should follow the same approach right ?

december1990 avatar Sep 29 '23 09:09 december1990

@december1990 Yes, at the moment there is no method to handle this case with the react-native-stripe library. However, it's possible to get the card PIN code with ios and android native library so I guess we could create a bridge.

quentinNpApnl avatar Sep 29 '23 10:09 quentinNpApnl

@quentinNpApnl to show pin card the app should implement 2FA method ? is that 2FA method is implemented by us ? I checked the android native package and the retrievePin method expects an OTP code sent to user but in stripe.js we don't have such a thing as parameter.

december1990 avatar Oct 10 '23 11:10 december1990

@december1990 Yes, you should make sure that your user uses 2FA before displaying the <Webview />

quentinNpApnl avatar Oct 10 '23 14:10 quentinNpApnl

@quentinNpApnl is it possible to use nextjs for that screen ? or it must be plain html, css

december1990 avatar Oct 10 '23 15:10 december1990

@december1990 Yes, you can use nextjs!

quentinNpApnl avatar Oct 10 '23 15:10 quentinNpApnl