Skip to content

Commit

Permalink
PX-1137 Release 2.0.0 (#74)
Browse files Browse the repository at this point in the history
Co-authored-by: tl-daven-gomes <[email protected]>
Co-authored-by: Daven Gomes <[email protected]>
  • Loading branch information
3 people authored Mar 6, 2024
1 parent cb6f371 commit b961748
Show file tree
Hide file tree
Showing 45 changed files with 2,787 additions and 2,296 deletions.
17 changes: 12 additions & 5 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ orbs:
node: circleci/[email protected]
android: circleci/[email protected]
rn: react-native-community/[email protected]
macos: circleci/[email protected]

executors:
base_executor:
Expand Down Expand Up @@ -89,7 +90,7 @@ jobs:
- android/create-avd:
avd-name: test
install: true
system-image: "system-images;android-23;default;x86"
system-image: "system-images;android-24;default;x86"
- android/start-emulator:
avd-name: test
post-emulator-launch-assemble-command: "" # this can now be empty as the build was done in build-all step
Expand All @@ -114,12 +115,16 @@ jobs:
build-ios-demo-app:
macos:
xcode: 15.0.1
xcode: 15.2.0
resource_class: macos.m1.large.gen1
working_directory: /Users/distiller/project

steps:
- checkout
- macos/add-uitest-permissions
- macos/add-permission:
bundle-id: "com.apple.CoreSimulator.SimulatorTrampoline"
permission-type: "kTCCServiceMicrophone"
- run:
name: Setup quick-start service
command: |
Expand All @@ -142,22 +147,24 @@ jobs:
yarn build
yalc publish
- run:
name: Install DemoApp dependencies
name: Install DemoApp dependencies and start server
command: |
cd /Users/distiller/project/DemoApp
npx yalc add rn-truelayer-payments-sdk
yarn install
yarn start
background: true
- run:
name: build ios
command: |
cd /Users/distiller/project/DemoApp/ios
bundle install
gem install cocoapods
bundle exec pod install
RCT_NEW_ARCH_ENABLED=1 bundle exec pod install
cd /Users/distiller/project/DemoApp
yarn react-native bundle --entry-file index.js --platform ios --dev false --bundle-output ios/main.jsbundle --assets-dest ios
cd ios
xcodebuild -workspace DemoApp.xcworkspace -scheme DemoAppUITests -destination 'platform=iOS Simulator,name=iPhone 15 Pro,OS=17.0.1' -configuration Debug test
xcodebuild -workspace DemoApp.xcworkspace -scheme DemoAppUITests -destination 'platform=iOS Simulator,name=iPhone 15 Pro,OS=17.2' -configuration Debug test
workflows:
version: 2
Expand Down
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
# CHANGELOG
All notable changes to this project will be documented in this file. To know better on how to write and maintain a changelog, refer to [this link](https://keepachangelog.com/en/1.0.0/).

## [2.0.0]

### Added

- `shouldPresentResultScreen` to `PaymentPreferences` and `MandatePreferences`. When this is enabled, a result screen is displayed at the end of the authorization flow. When the user is redirected back from the bank, it is recommended to re-invoke the SDK to display the result screen, to show the user the status of their payment or mandate. This is enabled by default.
- `waitTimeMillis` to `PaymentPreferences` and `MandatePreferences`. This is the maximum timeout for the payment or mandate result screen, until a final status. Once reached, the user is shown a button to dismiss the SDK and return to your app.
- New `FailureReason` cases. These more accurately reflect the reasons returned from TrueLayer Payments API V3.

### Changed

- Updated the underlying iOS SDK to version [3.0.1](https://github.com/TrueLayer/TrueLayer-iOS-SDK/releases/tag/3.0.1).
- Updated the underlying Android SDK to version [3.0.1](https://docs.truelayer.com/docs/android-sdk-release-history).

### Removed

- `paymentUseCase` from `PaymentPreferences`. To enable Signup+ for a payment, refer to the API documentation when creating a payment.

## [1.4.0]

### Changed
Expand Down
155 changes: 107 additions & 48 deletions DemoApp/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,25 @@ import {
Text,
useColorScheme,
View,
Linking,
Alert
} from 'react-native'

import React from 'react'

import AsyncStorage from '@react-native-async-storage/async-storage'

import {
TrueLayerPaymentsSDKWrapper,
Environment,
PaymentUseCase,
ResultType,
} from 'rn-truelayer-payments-sdk'

import uuid from 'react-native-uuid'
import {Colors} from 'react-native/Libraries/NewAppScreen'
import {log} from './utils/logger'
import { Colors } from 'react-native/Libraries/NewAppScreen'
import { log } from './utils/logger'

function App(): JSX.Element {
function App(): React.JSX.Element {
const isDarkMode = useColorScheme() === 'dark'

const backgroundStyle = {
Expand Down Expand Up @@ -56,6 +59,20 @@ function App(): JSX.Element {
ios: iOSTheme,
}

const getUrlAsync = async () => {
// Get the deep link used to open the app
const initialUrl = await Linking.getInitialURL()
if(initialUrl) {
handleRedirect(initialUrl)
}
}

getUrlAsync()

Linking.addEventListener("url", (event) => {
handleRedirect(event.url)
})

return (
<SafeAreaView style={backgroundStyle}>
<StatusBar
Expand Down Expand Up @@ -87,17 +104,22 @@ function App(): JSX.Element {
Start SDK
</Text>
</Pressable>
<Pressable style={styles.button} onPress={processPayment}>
<Text testID={'processPayment'} style={styles.text}>
Process Single Payment
<Pressable style={styles.button} onPress={() => createAndProcessPayment('GBP')}>
<Text testID={'processPaymentGBP'} style={styles.text}>
Process Single Payment GBP
</Text>
</Pressable>
<Pressable style={styles.button} onPress={() => createAndProcessPayment('EUR')}>
<Text testID={'processPaymentEUR'} style={styles.text}>
Process Single Payment EUR
</Text>
</Pressable>
<Pressable style={styles.button} onPress={getSinglePaymentStatus}>
<Text testID={'getPayment'} style={styles.text}>
Get Single Payment Status
</Text>
</Pressable>
<Pressable style={styles.button} onPress={processMandate}>
<Pressable style={styles.button} onPress={createAndProcessMandate}>
<Text testID={'processMandate'} style={styles.text}>
Process Mandate
</Text>
Expand All @@ -112,37 +134,43 @@ function App(): JSX.Element {
)
}

function processPayment(): void {
log('processPayment button clicked')
const redirectUri = 'truelayer://payments_sample'

getPaymentContext('payment').then(processorContext => {
function createAndProcessPayment(currency: 'GBP' | 'EUR'): void {
log(`processPayment button clicked for ${currency}`)

const type = currency == 'GBP' ? 'payment' : 'payment/euro'

getPaymentContext(type).then(processorContext => {
log(
`payment`,
`id: ${processorContext.id}`,
`resource_token: ${processorContext.resource_token}`,
)
processPayment(processorContext)
})
}

TrueLayerPaymentsSDKWrapper.processPayment(
{
paymentId: processorContext.id,
resourceToken: processorContext.resource_token,
redirectUri: 'truelayer://payments_sample',
},
{
paymentUseCase: PaymentUseCase.Send,
},
).then(result => {
switch (result.type) {
case ResultType.Success:
log(`processPayment success at step: ${result.step}`)
break
case ResultType.Failure:
log(
`Oh we've failed processPayment with following reason: ${result.reason}`,
)
break
}
})
function processPayment(processorContext: SamplePaymentContext) {
AsyncStorage.setItem('@Store:context', JSON.stringify(processorContext))

TrueLayerPaymentsSDKWrapper.processPayment(
{
paymentId: processorContext.id,
resourceToken: processorContext.resource_token,
redirectUri: 'truelayer://payments_sample',
},
).then(result => {
switch (result.type) {
case ResultType.Success:
log(`processPayment success at step: ${result.step}`)
break
case ResultType.Failure:
log(
`Oh we've failed processPayment with following reason: ${result.reason}`,
)
break
}
})
}

Expand Down Expand Up @@ -173,7 +201,7 @@ function getSinglePaymentStatus(): void {
})
}

function processMandate(): void {
function createAndProcessMandate(): void {
log('processMandate button clicked')

getPaymentContext('mandate').then(processorContext => {
Expand All @@ -182,22 +210,30 @@ function processMandate(): void {
`id: ${processorContext.id}`,
`resource_token: ${processorContext.resource_token}`,
)
TrueLayerPaymentsSDKWrapper.processMandate({
processMandate(processorContext)
})
}

function processMandate(processorContext: SamplePaymentContext): void {
AsyncStorage.setItem('@Store:context', JSON.stringify(processorContext))

TrueLayerPaymentsSDKWrapper.processMandate(
{
mandateId: processorContext.id,
resourceToken: processorContext.resource_token,
redirectUri: 'truelayer://payments_sample',
}).then(result => {
switch (result.type) {
case ResultType.Success:
log(`processMandate success at step: ${result.step}`)
break
case ResultType.Failure:
log(
`Oh we've failed processMandate with following reason: ${result.reason}`,
)
break
}
})
redirectUri: redirectUri
}
).then(result => {
switch (result.type) {
case ResultType.Success:
log(`processMandate success at step: ${result.step}`)
break
case ResultType.Failure:
log(
`Oh we've failed processMandate with following reason: ${result.reason}`,
)
break
}
})
}

Expand Down Expand Up @@ -228,6 +264,29 @@ function getMandateStatus(): void {
})
}

async function handleRedirect(url: string) {
// launch result screen
const isPayment = url.includes("payment_id")
const isMandate = url.includes("mandate_id")

const savedContext = await AsyncStorage.getItem('@Store:context')

if(savedContext != null) {
const processorContext = JSON.parse(savedContext)
if(isPayment) {
// relaunch sdk with processPayment
processPayment(processorContext)
}
else if (isMandate) {
// relaunch sdk with processMandate
processMandate(processorContext)
}
else {
Alert.alert("Error", "Invalid deep link received", [{ text: "OK" }])
}
}
}

interface SamplePaymentContext {
id: string
resource_token: string
Expand All @@ -238,7 +297,7 @@ interface SamplePaymentContext {
* Amend the url to match your instance.
*/
async function getPaymentContext(
type: 'mandate' | 'payment',
type: 'mandate' | 'payment' | 'payment/euro',
): Promise<SamplePaymentContext> {
return await fetch('http://localhost:3000/v3/' + type, {
method: 'POST',
Expand Down
6 changes: 4 additions & 2 deletions DemoApp/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@ source 'https://rubygems.org'
# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
ruby ">= 2.6.10"

gem 'cocoapods', '~> 1.13'
gem 'activesupport', '>= 6.1.7.3', '< 7.1.0'
# Cocoapods 1.15 introduced a bug which break the build. We will remove the upper
# bound in the template on Cocoapods with next React Native release.
gem 'cocoapods', '>= 1.13', '< 1.15'
gem 'activesupport', '>= 6.1.7.5', '< 7.1.0'
4 changes: 2 additions & 2 deletions DemoApp/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ PLATFORMS
ruby

DEPENDENCIES
activesupport (>= 6.1.7.3, < 7.1.0)
cocoapods (~> 1.13)
activesupport (>= 6.1.7.5, < 7.1.0)
cocoapods (>= 1.13, < 1.15)

RUBY VERSION
ruby 2.6.10p210
Expand Down
2 changes: 1 addition & 1 deletion DemoApp/__tests__/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import 'react-native'
import React from 'react'
import App from '../App'

// Note: import explicitly to use the types shiped with jest.
// Note: import explicitly to use the types shipped with jest.
import {it} from '@jest/globals'

// Note: test renderer must be required after react-native.
Expand Down
13 changes: 5 additions & 8 deletions DemoApp/android/app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
apply plugin: "com.android.application"
apply plugin: "org.jetbrains.kotlin.android"
apply plugin: "com.facebook.react"

/**
Expand Down Expand Up @@ -71,7 +72,8 @@ def jscFlavor = 'org.webkit:android-jsc:+'
android {
ndkVersion rootProject.ext.ndkVersion

compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
compileSdk rootProject.ext.compileSdkVersion

namespace "com.demoapp"
defaultConfig {
Expand Down Expand Up @@ -118,13 +120,8 @@ dependencies {

// The version of react-native is set by the React Native Gradle Plugin
implementation("com.facebook.react:react-android")

debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}")
debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
exclude group:'com.squareup.okhttp3', module:'okhttp'
}

debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}")
implementation("com.facebook.react:flipper-integration")

if (hermesEnabled.toBoolean()) {
implementation("com.facebook.react:hermes-android")
} else {
Expand Down
Loading

0 comments on commit b961748

Please sign in to comment.