Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.processout.sdk.api.model.request.napm.v2

import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

@JsonClass(generateAdapter = true)
internal data class NativeAlternativePaymentRequestBody(
@Json(name = "gateway_configuration_id")
val gatewayConfigurationId: String,
@Json(name = "submit_data")
val submitData: SubmitData?
) {

@JsonClass(generateAdapter = true)
data class SubmitData(
val parameters: Map<String, Any>
)
}
Original file line number Diff line number Diff line change
@@ -1,81 +1,18 @@
package com.processout.sdk.api.model.request.napm.v2

import com.processout.sdk.core.annotation.ProcessOutInternalApi
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

/**
* Request parameters for native alternative payment authorization.
*
* @param[invoiceId] Invoice identifier.
* @param[gatewayConfigurationId] Gateway configuration identifier.
* @param[parameters] Payment parameter values.
* @param[submitData] Payment payload.
*/
/** @suppress */
@ProcessOutInternalApi
data class PONativeAlternativePaymentAuthorizationRequest(
val invoiceId: String,
val gatewayConfigurationId: String,
val parameters: Map<String, Parameter>? = null
) {

/**
* Payment parameter value.
*/
data class Parameter internal constructor(
@ProcessOutInternalApi val value: Value
) {

companion object {
/**
* Arbitrary string value.
*/
fun string(value: String) = Parameter(Value.String(value))

/**
* Phone number value.
*
* @param[dialingCode] International dialing code.
* @param[number] The rest of the number without dialing code.
*/
fun phoneNumber(
dialingCode: String,
number: String
) = Parameter(
Value.PhoneNumber(
dialingCode = dialingCode,
number = number
)
)
}

/** @suppress */
@ProcessOutInternalApi
sealed class Value {
data class String(
val value: kotlin.String
) : Value()

@JsonClass(generateAdapter = true)
data class PhoneNumber(
@Json(name = "dialing_code")
val dialingCode: kotlin.String,
val number: kotlin.String
) : Value()
}
}
}

@JsonClass(generateAdapter = true)
internal data class NativeAlternativePaymentAuthorizationRequestBody(
@Json(name = "gateway_configuration_id")
val gatewayConfigurationId: String,
@Json(name = "submit_data")
val submitData: SubmitData?
) {

@JsonClass(generateAdapter = true)
data class SubmitData(
val parameters: Map<String, Any>
)
}
val submitData: PONativeAlternativePaymentSubmitData? = null
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.processout.sdk.api.model.request.napm.v2

import com.processout.sdk.core.annotation.ProcessOutInternalApi
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

