Skip to content

Commit

Permalink
Integrate with backend calls for client secret
Browse files Browse the repository at this point in the history
  • Loading branch information
simond-stripe committed Sep 24, 2024
1 parent 23956f4 commit 132cadd
Show file tree
Hide file tree
Showing 16 changed files with 606 additions and 170 deletions.
2 changes: 2 additions & 0 deletions dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ ext.versions = [
tensorflowLite : '2.11.0',
tensorflowLiteSupport : '0.4.3',
testParameterInjector : '1.12',
timber : '5.0.1',
truth : '1.1.3',
turbine : '1.0.0',
uiAutomator : '2.2.0',
Expand Down Expand Up @@ -189,6 +190,7 @@ ext.libs = [
tensorflowLiteSupport : "org.tensorflow:tensorflow-lite-support:${versions.tensorflowLiteSupport}",
tensorflowLitePlayServices : "com.google.android.gms:play-services-tflite-java:${versions.playServicesTfLite}",
tensorflowLitePlayServicesSupport : "com.google.android.gms:play-services-tflite-support:${versions.playServicesTfLite}",
timber : "com.jakewharton.timber:timber:${versions.timber}",
zxing : "com.google.zxing:core:${versions.zxing}",
]

Expand Down
8 changes: 8 additions & 0 deletions stripe-connect-example/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,20 @@ apply plugin: 'org.jetbrains.kotlin.plugin.serialization'

dependencies {
implementation project(":stripe-connect")
implementation project(':stripe-core')

// Kotlin
implementation libs.kotlin.coroutines
implementation libs.kotlin.coroutinesAndroid
implementation libs.kotlin.serialization

// Networking
implementation libs.fuel
implementation libs.fuelCoroutines

// Logging
implementation libs.timber

// AndroidX
implementation libs.androidx.activity
implementation libs.androidx.annotation
Expand Down
10 changes: 7 additions & 3 deletions stripe-connect-example/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>

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

<application android:name=".App">
<activity
android:name=".MainActivity"
android:exported="true"
Expand All @@ -12,11 +16,11 @@
</activity>

<activity
android:name=".ui.accountonboarding.AccountOnboardingExampleActivity"
android:name=".ui.features.accountonboarding.AccountOnboardingExampleActivity"
android:exported="false"
android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
<activity
android:name=".ui.payouts.PayoutsExampleActivity"
android:name=".ui.features.payouts.PayoutsExampleActivity"
android:exported="false"
android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
</application>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.stripe.android.connectsdk.example

import android.app.Application
import android.os.StrictMode
import timber.log.Timber

class App: Application() {
override fun onCreate() {
super.onCreate()

StrictMode.setThreadPolicy(
StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectAll()
.penaltyLog()
.build()
)

StrictMode.setVmPolicy(
StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
.detectLeakedClosableObjects()
.penaltyLog()
.build()
)

if (BuildConfig.DEBUG) {
Timber.plant(Timber.DebugTree())
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ import androidx.compose.ui.text.style.LineHeightStyle
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.stripe.android.connectsdk.example.ui.accountonboarding.AccountOnboardingExampleActivity
import com.stripe.android.connectsdk.example.ui.payouts.PayoutsExampleActivity
import com.stripe.android.connectsdk.example.ui.features.accountonboarding.AccountOnboardingExampleActivity
import com.stripe.android.connectsdk.example.ui.features.payouts.PayoutsExampleActivity

class MainActivity : ComponentActivity() {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,89 @@
package com.stripe.android.connectsdk.example.networking

import kotlinx.coroutines.delay
import com.github.kittinunf.fuel.core.Deserializable
import com.github.kittinunf.fuel.core.FuelError
import com.github.kittinunf.fuel.core.FuelManager
import com.github.kittinunf.fuel.core.Request
import com.github.kittinunf.fuel.core.Response
import com.github.kittinunf.fuel.core.awaitResult
import com.github.kittinunf.result.Result
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json

class EmbeddedComponentService {
suspend fun fetchClientSecret(): String? {
// TODO MXMOBILE-2511 - add backend call
delay(3000)
return null
private val fuel = FuelManager.instance
.apply {
// add logging
addRequestInterceptor(TimberRequestLogger("EmbeddedComponentService"))
addResponseInterceptor(TimberResponseLogger("EmbeddedComponentService"))

// add headers
addRequestInterceptor(ApplicationJsonHeaderInterceptor)
addRequestInterceptor(UserAgentHeader)
}

/**
* Returns the publishable key for use in the Stripe Connect SDK as well as a list
* of available merchants. Throws a [FuelError] exception on network issues and other errors.
*/
suspend fun getAccounts(): GetAccountsResponse {
return fuel.get(EXAMPLE_BACKEND_URL + "app_info")
.awaitModel(GetAccountsResponse.serializer())
.get()
}

/**
* Returns the client secret for the given merchant account to be used in the Stripe Connect SDK.
* Throws a [FuelError] exception on network issues and other errors.
*/
suspend fun fetchClientSecret(account: String): String {
return fuel.post(EXAMPLE_BACKEND_URL + "account_session")
.header("account", account)
.awaitModel(FetchClientSecretResponse.serializer())
.get()
.clientSecret
}

companion object {
private const val EXAMPLE_BACKEND_URL = "https://stripe-connect-mobile-example-v1.glitch.me/"
}
}

@Serializable
data class FetchClientSecretResponse(
@SerialName("client_secret")
val clientSecret: String
)

@Serializable
data class GetAccountsResponse(
@SerialName("publishable_key")
val publishableKey: String,
@SerialName("available_merchants")
val availableMerchants: List<Merchant>
)

@Serializable
data class Merchant(
@SerialName("merchant_id")
val merchantId: String,
@SerialName("display_name")
val displayName: String
)

suspend fun <T : Any> Request.awaitModel(
serializer: DeserializationStrategy<T>
): Result<T, FuelError> {
val deserializer = object : Deserializable<T> {

override fun deserialize(response: Response): T {
println(response.toString())
val body = response.body().asString("application/json")
return Json.decodeFromString(serializer, body)
}
}

return awaitResult(deserializer)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.stripe.android.connectsdk.example.networking

import android.os.Build
import com.github.kittinunf.fuel.core.FoldableRequestInterceptor
import com.github.kittinunf.fuel.core.FoldableResponseInterceptor
import com.github.kittinunf.fuel.core.RequestTransformer
import com.github.kittinunf.fuel.core.ResponseTransformer
import com.github.kittinunf.fuel.core.extensions.cUrlString
import com.stripe.android.core.version.StripeSdkVersion
import timber.log.Timber

object ApplicationJsonHeaderInterceptor : FoldableRequestInterceptor {
override fun invoke(next: RequestTransformer): RequestTransformer {
return { request ->
next(request.header("content-type", "application/json"))
}
}
}

object UserAgentHeader : FoldableRequestInterceptor {
fun getUserAgent(): String {
val androidBrand = Build.BRAND
val androidDevice = Build.MODEL
val osVersion = Build.VERSION.SDK_INT
return buildString {
append("Stripe/ConnectSDKExample")
append(" (Android $androidBrand $androidDevice; (OS Version $osVersion))+")
append(" Version/${StripeSdkVersion.VERSION_NAME}")
}
}

override fun invoke(next: RequestTransformer): RequestTransformer {
return { request ->
next(request.header("User-Agent", getUserAgent()))
}
}
}

class TimberRequestLogger(private val tag: String) : FoldableRequestInterceptor {
private val timber get() = Timber.tag(tag)

override fun invoke(next: RequestTransformer): RequestTransformer {
return { request ->
timber.i("Request: ${request.cUrlString()}")
next(request)
}
}
}

class TimberResponseLogger(private val tag: String) : FoldableResponseInterceptor {
private val timber get() = Timber.tag(tag)

override fun invoke(next: ResponseTransformer): ResponseTransformer {
return { request, response ->
timber.i("Response: $response")
next(request, response)
}
}
}

This file was deleted.

This file was deleted.

Loading

0 comments on commit 132cadd

Please sign in to comment.