naoufal/react-native-apple-pay

View on GitHub
js/NativeBridge/index.js

Summary

Maintainability
A
0 mins
Test Coverage
// @flow

import type { PaymentDetailsBase, PaymentComplete } from './types';

import { NativeModules, Platform } from 'react-native';
const { ReactNativePayments } = NativeModules;

const IS_ANDROID = Platform.OS === 'android';

const NativePayments: {
  canMakePayments: boolean,
  canMakePaymentsUsingNetworks: boolean,
  supportedGateways: Array<string>,
  createPaymentRequest: PaymentDetailsBase => Promise<any>,
  handleDetailsUpdate: PaymentDetailsBase => Promise<any>,
  show: () => Promise<any>,
  abort: () => Promise<any>,
  complete: PaymentComplete => Promise<any>,
  getFullWalletAndroid: string => Promise<any>
} = {
  supportedGateways: IS_ANDROID
    ? ['stripe', 'braintree'] // On Android, Payment Gateways are supported out of the gate.
    : ReactNativePayments ? ReactNativePayments.supportedGateways : [],

  canMakePayments(methodData: object) {
    return new Promise((resolve, reject) => {
      if (IS_ANDROID) {
        ReactNativePayments.canMakePayments(
          methodData,
          (err) => reject(err),
          (canMakePayments) => resolve(true)
        );

        return;
      }

      // On iOS, canMakePayments is exposed as a constant.
      resolve(ReactNativePayments.canMakePayments);
    });
  },

  // TODO based on Naoufal's talk on YouTube the intention of canMakePayments is for it to work like this, so I'm thinking we can integrate Yegor's code into canMakePayments.
  // NF 2020-11-18
  canMakePaymentsUsingNetworks(usingNetworks: []) {
    // IOS method to check that user has available cards at Apple Pay
    // https://developer.apple.com/documentation/passkit/pkpaymentauthorizationviewcontroller/1616187-canmakepaymentsusingnetworks?language=occ

    return new Promise((resolve) => {
      if (IS_ANDROID) {
        resolve(false);
      }

      ReactNativePayments.canMakePaymentsUsingNetworks(
        usingNetworks,
        (err, data) => resolve(data)
      );
    });
  },

  createPaymentRequest(methodData, details, options = {}) {
    return new Promise((resolve, reject) => {
      // Android Pay doesn't a PaymentRequest interface on the
      // Java side.  So we create and show Android Pay when
      // the user calls `.show`.
      if (IS_ANDROID) {
        return resolve();
      }

      ReactNativePayments.createPaymentRequest(
        methodData,
        details,
        options,
        err => {
          if (err) return reject(err);

          resolve();
        }
      );
    });
  },

  handleDetailsUpdate(details) {
    return new Promise((resolve, reject) => {
      // Android doesn't have display items, so we noop.
      // Users need to create a new Payment Request if they
      // need to update pricing.
      if (IS_ANDROID) {
        resolve(undefined);

        return;
      }

      ReactNativePayments.handleDetailsUpdate(details, err => {
        if (err) return reject(err);

        resolve();
      });
    });
  },

  show(methodData, details, options = {}) {
    return new Promise((resolve, reject) => {
      if (IS_ANDROID) {
        ReactNativePayments.show(
          methodData,
          details,
          options,
          (err) => reject(err),
          (...args) => { console.log(args); resolve(true) }
        );

        return;
      }

      ReactNativePayments.show((err, paymentToken) => {
        if (err) return reject(err);

        resolve(true);
      });
    });
  },

  abort() {
    return new Promise((resolve, reject) => {
      if (IS_ANDROID) {
        // TODO
        resolve(undefined);

        return;
      }

      ReactNativePayments.abort(err => {
        if (err) return reject(err);

        resolve(true);
      });
    });
  },

  complete(paymentStatus) {
    return new Promise((resolve, reject) => {
      // Android doesn't have a loading state, so we noop.
      if (IS_ANDROID) {
        resolve(undefined);

        return;
      }

      ReactNativePayments.complete(paymentStatus, err => {
        if (err) return reject(err);

        resolve(true);
      });
    });
  },

  getFullWalletAndroid(googleTransactionId: string, paymentMethodData: object, details: object): Promise<string> {
    return new Promise((resolve, reject) => {
      if (!IS_ANDROID) {
        reject(new Error('This method is only available on Android.'));

        return;
      }

      ReactNativePayments.getFullWalletAndroid(
        googleTransactionId,
        paymentMethodData,
        details,
        (err) => reject(err),
        (serializedPaymentToken) => resolve({
          serializedPaymentToken,
          paymentToken: JSON.parse(serializedPaymentToken),
          /** Leave previous typo in order not to create a breaking change **/
          serializedPaymenToken: serializedPaymentToken,
          paymenToken: JSON.parse(serializedPaymentToken)
        })
      );
    });
  }
};

export default NativePayments;