UNPKG

react-native-expo-braintree

Version:

React native and expo wrapper around braintree sdk fro android and ios

103 lines (96 loc) 5.78 kB
/* eslint-disable no-bitwise */ import { IOSConfig, withAppDelegate, withInfoPlist } from '@expo/config-plugins'; import eol from 'eol'; export const withExpoBraintreeAppDelegate = (expoConfig, { xCodeProjectAppName }) => { return withAppDelegate(expoConfig, config => { const appDelegate = config.modResults; let contents = eol.split(appDelegate.contents); // Step 1 Edit Import part // Editing import part for -swift.h file to be able to use Braintree const importSwiftHeaderFileContent = `#import "${xCodeProjectAppName}-Swift.h"`; const importSwiftHeaderFileIndex = contents.findIndex(content => content.includes(importSwiftHeaderFileContent)); // If importSwiftHeaderFileContent do not exist in AppDelegate.mm if (!~importSwiftHeaderFileIndex) { contents = [importSwiftHeaderFileContent, ...contents]; } const importExpoModulesSwiftHeader = `#import "ExpoModulesCore-Swift.h"`; const importExpoModulesSwiftHeaderFileIndex = contents.findIndex(content => content.includes(importExpoModulesSwiftHeader)); // If importExpoModulesSwiftHeader do not exist in AppDelegate.mm if (!~importExpoModulesSwiftHeaderFileIndex) { contents = [importExpoModulesSwiftHeader, ...contents]; } // Step 2 Add configure method in didFinishLaunchingWithOptions const didFinishLaunchingWithOptions = 'didFinishLaunchingWithOptions'; const expoBraintreeConfigureLine = ' [BraintreeExpoConfig configure];'; let didFinishLaunchingWithOptionsElementIndex = contents.findIndex(content => content.includes(didFinishLaunchingWithOptions)); const expoBraintreeConfigureLineIndex = contents.findIndex(content => content.includes(expoBraintreeConfigureLine)); // If didFinishLaunchingWithOptions exist in AppDelegate.mm and expoBraintreeConfigureLine do not exist if (!~expoBraintreeConfigureLineIndex && !!~didFinishLaunchingWithOptionsElementIndex) { contents.splice( // We are adding +2 to the index to insert content after '{' block didFinishLaunchingWithOptionsElementIndex + 2, 0, expoBraintreeConfigureLine); } // Step 3 Add method to properly handle openUrl method in AppDelegate.m const openUrlMethod = '- (BOOL)application:(UIApplication *)application openURL'; const expoBraintreeOpenUrlLines = [' if ([url.scheme localizedCaseInsensitiveCompare:[BraintreeExpoConfig getPaymentUrlScheme]] == NSOrderedSame) {', ' return [BraintreeExpoConfig handleUrl:url];', ' }']; const openUrlMethodElementIndex = contents.findIndex(content => content.includes(openUrlMethod)); const expoBraintreeOpenUrlLineIndex = contents.findIndex(content => content.includes(expoBraintreeOpenUrlLines?.[0] ?? '')); // If openUrlMethodElementIndex exist in AppDelegate.mm and expoBraintreeOpenUrlLineIndex do not exist if (!~expoBraintreeOpenUrlLineIndex && !!~openUrlMethodElementIndex) { contents.splice( // We are adding +1 to the index to insert content after '{' block openUrlMethodElementIndex + 1, 0, ...expoBraintreeOpenUrlLines); } config.modResults.contents = contents.join('\n'); return config; }); }; /** * Add a new wrapper Swift file to the Xcode project for Swift compatibility. */ export const withSwiftBraintreeWrapperFile = config => { return IOSConfig.XcodeProjectFile.withBuildSourceFile(config, { filePath: 'BraintreeExpoConfig.swift', contents: ['import Braintree', 'import Foundation', '', '@objc public class BraintreeExpoConfig: NSObject {', '', '@objc(configure)', 'public static func configure() {', ' BTAppContextSwitcher.sharedInstance.returnURLScheme = self.getPaymentUrlScheme()', '}', '', '@objc(getPaymentUrlScheme)', 'public static func getPaymentUrlScheme() -> String {', ' let bundleIdentifier = Bundle.main.bundleIdentifier ?? ""', ' return bundleIdentifier + ".braintree"', '}', '', '@objc(handleUrl:)', 'public static func handleUrl(url: URL) -> Bool {', ' return BTAppContextSwitcher.sharedInstance.handleOpen(url)', '}', '}'].join('\n') }); }; export const withExpoBraintreePlist = expoConfig => { return withInfoPlist(expoConfig, config => { const bundleIdentifier = config.ios?.bundleIdentifier ?? ''; const bundleIdentifierWithBraintreeSchema = `${bundleIdentifier}.braintree`; const bundleUrlTypes = config.modResults.CFBundleURLTypes ?? []; // Check if an entry with the specific Braintree URL scheme already exists const isBraintreeEntryNotExist = !bundleUrlTypes.find(urlType => { return urlType.CFBundleURLSchemes?.includes(bundleIdentifierWithBraintreeSchema); }); // If Braintree entry doesn't exist, add a new one if (isBraintreeEntryNotExist) { bundleUrlTypes.push({ CFBundleURLSchemes: [bundleIdentifierWithBraintreeSchema] }); } // Assign the modified bundleUrlTypes back to the config config.modResults.CFBundleURLTypes = bundleUrlTypes; return config; }); }; /* * Add allowlist Venmo URL scheme * @see https://developer.paypal.com/braintree/docs/guides/venmo/client-side/ios/v6#allowlist-venmo-url-scheme */ export const withVenmoScheme = expoConfig => { return withInfoPlist(expoConfig, config => { // Ensure LSApplicationQueriesSchemes exists in Info.plist config.modResults.LSApplicationQueriesSchemes = config.modResults.LSApplicationQueriesSchemes || []; // Hardcoded scheme for Venmo const venmoScheme = 'com.venmo.touch.v2'; // Add the Venmo scheme to the LSApplicationQueriesSchemes array if not already present if (!config.modResults.LSApplicationQueriesSchemes.includes(venmoScheme)) { config.modResults.LSApplicationQueriesSchemes.push(venmoScheme); } return config; }); }; //# sourceMappingURL=withExpoBraintree.ios.js.map