Here is an example project on how to integrate the existing native Android and iOS SDKs into a React Native app.
- Add the latest gradle dependency into the Android app module build file
To access the dependency you must first create Github personal access token
Once that is done you must add the following repository to your root build.gradle file
allprojects {
repositories {
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/banked/banked-android-sdk")
credentials {
username = <enter your username here>
password = <enter your PAT token here>
}
}
}
}
You can then access the artifact from the following
implementation("com.banked:checkout:2.0.4")
- Add an intent filter into the application manin activity so that the SDK can receive events from the banking providers
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="<host>"
android:scheme="<scheme>" />
</intent-filter>
- Create a
ReactContextBaseJavaModule
to bridge between the React Native code and call into the Banked SDK Android code
public class BankedSdkModule extends ReactContextBaseJavaModule {
public BankedSdkModule(ReactApplicationContext reactContext) {
super(reactContext);
}
@NonNull
@Override
public String getName() {
return "BankedSdk";
}
@ReactMethod
void initialise(String apiKey) {
Banked.setApiKey(apiKey);
}
@ReactMethod
void openBankedSdk(String paymentId, String continueUrl) {
final FragmentActivity activity = (FragmentActivity) getCurrentActivity();
Banked.startPayment(activity, paymentId, continueUrl);
}
}
- Create a
ReactPackage
to register and use the customReactContextBaseJavaModule
class above
public class BankedReactPackage implements ReactPackage {
@NonNull
@Override
public List<NativeModule> createNativeModules(@NonNull ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new BankedSdkModule(reactContext));
return modules;
}
@NonNull
@Override
public List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}
- Register the
ReactPackage
in theReactNativeHost
declared in the AndroidApplication
class.
private final ReactNativeHost mReactNativeHost =
new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
packages.add(new BankedReactPackage());
return packages;
}
@Override
protected String getJSMainModuleName() {
return "index";
}
};
- Add the Banked SDK lifecycle callback and add the payment session listener in your MainActivity
public class MainActivity extends ReactActivity implements OnPaymentSessionListener {
/**
* Returns the name of the main component registered from JavaScript. This is used to schedule
* rendering of the component.
*/
@Override
protected String getMainComponentName() {
return "BankedReactNativeExample";
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Banked.setOnPaymentSessionListener(this);
}
@Override
protected void onStart() {
super.onStart();
Banked.onStart(this);
}
@Override
public void onPaymentFailed(PaymentResult paymentResult) {
displayJavascriptAlert("Payment failed");
}
@Override
public void onPaymentSuccess(PaymentResult paymentResult) {
displayJavascriptAlert("Payment success");
}
@Override
public void onPaymentAborted() {
Log.d("Banked", "onPaymentAborted");
}
private void displayJavascriptAlert(String message) {
MainApplication application = (MainApplication) getApplication();
ReactNativeHost reactNativeHost = application.getReactNativeHost();
ReactInstanceManager reactInstanceManager = reactNativeHost.getReactInstanceManager();
ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
if (reactContext != null) {
CatalystInstance catalystInstance = reactContext.getCatalystInstance();
WritableNativeArray params = new WritableNativeArray();
params.pushString(message);
catalystInstance.callFunction("JavaScriptExposedAlert", "alert", params);
}
}
}
More information on how to integrate Android SDK in an application can be found at https://github.com/banked/banked-android-sdk-examples
- Use Cocoapods to install the Banked Checkout SDK
To integrate Banked Checkout SDK into your Xcode project using CocoaPods, specify it in your Podfile:
pod ‘Banked’
Note: Banked is dynamic framework (with some dependecies, like Sentry) but Cocoapods builds pods by default as static libraries. To use a framework like this we’d normally use the use_frameworks!
. However, this causes all pods to be compiled as dynamic frameworks which won't work for all React Native pods. To avoid this you can use plugin like cocoapods-user-defined-build-types
Full explanation of this problem here: [Swift Dynamic Frameworks & React Native] (https://medium.com/@joncardasis/swift-dynamic-frameworks-react-native-3d77c4972f32)
You will have to modify your Gemfile
in the root folder and add something like gem 'cocoapods-user-defined-build-types'
. Then run bundle install
.
Add this to the top of your Podfile
:
plugin 'cocoapods-user-defined-build-types'
enable_user_defined_build_types!
And to use the proper pod add:
pod 'Banked', :build_type => :dynamic_framework
Because Banked is an XCFramework, we also need iOS13, so in your Podfile add this: platform :ios, '13.0'
.
- Create
BankedCheckoutWrapper.swift
to bridge between Banked iOS SDK and Objective-C
import Foundation
import UIKit
import Banked
@objc class BankedCheckoutWrapper: NSObject {
@objc static let shared: BankedCheckoutWrapper = BankedCheckoutWrapper()
@objc func setUp(apiKey: String) {
BankedCheckout.shared.setUp(apiKey)
}
@objc func presentCheckout(viewController: UIViewController ,paymentId: String, continueURL: String) {
BankedCheckout.shared.presentCheckout(viewController , paymentId: paymentId, action: .pay, continueURL: continueURL) { response in
switch response {
case .success:
print("success")
case .failure(let error):
print("error \(error)")
}
}
}
@objc func handlePayment(url: URL) {
BankedCheckout.shared.handlePaymentWithURL(url, action: .pay) { response in
switch response {
case .success:
print("success")
case .failure(let error):
print("error \(error)")
}
}
}
}
- Create
BankedSdk
Objective-C class to bridge between the React Native code and call into theBankedCheckoutWrapper
.
Add the following to BankedSdk.h:
#import <Foundation/Foundation.h>
#import "React/RCTBridge.h"
NS_ASSUME_NONNULL_BEGIN
@interface BankedSdk : NSObject <RCTBridgeModule>
@end
NS_ASSUME_NONNULL_END
Next up, implemennt the native module as follows:
#import "BankedSdk.h"
#import "React/RCTLog.h"
#import "BankedReactNativeExample-Swift.h"
@implementation BankedSdk
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(initialise:(NSString *)apiKey)
{
[[BankedCheckoutWrapper shared] setUpWithApiKey: apiKey];
}
RCT_EXPORT_METHOD(openBankedSdk:(NSString *)paymentId and:(NSString *)continueUrl)
{
dispatch_async(dispatch_get_main_queue(), ^{
UIViewController *presentedViewController = RCTPresentedViewController();
[[BankedCheckoutWrapper shared] presentCheckoutWithViewController: presentedViewController paymentId: paymentId continueURL: continueUrl];
});
}
RCT_EXPORT_METHOD(handlePaymentForURL:(NSURL *)url)
{
[[BankedCheckoutWrapper shared] handlePaymentWithUrl: url];
}
@end