Skip to content

Commit

Permalink
Fetch available incentives after linking bank account
Browse files Browse the repository at this point in the history
  • Loading branch information
tillh-stripe committed Dec 9, 2024
1 parent ab9e133 commit 3be015b
Show file tree
Hide file tree
Showing 14 changed files with 131 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,9 @@ internal class FinancialConnectionsSheetViewModel @Inject constructor(
instantDebits = InstantDebitsResult(
encodedPaymentMethod = paymentMethod,
last4 = url.getQueryParameter(QUERY_PARAM_LAST4),
bankName = url.getQueryParameter(QUERY_BANK_NAME)
bankName = url.getQueryParameter(QUERY_BANK_NAME),
// TODO(tillh-stripe): Pull this from the URL
eligibleForIncentive = false,
),
financialConnectionsSession = null,
token = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,26 @@ internal class RealCreateInstantDebitsResult @Inject constructor(
)
}

val incentiveEligibilitySessionId = elementsSessionContext?.incentiveEligibilitySession?.id

val eligibleForIncentive = if (incentiveEligibilitySessionId != null) {
val availableIncentives = runCatching {
consumerRepository.updateAvailableIncentives(
sessionId = incentiveEligibilitySessionId,
consumerSessionClientSecret = clientSecret,
)
}.getOrNull()

availableIncentives?.data?.isNotEmpty() == true
} else {
false
}

