Last active
May 5, 2020 14:50
-
-
Save flopshot/d4f754fde5f48b858e23d6707e7eddcd to your computer and use it in GitHub Desktop.
Example of a local-version request code for Stripe.confirmSetupIntent
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// AddCardUseCase designed to be injected into any view-layer presenter, | |
// regardless of whether it is an activity or fragemnt. In our case, we are | |
// injecting this AddCardUseCase into two fragments, possibly contained in the same Activity | |
class AddCardUseCase( | |
private val accountRepo: accountRepository, | |
private val setupIntentRelay: SetupIntentRelay, | |
private val stripeManager: StripeManager, | |
private val containingActivity: Activity // <- injected here just for demonstration | |
) { | |
fun addCard(params: PaymentMethodCreateParams): Flow<AddCardState> { | |
val confirmSetupIntentId = UUID.randomUUID().toString() | |
accountRepository.createSetupIntentFromOurBackend(accountRepo.userId) | |
.flatmapLatest { setupIntent -> | |
val confirmParams = ConfirmSetupIntentParams.create(params, setupIntent.clientSecret) | |
stripe.confirmSetupIntent( | |
containingActivity = Activity, | |
confirmSetupIntentParams = confirmParams, | |
clientRequestCode = confirmSetupIntentId // <- I wish I could have a local-version request code | |
) | |
return@flatMapLatest setupIntentRelay.setupIntentResultFlow() | |
.filter{ codeToPaymentIntentState: Pair<String, SetupIntentState> -> | |
codeToSetupIntentState.first == confirmSetupIntentId | |
}.take(1) | |
}.flatMapLatest { codeToSetupIntentState: Pair<String, SetupIntentState> -> | |
when (val state = codeToSetupIntentState.second) { | |
PaymentIntentState.Success -> { | |
accountRepository.addCreditCardToUserInOurBackend( | |
state.second.setupIntent, | |
) | |
} | |
else -> throw IllegalStateException() | |
} | |
} | |
.catch { t -> | |
emit(AddCreditCartState.Error(t)) | |
} | |
} | |
} | |
class ContainingActivity: Activity { | |
@Inject lateinit var setupIntentRelay: SetupIntentRelay | |
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { | |
super.onActivityResult(requestCode, resultCode, data) | |
val weakActivity = WeakReference<Activity>(this) | |
// Handle the result of stripe.confirmSetup | |
stripe.onSetupResult(requestCode, data, object : ApiResultCallback<SetupIntentResult> { | |
override fun onSuccess(result: SetupIntentResult) { | |
val setupIntent = result.intent | |
val clientRequestCode = result.clientRequestCode // <- Having this returned by the result means that I can completly decouple stripe from my UI logic | |
val status = paymentIntent.status | |
if (status == StripeIntent.Status.Succeeded) { | |
setupIntentRelay.postToSetupIntentResultFlow( | |
clientRequestCode to SetupIntentState.Success(paymentIntent) | |
) | |
} else if (status == StripeIntent.Status.RequiresPaymentMethod) { | |
setupIntentRelay.postToSetupIntentResultFlow( | |
clientRequestCode to SetupIntentState.Error(IllegalStateException( | |
"Payment failed", paymentIntent.lastPaymentError?.message ?: "" | |
) | |
) | |
} | |
} | |
override fun onError(e: Exception) { | |
setupIntentRelay.postToSetupIntentResultFlow( | |
clientRequestCode to SetupIntentState.Error(e) | |
) | |
} | |
}) | |
} | |
} | |
sealed class SetupIntentState { | |
data class Error(val t: Throwable): SetupIntentState() | |
data class Success(val paymentIntent: PaymentIntent): SetupIntentState() | |
} | |
data class SetupIntent( | |
val stripeSetupIntentId: String, | |
val clientSecret: String | |
) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment