Skip to content

Commit

Permalink
PX-1826 3.8.0 release. (#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
tl-lukasz-franieczek authored Nov 6, 2024
1 parent 60d774d commit 4a01d6d
Show file tree
Hide file tree
Showing 11 changed files with 882 additions and 94 deletions.
644 changes: 644 additions & 0 deletions MigrateTo3.8.0.md

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ your environment from the dropdown.

You can also select between launching flows for payments in different currencies or mandates.


## :warning: **For SDK version 3.8.0+ go [here](./MigrateTo3.8.0.md)** :warning:

## How does the payment flow with the SDK works?

```mermaid
Expand Down
8 changes: 4 additions & 4 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ android {
}
compileOptions {
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
sourceCompatibility JavaVersion.VERSION_19
targetCompatibility JavaVersion.VERSION_19
}
kotlinOptions {
jvmTarget = '17'
jvmTarget = '19'
}
buildFeatures {
compose true
Expand Down Expand Up @@ -72,5 +72,5 @@ dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:$json_serialization_version"
implementation "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:$retrofit2_kotlinx_serialization"

implementation "com.truelayer.payments:ui:3.2.1"
implementation "com.truelayer.payments:ui:3.8.0"
}
10 changes: 7 additions & 3 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.INTERNET" />

<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
Expand All @@ -12,7 +14,7 @@
android:supportsRtl="true"
android:theme="@style/Theme.SDKDemo"
android:usesCleartextTraffic="true"
tools:targetApi="31">
tools:targetApi="34">
<activity
android:name=".MainActivity"
android:exported="true"
Expand Down Expand Up @@ -46,11 +48,13 @@
android:label="@string/integration_activity"/>
<activity
android:name=".integrations.ActivityXIntegrationActivity"
android:parentActivityName=".MainActivity"
android:label="@string/integration_activityx"/>
android:exported="true"
android:label="@string/integration_activityx">
</activity>
<activity
android:name=".integrations.ComposeIntegrationActivity"
android:theme="@style/Theme.SDKDemo.NoActionBar"
android:launchMode="singleTask"
android:parentActivityName=".MainActivity"/>
<activity
android:name=".integrations.JavaIntegrationActivity"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ import com.truelayer.payments.core.domain.configuration.HttpConnectionConfigurat
import com.truelayer.payments.core.domain.configuration.HttpLoggingLevel
import com.truelayer.payments.core.domain.utils.Fail
import com.truelayer.payments.core.domain.utils.Ok
import com.truelayer.payments.core.utils.extractTrueLayerRedirectParams
import com.truelayer.payments.ui.TrueLayerUI
import com.truelayer.payments.ui.screens.processor.ProcessorActivityContract
import com.truelayer.payments.ui.screens.processor.ProcessorContext
import com.truelayer.payments.ui.screens.processor.ProcessorResult
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
Expand All @@ -26,13 +28,10 @@ import kotlinx.coroutines.withContext
class ActivityIntegrationActivity : Activity() {

private val scope = CoroutineScope(Dispatchers.IO)
private lateinit var processorContextProvider: ProcessorContextProvider

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

processorContextProvider = ProcessorContextProvider(PrefUtils.getQuickstartUrl(this))

val binding = ActivityIntegrationBinding.inflate(layoutInflater)
setContentView(binding.root)

Expand All @@ -44,25 +43,49 @@ class ActivityIntegrationActivity : Activity() {
)
}

tryHandleIntentWithRedirectFromBankData(intent)

binding.launchButton.setOnClickListener {
scope.launch {
launchPaymentFlow()
}
}
}

override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
intent?.let {
tryHandleIntentWithRedirectFromBankData(it)
}
}

private fun tryHandleIntentWithRedirectFromBankData(intent: Intent) {
val params = intent.data.extractTrueLayerRedirectParams()
val storedProcessorContext = PrefUtils.getProcessorContext(this)
if (params.isNotEmpty() && storedProcessorContext != null &&
(storedProcessorContext.id == params["payment_id"] || storedProcessorContext.id == params["mandate_id"])) {
// The user is returning from the provider app
// and the payment/mandate ID matches the one we have stored
// so we can fetch the payment status
startPaymentActivity(storedProcessorContext)
}
}

private fun startPaymentActivity(processorContext: ProcessorContext) {
// Create an intent with the payment context to start the payment flow
val intent = ProcessorActivityContract().createIntent(this, processorContext)
// Start activity for result to receive the results of the payment flow
startActivityForResult(intent, 0)
}

private suspend fun launchPaymentFlow() {
val paymentType = PrefUtils.getPaymentType(this)
// Create a payment context
val processorContextProvider = ProcessorContextProvider(PrefUtils.getQuickstartUrl(this))
when (val processorContext = processorContextProvider.getProcessorContext(paymentType, this)) {
is Ok -> {
// Create an intent with the payment context to start the payment flow
val intent = ProcessorActivityContract().createIntent(
this@ActivityIntegrationActivity,
processorContext.value
)
// Start activity for result to receive the results of the payment flow
startActivityForResult(intent, 0)
PrefUtils.setIntegrationType(PrefUtils.IntegrationType.ACTIVITY, this@ActivityIntegrationActivity)
startPaymentActivity(processorContext.value)
}
is Fail -> withContext(Dispatchers.Main) {
// Display error if payment context creation failed
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package com.truelayer.demo.integrations

import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.appcompat.app.AppCompatActivity
import androidx.core.util.Consumer
import com.truelayer.demo.R
import com.truelayer.demo.databinding.ActivityIntegrationBinding
import com.truelayer.demo.payments.ProcessorContextProvider
Expand All @@ -12,6 +15,7 @@ import com.truelayer.payments.core.domain.configuration.HttpConnectionConfigurat
import com.truelayer.payments.core.domain.configuration.HttpLoggingLevel
import com.truelayer.payments.core.domain.utils.Fail
import com.truelayer.payments.core.domain.utils.Ok
import com.truelayer.payments.core.utils.extractTrueLayerRedirectParams
import com.truelayer.payments.ui.TrueLayerUI
import com.truelayer.payments.ui.screens.processor.ProcessorActivityContract
import com.truelayer.payments.ui.screens.processor.ProcessorContext
Expand All @@ -26,12 +30,11 @@ import kotlinx.coroutines.withContext
class ActivityXIntegrationActivity : AppCompatActivity() {

private val scope = CoroutineScope(Dispatchers.IO)
private lateinit var processorContextProvider: ProcessorContextProvider
private var newIntentConsumer: Consumer<Intent>? = null

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

processorContextProvider = ProcessorContextProvider(PrefUtils.getQuickstartUrl(this))
Log.e("ActivityXIntegrationActivity", "onCreate: $intent")

val binding = ActivityIntegrationBinding.inflate(layoutInflater)
setContentView(binding.root)
Expand All @@ -44,26 +47,65 @@ class ActivityXIntegrationActivity : AppCompatActivity() {
)
}

// Create a contract to receive the results
val contract = ProcessorActivityContract()

// Handle the result returned from the SDK at the end of the payment flow
val flow = registerForActivityResult(contract) {
Toast.makeText(this, it.toString(), Toast.LENGTH_LONG).show()
newIntentConsumer = Consumer<Intent> { intent ->
// extract payment id
Log.e("ActivityXIntegrationActivity", "newIntentConsumer: $intent")
val flow = registerFlow()
tryHandleIntentWithRedirectFromBankData(intent, flow)
}
newIntentConsumer?.let {
addOnNewIntentListener(it)
}

val flow = registerFlow()

tryHandleIntentWithRedirectFromBankData(intent, flow)

binding.launchButton.setOnClickListener {
scope.launch {
launchFlow(flow)
startNewPayment(flow)
}
}
}

private suspend fun launchFlow(flow: ActivityResultLauncher<ProcessorContext>) {
override fun onDestroy() {
super.onDestroy()
Log.e("ActivityXIntegrationActivity", "onDestroy")
newIntentConsumer?.let { removeOnNewIntentListener(it) }
}

private fun tryHandleIntentWithRedirectFromBankData(intent: Intent, flow: ActivityResultLauncher<ProcessorContext>) {
val params = intent.data.extractTrueLayerRedirectParams()
val storedProcessorContext = PrefUtils.getProcessorContext(this)
if (params.isNotEmpty() && storedProcessorContext != null &&
(storedProcessorContext.id == params["payment_id"] || storedProcessorContext.id == params["mandate_id"])) {
// The user is returning from the provider app
// and the payment/mandate ID matches the one we have stored
// so we can fetch the payment status
flow.launch(storedProcessorContext)
}
}

private fun registerFlow(): ActivityResultLauncher<ProcessorContext> {
// Create a contract to receive the results
val contract = ProcessorActivityContract()
// Handle the result returned from the SDK at the end of the payment flow
return registerForActivityResult(contract) {
Toast.makeText(this, it.toString(), Toast.LENGTH_LONG).show()
Log.e("ActivityXIntegrationActivity", it.toString())
}
}

private suspend fun startNewPayment(flow: ActivityResultLauncher<ProcessorContext>) {
val paymentType = PrefUtils.getPaymentType(this)

val processorContextProvider = ProcessorContextProvider(PrefUtils.getQuickstartUrl(this))
val processorContext = processorContextProvider.getProcessorContext(paymentType, this)

// Create a payment context
when (val processorContext = processorContextProvider.getProcessorContext(paymentType, this)) {
when (processorContext) {
is Ok -> {
PrefUtils.setIntegrationType(PrefUtils.IntegrationType.ACTIVITY_X, this@ActivityXIntegrationActivity)
// Start the payment flow
flow.launch(processorContext.value)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,10 @@ class ComposeIntegrationActivity : AppCompatActivity() {
var error by remember { mutableStateOf<String?>(null) }
LaunchedEffect(true) {
processorContextProvider.getProcessorContext(paymentType, this@ComposeIntegrationActivity)
.onOk { processorContext = it }
.onOk {
processorContext = it
PrefUtils.setIntegrationType(PrefUtils.IntegrationType.COMPOSE, this@ComposeIntegrationActivity)
}
.onError { error = it.localizedMessage }
}
Theme(
Expand Down
Loading

0 comments on commit 4a01d6d

Please sign in to comment.