/**
* Specifies native alternative payment payload.
*
* @param[parameters] Map of payment parameter values.
*/
/** @suppress */
@ProcessOutInternalApi
data class PONativeAlternativePaymentSubmitData(
val parameters: Map<String, Parameter>
) {

/**
* Payment parameter value.
*/
data class Parameter internal constructor(
@ProcessOutInternalApi val value: Value
) {

companion object {
/**
* Arbitrary string value.
*/
fun string(value: String) = Parameter(Value.String(value))

/**
* Phone number value.
*
* @param[dialingCode] International dialing code.
* @param[number] The rest of the number without dialing code.
*/
fun phoneNumber(
dialingCode: String,
number: String
) = Parameter(
Value.PhoneNumber(
dialingCode = dialingCode,
number = number
)
)
}

/** @suppress */
@ProcessOutInternalApi
sealed class Value {
data class String(
val value: kotlin.String
) : Value()

@JsonClass(generateAdapter = true)
data class PhoneNumber(
@Json(name = "dialing_code")
val dialingCode: kotlin.String,
val number: kotlin.String
) : Value()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.processout.sdk.api.model.request.napm.v2

import com.processout.sdk.core.annotation.ProcessOutInternalApi

/**
* Request parameters for native alternative payment tokenization.
*
* @param[customerId] Customer identifier.
* @param[customerTokenId] Customer token identifier.
* @param[gatewayConfigurationId] Gateway configuration identifier.
* @param[submitData] Payment payload.
*/
/** @suppress */
@ProcessOutInternalApi
data class PONativeAlternativePaymentTokenizationRequest(
val customerId: String,
val customerTokenId: String,
val gatewayConfigurationId: String,
val submitData: PONativeAlternativePaymentSubmitData? = null
)
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ import com.squareup.moshi.JsonClass
* @param[state] State of native alternative payment.
* @param[invoice] Invoice details.
* @param[paymentMethod] Payment method details.
* @param[nextStep] Next required step in the payment flow.
* @param[customerInstructions] Instructions for the customer that provide additional information and/or describe required actions.
* @param[elements] An ordered list of elements that needs to be rendered on the UI during native alternative payment flow.
* @param[redirect] Indicates required redirect.
*/
/** @suppress */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.processout.sdk.api.model.response.napm.v2

import com.processout.sdk.core.annotation.ProcessOutInternalApi
import com.squareup.moshi.JsonClass

/**
* Specifies details of native alternative payment.
*
* @param[state] State of native alternative payment.
* @param[paymentMethod] Payment method details.
* @param[elements] An ordered list of elements that needs to be rendered on the UI during native alternative payment flow.
* @param[redirect] Indicates required redirect.
*/
/** @suppress */
@ProcessOutInternalApi
data class PONativeAlternativePaymentTokenizationResponse(
val state: PONativeAlternativePaymentState,
// val paymentMethod: PONativeAlternativePaymentMethodDetails, // TODO(v2): uncomment
val elements: List<PONativeAlternativePaymentElement>?,
val redirect: PONativeAlternativePaymentRedirect?
)

@JsonClass(generateAdapter = true)
internal data class NativeAlternativePaymentTokenizationResponseBody(
val state: PONativeAlternativePaymentState,
// @Json(name = "payment_method")
// val paymentMethod: PONativeAlternativePaymentMethodDetails, // TODO(v2): uncomment
val elements: List<NativeAlternativePaymentElement>?,
val redirect: PONativeAlternativePaymentRedirect?
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package com.processout.sdk.api.network
import com.processout.sdk.api.model.request.AssignCustomerTokenRequestWithDeviceData
import com.processout.sdk.api.model.request.POCreateCustomerRequest
import com.processout.sdk.api.model.request.POCreateCustomerTokenRequestBody
import com.processout.sdk.api.model.request.napm.v2.NativeAlternativePaymentRequestBody
import com.processout.sdk.api.model.response.CustomerResponse
import com.processout.sdk.api.model.response.CustomerTokenResponse
import com.processout.sdk.api.model.response.napm.v2.NativeAlternativePaymentTokenizationResponseBody
import com.processout.sdk.api.network.HeaderConstants.CLIENT_SECRET
import retrofit2.Response
import retrofit2.http.*
Expand All @@ -18,6 +20,13 @@ internal interface CustomerTokensApi {
@Body request: AssignCustomerTokenRequestWithDeviceData
): Response<CustomerTokenResponse>

@POST("/customers/{customer_id}/tokens/{token_id}/tokenize")
suspend fun tokenize(
@Path("customer_id") customerId: String,
@Path("token_id") tokenId: String,
@Body request: NativeAlternativePaymentRequestBody
): Response<NativeAlternativePaymentTokenizationResponseBody>

@DELETE("/customers/{customer_id}/tokens/{token_id}")
suspend fun deleteCustomerToken(
@Path("customer_id") customerId: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import com.processout.sdk.api.model.request.InvoiceAuthorizationRequestWithDevic
import com.processout.sdk.api.model.request.NativeAPMRequestBody
import com.processout.sdk.api.model.request.NativeAlternativePaymentCaptureRequest
import com.processout.sdk.api.model.request.POCreateInvoiceRequest
import com.processout.sdk.api.model.request.napm.v2.NativeAlternativePaymentAuthorizationRequestBody
import com.processout.sdk.api.model.request.napm.v2.NativeAlternativePaymentRequestBody
import com.processout.sdk.api.model.response.*
import com.processout.sdk.api.model.response.napm.v2.NativeAlternativePaymentAuthorizationResponseBody
import com.processout.sdk.api.network.HeaderConstants.CLIENT_SECRET
Expand All @@ -23,7 +23,7 @@ internal interface InvoicesApi {
@POST("/invoices/{id}/apm-payment")
suspend fun authorizeInvoice(
@Path("id") invoiceId: String,
@Body request: NativeAlternativePaymentAuthorizationRequestBody
@Body request: NativeAlternativePaymentRequestBody
): Response<NativeAlternativePaymentAuthorizationResponseBody>

@GET("/invoices/{invoiceId}/apm-payment/{gatewayConfigurationId}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import com.processout.sdk.api.model.request.POAssignCustomerTokenRequest
import com.processout.sdk.api.model.request.POCreateCustomerRequest
import com.processout.sdk.api.model.request.POCreateCustomerTokenRequest
import com.processout.sdk.api.model.request.PODeleteCustomerTokenRequest
import com.processout.sdk.api.model.request.napm.v2.PONativeAlternativePaymentTokenizationRequest
import com.processout.sdk.api.model.response.CustomerTokenResponse
import com.processout.sdk.api.model.response.POCustomer
import com.processout.sdk.api.model.response.POCustomerToken
import com.processout.sdk.api.model.response.napm.v2.PONativeAlternativePaymentTokenizationResponse
import com.processout.sdk.core.ProcessOutResult
import com.processout.sdk.core.annotation.ProcessOutInternalApi

Expand All @@ -16,6 +18,10 @@ internal interface CustomerTokensRepository {
request: POAssignCustomerTokenRequest
): ProcessOutResult<CustomerTokenResponse>

suspend fun tokenize(
request: PONativeAlternativePaymentTokenizationRequest
): ProcessOutResult<PONativeAlternativePaymentTokenizationResponse>

suspend fun deleteCustomerToken(
request: PODeleteCustomerTokenRequest
): ProcessOutResult<Unit>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
package com.processout.sdk.api.repository

import com.processout.sdk.api.model.request.*
import com.processout.sdk.api.model.request.napm.v2.NativeAlternativePaymentRequestBody
import com.processout.sdk.api.model.request.napm.v2.NativeAlternativePaymentRequestBody.SubmitData
import com.processout.sdk.api.model.request.napm.v2.PONativeAlternativePaymentSubmitData.Parameter
import com.processout.sdk.api.model.request.napm.v2.PONativeAlternativePaymentSubmitData.Parameter.Value
import com.processout.sdk.api.model.request.napm.v2.PONativeAlternativePaymentTokenizationRequest
import com.processout.sdk.api.model.response.napm.v2.NativeAlternativePaymentElement
import com.processout.sdk.api.model.response.napm.v2.NativeAlternativePaymentTokenizationResponseBody
import com.processout.sdk.api.model.response.napm.v2.PONativeAlternativePaymentElement
import com.processout.sdk.api.model.response.napm.v2.PONativeAlternativePaymentTokenizationResponse
import com.processout.sdk.api.network.CustomerTokensApi
import com.processout.sdk.core.POFailure
import com.processout.sdk.core.ProcessOutResult
Expand All @@ -23,6 +32,16 @@ internal class DefaultCustomerTokensRepository(
)
}

override suspend fun tokenize(
request: PONativeAlternativePaymentTokenizationRequest
) = apiCall {
api.tokenize(
customerId = request.customerId,
tokenId = request.customerTokenId,
request = request.toBody()
)
}.map { it.toModel() }

override suspend fun deleteCustomerToken(
request: PODeleteCustomerTokenRequest
) = apiCall {
Expand Down Expand Up @@ -57,4 +76,44 @@ internal class DefaultCustomerTokensRepository(
metadata = metadata,
deviceData = contextGraph.deviceData
)

private fun PONativeAlternativePaymentTokenizationRequest.toBody() =
NativeAlternativePaymentRequestBody(
gatewayConfigurationId = gatewayConfigurationId,
submitData = submitData?.let { SubmitData(parameters = it.parameters.map()) }
)

private fun Map<String, Parameter>.map() =
mapValues { (_, parameter) ->
when (val value = parameter.value) {
is Value.String -> value.value
is Value.PhoneNumber -> value
}
}

private fun NativeAlternativePaymentTokenizationResponseBody.toModel() =
PONativeAlternativePaymentTokenizationResponse(
state = state,
// paymentMethod = paymentMethod, // TODO(v2): uncomment
elements = elements?.map {
when (it) {
is NativeAlternativePaymentElement.Form ->
PONativeAlternativePaymentElement.Form(
parameterDefinitions = it.parameters.parameterDefinitions
)
is NativeAlternativePaymentElement.CustomerInstruction ->
PONativeAlternativePaymentElement.CustomerInstruction(
instruction = it.instruction
)
is NativeAlternativePaymentElement.CustomerInstructionGroup ->
PONativeAlternativePaymentElement.CustomerInstructionGroup(
label = it.label,
instructions = it.instructions
)
NativeAlternativePaymentElement.Unknown ->
PONativeAlternativePaymentElement.Unknown
}
},
redirect = redirect
)
}
Loading