Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Connect SDK] Integrate with backend calls for client secret #9287

Draft
wants to merge 1 commit into
base: simond/connect-sdk-example-app
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -188,6 +189,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,10 +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? {
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
Loading