-
Notifications
You must be signed in to change notification settings - Fork 0
PSP Module integration process
PSP Modules are separate libraries that contain specific implementations required to facilitate flow with various PSPs
If you want to integrate a new PSP into the Payment SDK, you should follow these steps:
You should create a new gradle module with name following format psp-integration
where psp
is the actual name of the PSP you are integrating. We are using Kotlin DSL for our gradle files. You should also add a dependency to the core payment SDK project
implementation(project(Modules.paymentSdk))
We use Dagger 2 to provide dependency injection in core library, and depending on your needs you might need to use this dependency graph in your module. One use case would be to provide SEPA registration, as you would need to call Payment SDK backend from your module, but with specific BillingData fields populated, that might be PSP dependant. To do this you should provide a companion object that implements IntegrationCompanion
interface inside your concrete Integration class. Here is an example of what that companion object should look like.
var integration: BsPayoneIntegration? = null
override fun create(): IntegrationInitialization {
return object : IntegrationInitialization {
override fun initializedOrNull(): Integration? {
return integration
}
override fun initialize(paymentSdkComponent: PaymentSdkComponent, url: String): Integration {
if (integration == null) {
if (url.isEmpty()) {
integration = BsPayoneIntegration(paymentSdkComponent)
} else {
integration = BsPayoneIntegration(paymentSdkComponent, url)
}
}
return integration as Integration
}
}
}
}
The reason for the singleton like approach in the method initializedOrNull
is that building a core dependency graph depends on having all integrations provided, while the integrations depend on dependency graph to start initialization. To work around this circular dependancy and still provide a easy to use API to 3rd party developers, we use initializedOrNull
. url
parameter is provided for easier testing.
Once you have provided the IntegrationCompanion
you should initialize your module in the init block of your concrete Integration
implementation, as in following example:
init {
bsPayoneIntegrationComponent = DaggerBsPayoneIntegrationComponent.builder()
.paymentSdkComponent(paymentSdkComponent)
.bsPayoneModule(BsPayoneModule(url))
.build()
bsPayoneIntegrationComponent.inject(this)
}
Payment method registration requests are modeled with a RegistrationRequest
class provided by core library. This class contains StandardizedData
and AdditionalRegistrationData
. Standardized data
represents the values we are certain each payment method shares no matter what PSP is being used, while AdditionalRegistrationData
contains values that are PSP specific. Combining values provided by user (such as Credit card number, expiry data, IBAN account, Billing data) and data provided by the Payment SDK backend (such as hashed requests, or other forms of credentials used to identify with the PSP) you can create a proper request that your particular PSP can consume and provide a payment alias which can then be sent to the merchant backend to be used as a payment method.
Here is the overview of the credit card flow
Here is an example of registration request handling:
override fun handleRegistrationRequest(registrationRequest: RegistrationRequest): Single<String> {
val standardizedData = registrationRequest.standardizedData
val additionalData = registrationRequest.additionalData
return when (standardizedData) {
is CreditCardRegistrationRequest -> {
bsPayoneHandler.registerCreditCard(
registrationRequest.standardizedData.aliasId,
BsPayoneRegistrationRequest.fromMap(additionalData.extraData),
standardizedData.creditCardData
)
}
is SepaRegistrationRequest -> {
bsPayoneHandler.registerSepa(
registrationRequest.standardizedData.aliasId,
standardizedData.sepaData,
standardizedData.billingData
)
}
else -> {
throw RuntimeException("Unsupported payment method")
}
}
}
In the example above you can see that we currently support CreditCard and Sepa requests for this particular PSP. Calls to bsPayoneHandler
are concrete implementations for this particular PSP.