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

PayTo - Create component #1989

Merged
merged 2 commits into from
Feb 4, 2025
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,8 @@ internal fun getComponentFor(
)
}

// TODO Add PayTo here when component provider is created

checkCompileOnly { SepaComponent.PROVIDER.isPaymentMethodSupported(paymentMethod) } -> {
SepaComponentProvider(dropInOverrideParams, analyticsManager).get(
fragment = fragment,
Expand Down
21 changes: 21 additions & 0 deletions payto/api/payto.api
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,24 @@ public final class com/adyen/checkout/payto/BuildConfig {
public fun <init> ()V
}

public final class com/adyen/checkout/payto/PayToComponent : androidx/lifecycle/ViewModel, com/adyen/checkout/action/core/internal/ActionHandlingComponent, com/adyen/checkout/components/core/internal/ButtonComponent, com/adyen/checkout/components/core/internal/PaymentComponent, com/adyen/checkout/ui/core/internal/ui/ViewableComponent {
public static final field Companion Lcom/adyen/checkout/payto/PayToComponent$Companion;
public static final field PAYMENT_METHOD_TYPES Ljava/util/List;
public static final field PROVIDER Lcom/adyen/checkout/payto/internal/provider/PayToComponentProvider;
public fun canHandleAction (Lcom/adyen/checkout/components/core/action/Action;)Z
public fun getDelegate ()Lcom/adyen/checkout/components/core/internal/ui/ComponentDelegate;
public fun getViewFlow ()Lkotlinx/coroutines/flow/Flow;
public fun handleAction (Lcom/adyen/checkout/components/core/action/Action;Landroid/app/Activity;)V
public fun handleIntent (Landroid/content/Intent;)V
public fun isConfirmationRequired ()Z
public fun setInteractionBlocked (Z)V
public fun setOnRedirectListener (Lkotlin/jvm/functions/Function0;)V
public fun submit ()V
}

public final class com/adyen/checkout/payto/PayToComponent$Companion {
}

public final class com/adyen/checkout/payto/PayToComponentState : com/adyen/checkout/components/core/PaymentComponentState {
public fun <init> (Lcom/adyen/checkout/components/core/PaymentComponentData;ZZ)V
public final fun component1 ()Lcom/adyen/checkout/components/core/PaymentComponentData;
Expand All @@ -22,3 +40,6 @@ public final class com/adyen/checkout/payto/PayToComponentState : com/adyen/chec
public fun toString ()Ljava/lang/String;
}

public final class com/adyen/checkout/payto/internal/provider/PayToComponentProvider {
}

1 change: 1 addition & 0 deletions payto/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,5 @@ dependencies {
testImplementation testFixtures(project(':ui-core'))
testImplementation libs.bundles.junit
testImplementation libs.bundles.kotlin.coroutines.test
testImplementation libs.bundles.mockito
}
103 changes: 103 additions & 0 deletions payto/src/main/java/com/adyen/checkout/payto/PayToComponent.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* Copyright (c) 2025 Adyen N.V.
*
* This file is open source and available under the MIT license. See the LICENSE file for more info.
*
* Created by ararat on 3/2/2025.
*/

package com.adyen.checkout.payto

import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.adyen.checkout.action.core.internal.ActionHandlingComponent
import com.adyen.checkout.action.core.internal.DefaultActionHandlingComponent
import com.adyen.checkout.action.core.internal.ui.GenericActionDelegate
import com.adyen.checkout.components.core.PaymentMethodTypes
import com.adyen.checkout.components.core.internal.ButtonComponent
import com.adyen.checkout.components.core.internal.ComponentEventHandler
import com.adyen.checkout.components.core.internal.PaymentComponent
import com.adyen.checkout.components.core.internal.PaymentComponentEvent
import com.adyen.checkout.components.core.internal.toActionCallback
import com.adyen.checkout.components.core.internal.ui.ComponentDelegate
import com.adyen.checkout.core.AdyenLogLevel
import com.adyen.checkout.core.internal.util.adyenLog
import com.adyen.checkout.payto.internal.provider.PayToComponentProvider
import com.adyen.checkout.payto.internal.ui.PayToDelegate
import com.adyen.checkout.ui.core.internal.ui.ButtonDelegate
import com.adyen.checkout.ui.core.internal.ui.ComponentViewType
import com.adyen.checkout.ui.core.internal.ui.ViewableComponent
import com.adyen.checkout.ui.core.internal.util.mergeViewFlows
import kotlinx.coroutines.flow.Flow

/**
* A [PaymentComponent] that supports the [PaymentMethodTypes.PAY_TO] payment method.
*/
class PayToComponent internal constructor(
private val payToDelegate: PayToDelegate,
private val genericActionDelegate: GenericActionDelegate,
private val actionHandlingComponent: DefaultActionHandlingComponent,
internal val componentEventHandler: ComponentEventHandler<PayToComponentState>,
) : ViewModel(),
PaymentComponent,
ViewableComponent,
ButtonComponent,
ActionHandlingComponent by actionHandlingComponent {

override val delegate: ComponentDelegate get() = actionHandlingComponent.activeDelegate

override val viewFlow: Flow<ComponentViewType?> = mergeViewFlows(
viewModelScope,
payToDelegate.viewFlow,
genericActionDelegate.viewFlow,
)

init {
payToDelegate.initialize(viewModelScope)
genericActionDelegate.initialize(viewModelScope)
componentEventHandler.initialize(viewModelScope)
}

internal fun observe(
lifecycleOwner: LifecycleOwner,
callback: (PaymentComponentEvent<PayToComponentState>) -> Unit
) {
payToDelegate.observe(lifecycleOwner, viewModelScope, callback)
genericActionDelegate.observe(lifecycleOwner, viewModelScope, callback.toActionCallback())
}

internal fun removeObserver() {
payToDelegate.removeObserver()
genericActionDelegate.removeObserver()
}

override fun isConfirmationRequired(): Boolean = payToDelegate.isConfirmationRequired()

override fun submit() {
(delegate as? ButtonDelegate)?.onSubmit()
?: adyenLog(AdyenLogLevel.ERROR) { "Component is currently not submittable, ignoring." }
}

override fun setInteractionBlocked(isInteractionBlocked: Boolean) {
(delegate as? PayToDelegate)?.setInteractionBlocked(isInteractionBlocked)
?: adyenLog(AdyenLogLevel.ERROR) { "Payment component is not interactable, ignoring." }
}

override fun onCleared() {
super.onCleared()
adyenLog(AdyenLogLevel.DEBUG) { "onCleared" }
payToDelegate.onCleared()
genericActionDelegate.onCleared()
componentEventHandler.onCleared()
}

companion object {

@JvmField
val PROVIDER = PayToComponentProvider()

@JvmField
val PAYMENT_METHOD_TYPES = listOf(PaymentMethodTypes.PAY_TO)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright (c) 2025 Adyen N.V.
*
* This file is open source and available under the MIT license. See the LICENSE file for more info.
*
* Created by ararat on 3/2/2025.
*/

package com.adyen.checkout.payto.internal.provider

import androidx.annotation.RestrictTo

// TODO To be implemented
class PayToComponentProvider
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
constructor()
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright (c) 2025 Adyen N.V.
*
* This file is open source and available under the MIT license. See the LICENSE file for more info.
*
* Created by ararat on 3/2/2025.
*/

package com.adyen.checkout.payto.internal.ui

import com.adyen.checkout.components.core.internal.ui.PaymentComponentDelegate
import com.adyen.checkout.payto.PayToComponentState
import com.adyen.checkout.ui.core.internal.ui.ButtonDelegate
import com.adyen.checkout.ui.core.internal.ui.UIStateDelegate
import com.adyen.checkout.ui.core.internal.ui.ViewProvidingDelegate

internal interface PayToDelegate :
PaymentComponentDelegate<PayToComponentState>,
ViewProvidingDelegate,
ButtonDelegate,
UIStateDelegate {

fun setInteractionBlocked(isInteractionBlocked: Boolean)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2025 Adyen N.V.
*
* This file is open source and available under the MIT license. See the LICENSE file for more info.
*
* Created by ararat on 3/2/2025.
*/

package com.adyen.checkout.payto.internal.ui

import android.content.Context
import com.adyen.checkout.payto.internal.ui.view.PayToView
import com.adyen.checkout.ui.core.internal.ui.AmountButtonComponentViewType
import com.adyen.checkout.ui.core.internal.ui.ButtonComponentViewType
import com.adyen.checkout.ui.core.internal.ui.ComponentView
import com.adyen.checkout.ui.core.internal.ui.ComponentViewType
import com.adyen.checkout.ui.core.internal.ui.ViewProvider

internal object PayToViewProvider : ViewProvider {

override fun getView(viewType: ComponentViewType, context: Context): ComponentView = when (viewType) {
PayToComponentViewType -> PayToView(context)
else -> throw IllegalArgumentException("Unsupported view type")
}
}

internal object PayToComponentViewType : AmountButtonComponentViewType {
override val viewProvider: ViewProvider = PayToViewProvider
override val buttonTextResId: Int = ButtonComponentViewType.DEFAULT_BUTTON_TEXT_RES_ID
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2025 Adyen N.V.
*
* This file is open source and available under the MIT license. See the LICENSE file for more info.
*
* Created by ararat on 3/2/2025.
*/

package com.adyen.checkout.payto.internal.ui.view

import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.widget.LinearLayout
import com.adyen.checkout.components.core.internal.ui.ComponentDelegate
import com.adyen.checkout.ui.core.internal.ui.ComponentView
import kotlinx.coroutines.CoroutineScope

internal class PayToView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr), ComponentView {

override fun initView(delegate: ComponentDelegate, coroutineScope: CoroutineScope, localizedContext: Context) {
// TODO To be implemented
}

override fun highlightValidationErrors() {
// TODO To be implemented
}

override fun getView(): View = this
}
Loading
Loading