return InstantDebitsResult(
encodedPaymentMethod = paymentMethod,
bankName = paymentDetails.bankName,
last4 = paymentDetails.last4,
eligibleForIncentive = eligibleForIncentive,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,6 @@ internal sealed class FinancialConnectionsSheetActivityResult : Parcelable {
internal data class InstantDebitsResult(
val encodedPaymentMethod: String,
val last4: String?,
val bankName: String?
val bankName: String?,
val eligibleForIncentive: Boolean,
) : Parcelable
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class FinancialConnectionsSheetForInstantDebitsContract :
encodedPaymentMethod = instantDebits.encodedPaymentMethod,
last4 = instantDebits.last4,
bankName = instantDebits.bankName,
eligibleForIncentive = instantDebits.eligibleForIncentive,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,14 @@ import kotlinx.parcelize.Parcelize
sealed class FinancialConnectionsSheetInstantDebitsResult : Parcelable {
/**
* The customer completed the connections session.
* @param paymentMethodId The payment method id, that can be used to confirm the payment.
* @param last4 The last 4 digits of the bank account.
* @param bankName The name of the bank.
*/
@Parcelize
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
data class Completed(
val encodedPaymentMethod: String,
val last4: String?,
val bankName: String?
val bankName: String?,
val eligibleForIncentive: Boolean,
) : FinancialConnectionsSheetInstantDebitsResult()

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import com.stripe.android.model.ConsumerSessionSignup
import com.stripe.android.model.ConsumerSignUpConsentAction.EnteredPhoneNumberClickedSaveToLink
import com.stripe.android.model.CustomEmailType
import com.stripe.android.model.SharePaymentDetails
import com.stripe.android.model.UpdateAvailableIncentives
import com.stripe.android.model.VerificationType
import com.stripe.android.repository.ConsumersApiService
import kotlinx.coroutines.sync.Mutex
Expand Down Expand Up @@ -69,6 +70,11 @@ internal interface FinancialConnectionsConsumerSessionRepository {
billingPhone: String?,
): SharePaymentDetails

suspend fun updateAvailableIncentives(
sessionId: String,
consumerSessionClientSecret: String,
): UpdateAvailableIncentives

companion object {
operator fun invoke(
consumersApiService: ConsumersApiService,
Expand Down Expand Up @@ -238,6 +244,18 @@ private class FinancialConnectionsConsumerSessionRepositoryImpl(
).getOrThrow()
}

override suspend fun updateAvailableIncentives(
sessionId: String,
consumerSessionClientSecret: String,
): UpdateAvailableIncentives {
return consumersApiService.updateAvailableIncentives(
sessionId = sessionId,
consumerSessionClientSecret = consumerSessionClientSecret,
requestSurface = requestSurface,
requestOptions = provideApiRequestOptions(useConsumerPublishableKey = true),
).getOrThrow()
}

private suspend fun postConsumerSession(
email: String,
clientSecret: String
Expand Down Expand Up @@ -266,6 +284,9 @@ private class FinancialConnectionsConsumerSessionRepositoryImpl(
signup: ConsumerSessionSignup,
) {
logger.debug("SYNC_CACHE: updating local consumer session from signUp")
consumerSessionRepository.storeNewConsumerSession(signup.consumerSession, signup.publishableKey)
consumerSessionRepository.storeNewConsumerSession(
consumerSession = signup.consumerSession,
publishableKey = signup.publishableKey,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ sealed interface CollectBankAccountForInstantDebitsResult : Parcelable {
val intent: StripeIntent?,
val paymentMethod: PaymentMethod,
val last4: String?,
val bankName: String?
val bankName: String?,
val eligibleForIncentive: Boolean,
) : CollectBankAccountForInstantDebitsResult

@Parcelize
Expand Down Expand Up @@ -51,7 +52,8 @@ internal fun CollectBankAccountResultInternal.toInstantDebitsResult(): CollectBa
intent = response.intent,
paymentMethod = response.instantDebitsData.paymentMethod,
last4 = response.instantDebitsData.last4,
bankName = response.instantDebitsData.bankName
bankName = response.instantDebitsData.bankName,
eligibleForIncentive = response.instantDebitsData.eligibleForIncentive,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ data class CollectBankAccountResponseInternal(
data class InstantDebitsData(
val paymentMethod: PaymentMethod,
val last4: String?,
val bankName: String?
val bankName: String?,
val eligibleForIncentive: Boolean,
) : StripeModel
}
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ internal class CollectBankAccountViewModel @Inject constructor(
paymentMethod = it,
last4 = result.last4,
bankName = result.bankName,
eligibleForIncentive = result.eligibleForIncentive,
)
},
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,19 @@ package com.stripe.android.model
import androidx.annotation.RestrictTo
import com.stripe.android.core.model.StripeModel
import kotlinx.parcelize.Parcelize
import kotlinx.serialization.Serializable

@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@Parcelize
@Serializable
data class LinkConsumerIncentive(
val incentiveParams: IncentiveParams,
val incentiveDisplayText: String?,
) : StripeModel {

@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@Parcelize
@Serializable
data class IncentiveParams(
val paymentMethod: String,
) : StripeModel
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.stripe.android.model

import androidx.annotation.RestrictTo
import com.stripe.android.core.model.StripeModel
import kotlinx.parcelize.Parcelize
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@Parcelize
@Serializable
data class UpdateAvailableIncentives(
@SerialName("data") val data: List<LinkConsumerIncentive>,
) : StripeModel
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.stripe.android.model.parsers

import androidx.annotation.RestrictTo
import com.stripe.android.core.model.parsers.ModelJsonParser
import com.stripe.android.model.UpdateAvailableIncentives
import org.json.JSONObject

@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
object UpdateAvailableIncentivesJsonParser : ModelJsonParser<UpdateAvailableIncentives> {

override fun parse(json: JSONObject): UpdateAvailableIncentives? {
val incentives = json.optJSONArray("data")?.let { data ->
List(data.length()) { index ->
LinkConsumerIncentiveJsonParser.parse(data.getJSONObject(index))
}
}

return incentives?.let {
UpdateAvailableIncentives(data = it.filterNotNull())
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ import com.stripe.android.model.ConsumerSignUpConsentAction
import com.stripe.android.model.CustomEmailType
import com.stripe.android.model.IncentiveEligibilitySession
import com.stripe.android.model.SharePaymentDetails
import com.stripe.android.model.UpdateAvailableIncentives
import com.stripe.android.model.VerificationType
import com.stripe.android.model.parsers.AttachConsumerToLinkAccountSessionJsonParser
import com.stripe.android.model.parsers.ConsumerPaymentDetailsJsonParser
import com.stripe.android.model.parsers.ConsumerSessionJsonParser
import com.stripe.android.model.parsers.ConsumerSessionLookupJsonParser
import com.stripe.android.model.parsers.ConsumerSessionSignupJsonParser
import com.stripe.android.model.parsers.SharePaymentDetailsJsonParser
import com.stripe.android.model.parsers.UpdateAvailableIncentivesJsonParser
import java.util.Locale

@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
Expand Down Expand Up @@ -91,6 +93,13 @@ interface ConsumersApiService {
requestOptions: ApiRequest.Options,
extraParams: Map<String, Any?>,
): Result<SharePaymentDetails>

suspend fun updateAvailableIncentives(
sessionId: String,
consumerSessionClientSecret: String,
requestSurface: String,
requestOptions: ApiRequest.Options,
): Result<UpdateAvailableIncentives>
}

@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
Expand Down Expand Up @@ -314,6 +323,30 @@ class ConsumersApiServiceImpl(
)
}

override suspend fun updateAvailableIncentives(
sessionId: String,
consumerSessionClientSecret: String,
requestSurface: String,
requestOptions: ApiRequest.Options,
): Result<UpdateAvailableIncentives> {
return executeRequestWithResultParser(
stripeErrorJsonParser = stripeErrorJsonParser,
stripeNetworkClient = stripeNetworkClient,
request = apiRequestFactory.createPost(
url = updateAvailableIncentivesUrl,
options = requestOptions,
params = mapOf(
"request_surface" to requestSurface,
"session_id" to sessionId,
"credentials" to mapOf(
"consumer_session_client_secret" to consumerSessionClientSecret
),
),
),
responseJsonParser = UpdateAvailableIncentivesJsonParser,
)
}

internal companion object {

/**
Expand Down Expand Up @@ -356,6 +389,11 @@ class ConsumersApiServiceImpl(
*/
private val sharePaymentDetails: String = getApiUrl("consumers/payment_details/share")

/**
* @return `https://api.stripe.com/v1/consumers/incentives/update_available`
*/
private val updateAvailableIncentivesUrl: String = getApiUrl("consumers/incentives/update_available")

private fun getApiUrl(path: String): String {
return "${ApiRequest.API_HOST}/v1/$path"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ internal class USBankAccountFormViewModel @Inject internal constructor(
financialConnectionsSessionId = null,
mandateText = buildMandateText(isVerifyWithMicrodeposits = false),
isVerifyingWithMicrodeposits = false,
eligibleForIncentive = result.eligibleForIncentive,
)
)
}
Expand Down

0 comments on commit 3be015b

Please sign in to comment.