diff --git a/sdk/src/main/kotlin/com/processout/sdk/api/model/request/napm/v2/PONativeAlternativePaymentAuthorizationRequest.kt b/sdk/src/main/kotlin/com/processout/sdk/api/model/request/napm/v2/PONativeAlternativePaymentAuthorizationRequest.kt new file mode 100644 index 000000000..dcfc43b4d --- /dev/null +++ b/sdk/src/main/kotlin/com/processout/sdk/api/model/request/napm/v2/PONativeAlternativePaymentAuthorizationRequest.kt @@ -0,0 +1,79 @@ +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 parameters. + */ +/** @suppress */ +@ProcessOutInternalApi +data class PONativeAlternativePaymentAuthorizationRequest( + val invoiceId: String, + val gatewayConfigurationId: String, + val parameters: Map? = null +) { + + /** + * Payment parameter. + */ + data class Parameter internal constructor( + internal val value: Value + ) { + + companion object { + /** + * Arbitrary string parameter. + */ + fun string(value: String) = Parameter(Value.String(value)) + + /** + * Phone number parameter. + * + * @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 + ) + ) + } + + internal 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 + ) +} diff --git a/sdk/src/main/kotlin/com/processout/sdk/api/model/request/napm/v2/PONativeAlternativePaymentRequest.kt b/sdk/src/main/kotlin/com/processout/sdk/api/model/request/napm/v2/PONativeAlternativePaymentRequest.kt new file mode 100644 index 000000000..ef91d4a90 --- /dev/null +++ b/sdk/src/main/kotlin/com/processout/sdk/api/model/request/napm/v2/PONativeAlternativePaymentRequest.kt @@ -0,0 +1,16 @@ +package com.processout.sdk.api.model.request.napm.v2 + +import com.processout.sdk.core.annotation.ProcessOutInternalApi + +/** + * Request parameters for native alternative payment. + * + * @param[invoiceId] Invoice identifier. + * @param[gatewayConfigurationId] Gateway configuration identifier. + */ +/** @suppress */ +@ProcessOutInternalApi +data class PONativeAlternativePaymentRequest( + val invoiceId: String, + val gatewayConfigurationId: String +) diff --git a/sdk/src/main/kotlin/com/processout/sdk/api/model/response/napm/v2/PONativeAlternativePaymentAuthorizationResponse.kt b/sdk/src/main/kotlin/com/processout/sdk/api/model/response/napm/v2/PONativeAlternativePaymentAuthorizationResponse.kt new file mode 100644 index 000000000..a56a314d2 --- /dev/null +++ b/sdk/src/main/kotlin/com/processout/sdk/api/model/response/napm/v2/PONativeAlternativePaymentAuthorizationResponse.kt @@ -0,0 +1,53 @@ +package com.processout.sdk.api.model.response.napm.v2 + +import com.processout.sdk.api.model.response.napm.v2.PONativeAlternativePaymentAuthorizationResponse.State +import com.processout.sdk.core.annotation.ProcessOutInternalApi +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +/** + * Specifies details of native alternative payment. + * + * @param[state] State of native alternative payment. + * @param[nextStep] Next required step in the payment flow. + * @param[customerInstructions] Instructions for the customer that provide additional information and/or describe required actions. + */ +/** @suppress */ +@ProcessOutInternalApi +data class PONativeAlternativePaymentAuthorizationResponse( + val state: State, + val nextStep: PONativeAlternativePaymentNextStep?, + val customerInstructions: List? +) { + + /** + * State of native alternative payment. + */ + @JsonClass(generateAdapter = false) + enum class State { + /** Next step is required to proceed. */ + NEXT_STEP_REQUIRED, + + /** Payment is ready to be captured. */ + PENDING_CAPTURE, + + /** Payment is captured. */ + CAPTURED, + + /** + * Placeholder that allows adding additional cases while staying backward compatible. + * __Warning:__ Do not match this case directly, use _when-else_ instead. + */ + @ProcessOutInternalApi + UNKNOWN + } +} + +@JsonClass(generateAdapter = true) +internal data class NativeAlternativePaymentAuthorizationResponseBody( + val state: State, + @Json(name = "next_step") + val nextStep: NativeAlternativePaymentNextStep?, + @Json(name = "customer_instructions") + val customerInstructions: List? +) diff --git a/sdk/src/main/kotlin/com/processout/sdk/api/model/response/napm/v2/PONativeAlternativePaymentCustomerInstruction.kt b/sdk/src/main/kotlin/com/processout/sdk/api/model/response/napm/v2/PONativeAlternativePaymentCustomerInstruction.kt new file mode 100644 index 000000000..96377ed3b --- /dev/null +++ b/sdk/src/main/kotlin/com/processout/sdk/api/model/response/napm/v2/PONativeAlternativePaymentCustomerInstruction.kt @@ -0,0 +1,78 @@ +package com.processout.sdk.api.model.response.napm.v2 + +import com.processout.sdk.api.model.response.POBarcode +import com.processout.sdk.api.model.response.POImageResource +import com.processout.sdk.core.annotation.ProcessOutInternalApi +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +/** + * Specifies instruction for the customer, providing additional information and/or describing required actions. + */ +/** @suppress */ +@ProcessOutInternalApi +sealed class PONativeAlternativePaymentCustomerInstruction { + + /** + * Customer instruction provided as a markdown text. + * + * @param[label] Optional instruction display label. + * @param[value] Markdown text. + */ + @JsonClass(generateAdapter = true) + data class Text( + val label: String?, + val value: String + ) : PONativeAlternativePaymentCustomerInstruction() + + /** + * Customer instruction provided as an image resource. + * + * @param[value] Image resource. + */ + @JsonClass(generateAdapter = true) + data class Image( + val value: POImageResource + ) : PONativeAlternativePaymentCustomerInstruction() + + /** + * Customer instruction provided via barcode. + * + * @param[rawSubtype] Raw barcode subtype. + * @param[rawValue] Base64 encoded value. + */ + @JsonClass(generateAdapter = true) + data class Barcode( + @Json(name = "subtype") + val rawSubtype: String, + @Json(name = "value") + val rawValue: String + ) : PONativeAlternativePaymentCustomerInstruction() { + + /** Barcode value. */ + val value: POBarcode + get() = POBarcode( + rawType = rawSubtype, + rawValue = rawValue + ) + } + + /** + * Group of customer instructions. + * + * @param[label] Optional group display label. + * @param[instructions] Grouped instructions for the customer that provide additional information and/or describe required actions. + */ + @JsonClass(generateAdapter = true) + data class Group( + val label: String?, + val instructions: List + ) : PONativeAlternativePaymentCustomerInstruction() + + /** + * Placeholder that allows adding additional cases while staying backward compatible. + * __Warning:__ Do not match this case directly, use _when-else_ instead. + */ + @ProcessOutInternalApi + data object Unknown : PONativeAlternativePaymentCustomerInstruction() +} diff --git a/sdk/src/main/kotlin/com/processout/sdk/api/model/response/napm/v2/PONativeAlternativePaymentNextStep.kt b/sdk/src/main/kotlin/com/processout/sdk/api/model/response/napm/v2/PONativeAlternativePaymentNextStep.kt new file mode 100644 index 000000000..167132142 --- /dev/null +++ b/sdk/src/main/kotlin/com/processout/sdk/api/model/response/napm/v2/PONativeAlternativePaymentNextStep.kt @@ -0,0 +1,278 @@ +package com.processout.sdk.api.model.response.napm.v2 + +import com.processout.sdk.api.model.response.napm.v2.PONativeAlternativePaymentNextStep.SubmitData.Parameter +import com.processout.sdk.core.annotation.ProcessOutInternalApi +import com.processout.sdk.core.util.findBy +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +/** + * Specifies the next required step in the payment flow. + */ +/** @suppress */ +@ProcessOutInternalApi +sealed class PONativeAlternativePaymentNextStep { + + /** + * Indicates that the next required step is submitting data for the expected [parameterDefinitions]. + */ + data class SubmitData( + val parameterDefinitions: List + ) : PONativeAlternativePaymentNextStep() { + + /** + * Payment parameter definition. + */ + sealed class Parameter { + + /** + * Text parameter. + * + * @param[key] Parameter key. + * @param[label] Parameter display label. + * @param[required] Indicates whether the parameter is required. + * @param[minLength] Optional minimum length. + * @param[maxLength] Optional maximum length. + */ + @JsonClass(generateAdapter = true) + data class Text( + val key: String, + val label: String, + val required: Boolean, + @Json(name = "min_length") + val minLength: Int?, + @Json(name = "max_length") + val maxLength: Int? + ) : Parameter() + + /** + * Single selection parameter. + * + * @param[key] Parameter key. + * @param[label] Parameter display label. + * @param[required] Indicates whether the parameter is required. + * @param[availableValues] Available values. + */ + @JsonClass(generateAdapter = true) + data class SingleSelect( + val key: String, + val label: String, + val required: Boolean, + @Json(name = "available_values") + val availableValues: List + ) : Parameter() { + + /** Preselected value. */ + val preselectedValue: AvailableValue? + get() = availableValues.find { it.preselected } + + /** + * Available parameter value. + * + * @param[value] Parameter value. + * @param[label] Value display label. + * @param[preselected] Indicates whether the value should be preselected by default. + */ + @JsonClass(generateAdapter = true) + data class AvailableValue( + val value: String, + val label: String, + val preselected: Boolean + ) + } + + /** + * Boolean parameter. + * + * @param[key] Parameter key. + * @param[label] Parameter display label. + * @param[required] Indicates whether the parameter is required. + */ + @JsonClass(generateAdapter = true) + data class Bool( + val key: String, + val label: String, + val required: Boolean + ) : Parameter() + + /** + * Digits only parameter. + * + * @param[key] Parameter key. + * @param[label] Parameter display label. + * @param[required] Indicates whether the parameter is required. + * @param[minLength] Optional minimum length. + * @param[maxLength] Optional maximum length. + */ + @JsonClass(generateAdapter = true) + data class Digits( + val key: String, + val label: String, + val required: Boolean, + @Json(name = "min_length") + val minLength: Int?, + @Json(name = "max_length") + val maxLength: Int? + ) : Parameter() + + /** + * Phone number parameter. + * + * @param[key] Parameter key. + * @param[label] Parameter display label. + * @param[required] Indicates whether the parameter is required. + * @param[dialingCodes] Supported international dialing codes. + */ + @JsonClass(generateAdapter = true) + data class PhoneNumber( + val key: String, + val label: String, + val required: Boolean, + @Json(name = "dialing_codes") + val dialingCodes: List? + ) : Parameter() { + + /** + * International dialing code. + * + * @param[id] Country code identifier. + * @param[value] Dialing code value. + */ + @JsonClass(generateAdapter = true) + data class DialingCode( + val id: String, + val value: String + ) + } + + /** + * Email parameter. + * + * @param[key] Parameter key. + * @param[label] Parameter display label. + * @param[required] Indicates whether the parameter is required. + */ + @JsonClass(generateAdapter = true) + data class Email( + val key: String, + val label: String, + val required: Boolean + ) : Parameter() + + /** + * Card number parameter. + * + * @param[key] Parameter key. + * @param[label] Parameter display label. + * @param[required] Indicates whether the parameter is required. + * @param[minLength] Optional minimum length. + * @param[maxLength] Optional maximum length. + */ + @JsonClass(generateAdapter = true) + data class Card( + val key: String, + val label: String, + val required: Boolean, + @Json(name = "min_length") + val minLength: Int?, + @Json(name = "max_length") + val maxLength: Int? + ) : Parameter() + + /** + * One-Time Password (OTP) parameter. + * + * @param[key] Parameter key. + * @param[rawSubtype] Raw OTP subtype. + * @param[label] Parameter display label. + * @param[required] Indicates whether the parameter is required. + * @param[minLength] Optional minimum length. + * @param[maxLength] Optional maximum length. + */ + @JsonClass(generateAdapter = true) + data class Otp( + val key: String, + @Json(name = "subtype") + val rawSubtype: String, + val label: String, + val required: Boolean, + @Json(name = "min_length") + val minLength: Int?, + @Json(name = "max_length") + val maxLength: Int? + ) : Parameter() { + + /** OTP subtype. */ + val subtype: Subtype + get() = Subtype::rawType.findBy(rawSubtype) ?: Subtype.UNKNOWN + + /** + * One-Time Password (OTP) subtype. + */ + enum class Subtype(val rawType: String) { + /** Text OTP. */ + TEXT("text"), + + /** Digits only OTP. */ + DIGITS("digits"), + + /** + * Placeholder that allows adding additional cases while staying backward compatible. + * __Warning:__ Do not match this case directly, use _when-else_ instead. + */ + @ProcessOutInternalApi + UNKNOWN(String()) + } + } + + /** + * Placeholder that allows adding additional cases while staying backward compatible. + * __Warning:__ Do not match this case directly, use _when-else_ instead. + */ + @ProcessOutInternalApi + data object Unknown : Parameter() + } + } + + /** + * Indicates that the next required step is a redirect to the URL. + */ + data class Redirect( + val url: String + ) : PONativeAlternativePaymentNextStep() + + /** + * Placeholder that allows adding additional cases while staying backward compatible. + * __Warning:__ Do not match this case directly, use _when-else_ instead. + */ + @ProcessOutInternalApi + data object Unknown : PONativeAlternativePaymentNextStep() +} + +internal sealed class NativeAlternativePaymentNextStep { + + @JsonClass(generateAdapter = true) + data class SubmitData( + val parameters: Parameters + ) : NativeAlternativePaymentNextStep() { + + @JsonClass(generateAdapter = true) + data class Parameters( + @Json(name = "parameter_definitions") + val parameterDefinitions: List + ) + } + + @JsonClass(generateAdapter = true) + data class Redirect( + val parameters: Parameters + ) : NativeAlternativePaymentNextStep() { + + @JsonClass(generateAdapter = true) + data class Parameters( + val url: String + ) + } + + data object Unknown : NativeAlternativePaymentNextStep() +} diff --git a/sdk/src/main/kotlin/com/processout/sdk/api/network/InvoicesApi.kt b/sdk/src/main/kotlin/com/processout/sdk/api/network/InvoicesApi.kt index c3124e4c1..7552314a0 100644 --- a/sdk/src/main/kotlin/com/processout/sdk/api/network/InvoicesApi.kt +++ b/sdk/src/main/kotlin/com/processout/sdk/api/network/InvoicesApi.kt @@ -4,7 +4,9 @@ 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.response.* +import com.processout.sdk.api.model.response.napm.v2.NativeAlternativePaymentAuthorizationResponseBody import com.processout.sdk.api.network.HeaderConstants.CLIENT_SECRET import retrofit2.Response import retrofit2.http.* @@ -18,6 +20,18 @@ internal interface InvoicesApi { @Header(CLIENT_SECRET) clientSecret: String? ): Response + @POST("/invoices/{id}/apm-payment") + suspend fun authorizeInvoice( + @Path("id") invoiceId: String, + @Body request: NativeAlternativePaymentAuthorizationRequestBody + ): Response + + @GET("/invoices/{invoiceId}/apm-payment/{gatewayConfigurationId}") + suspend fun nativeAlternativePayment( + @Path("invoiceId") invoiceId: String, + @Path("gatewayConfigurationId") gatewayConfigurationId: String + ): Response + @POST("/invoices/{id}/native-payment") suspend fun initiatePayment( @Path("id") invoiceId: String, diff --git a/sdk/src/main/kotlin/com/processout/sdk/api/repository/DefaultInvoicesRepository.kt b/sdk/src/main/kotlin/com/processout/sdk/api/repository/DefaultInvoicesRepository.kt index da03358dd..c1a9b766a 100644 --- a/sdk/src/main/kotlin/com/processout/sdk/api/repository/DefaultInvoicesRepository.kt +++ b/sdk/src/main/kotlin/com/processout/sdk/api/repository/DefaultInvoicesRepository.kt @@ -1,7 +1,17 @@ package com.processout.sdk.api.repository import com.processout.sdk.api.model.request.* +import com.processout.sdk.api.model.request.napm.v2.NativeAlternativePaymentAuthorizationRequestBody +import com.processout.sdk.api.model.request.napm.v2.NativeAlternativePaymentAuthorizationRequestBody.SubmitData +import com.processout.sdk.api.model.request.napm.v2.PONativeAlternativePaymentAuthorizationRequest +import com.processout.sdk.api.model.request.napm.v2.PONativeAlternativePaymentAuthorizationRequest.Parameter +import com.processout.sdk.api.model.request.napm.v2.PONativeAlternativePaymentAuthorizationRequest.Parameter.Value +import com.processout.sdk.api.model.request.napm.v2.PONativeAlternativePaymentRequest import com.processout.sdk.api.model.response.* +import com.processout.sdk.api.model.response.napm.v2.NativeAlternativePaymentAuthorizationResponseBody +import com.processout.sdk.api.model.response.napm.v2.NativeAlternativePaymentNextStep +import com.processout.sdk.api.model.response.napm.v2.PONativeAlternativePaymentAuthorizationResponse +import com.processout.sdk.api.model.response.napm.v2.PONativeAlternativePaymentNextStep import com.processout.sdk.api.network.HeaderConstants.CLIENT_SECRET import com.processout.sdk.api.network.InvoicesApi import com.processout.sdk.core.* @@ -25,6 +35,24 @@ internal class DefaultInvoicesRepository( ) } + override suspend fun authorizeInvoice( + request: PONativeAlternativePaymentAuthorizationRequest + ) = apiCall { + api.authorizeInvoice( + invoiceId = request.invoiceId, + request = request.toBody() + ) + }.map { it.toModel() } + + override suspend fun nativeAlternativePayment( + request: PONativeAlternativePaymentRequest + ) = apiCall { + api.nativeAlternativePayment( + invoiceId = request.invoiceId, + gatewayConfigurationId = request.gatewayConfigurationId + ) + }.map { it.toModel() } + override suspend fun initiatePayment( request: PONativeAlternativePaymentMethodRequest ) = apiCall { @@ -127,6 +155,40 @@ internal class DefaultInvoicesRepository( nativeApm = NativeAPMRequestParameters(parameterValues = parameters) ) + private fun PONativeAlternativePaymentAuthorizationRequest.toBody() = + NativeAlternativePaymentAuthorizationRequestBody( + gatewayConfigurationId = gatewayConfigurationId, + submitData = parameters?.let { SubmitData(parameters = it.map()) } + ) + + private fun Map.map() = + mapValues { (_, parameter) -> + when (val value = parameter.value) { + is Value.String -> value.value + is Value.PhoneNumber -> value + } + } + + private fun NativeAlternativePaymentAuthorizationResponseBody.toModel() = + PONativeAlternativePaymentAuthorizationResponse( + state = state, + nextStep = nextStep?.let { + when (it) { + is NativeAlternativePaymentNextStep.SubmitData -> + PONativeAlternativePaymentNextStep.SubmitData( + parameterDefinitions = it.parameters.parameterDefinitions + ) + is NativeAlternativePaymentNextStep.Redirect -> + PONativeAlternativePaymentNextStep.Redirect( + url = it.parameters.url + ) + NativeAlternativePaymentNextStep.Unknown -> + PONativeAlternativePaymentNextStep.Unknown + } + }, + customerInstructions = customerInstructions + ) + private fun ProcessOutResult>.map() = fold( onSuccess = { response -> response.body()?.let { invoice -> diff --git a/sdk/src/main/kotlin/com/processout/sdk/api/repository/InvoicesRepository.kt b/sdk/src/main/kotlin/com/processout/sdk/api/repository/InvoicesRepository.kt index 8030d06d4..5b617539b 100644 --- a/sdk/src/main/kotlin/com/processout/sdk/api/repository/InvoicesRepository.kt +++ b/sdk/src/main/kotlin/com/processout/sdk/api/repository/InvoicesRepository.kt @@ -4,7 +4,10 @@ import com.processout.sdk.api.model.request.POCreateInvoiceRequest import com.processout.sdk.api.model.request.POInvoiceAuthorizationRequest import com.processout.sdk.api.model.request.POInvoiceRequest import com.processout.sdk.api.model.request.PONativeAlternativePaymentMethodRequest +import com.processout.sdk.api.model.request.napm.v2.PONativeAlternativePaymentAuthorizationRequest +import com.processout.sdk.api.model.request.napm.v2.PONativeAlternativePaymentRequest import com.processout.sdk.api.model.response.* +import com.processout.sdk.api.model.response.napm.v2.PONativeAlternativePaymentAuthorizationResponse import com.processout.sdk.core.ProcessOutCallback import com.processout.sdk.core.ProcessOutResult import com.processout.sdk.core.annotation.ProcessOutInternalApi @@ -15,6 +18,14 @@ internal interface InvoicesRepository { request: POInvoiceAuthorizationRequest ): ProcessOutResult + suspend fun authorizeInvoice( + request: PONativeAlternativePaymentAuthorizationRequest + ): ProcessOutResult + + suspend fun nativeAlternativePayment( + request: PONativeAlternativePaymentRequest + ): ProcessOutResult + suspend fun initiatePayment( request: PONativeAlternativePaymentMethodRequest ): ProcessOutResult diff --git a/sdk/src/main/kotlin/com/processout/sdk/api/service/DefaultInvoicesService.kt b/sdk/src/main/kotlin/com/processout/sdk/api/service/DefaultInvoicesService.kt index 696e33a1c..5d46b4f4c 100644 --- a/sdk/src/main/kotlin/com/processout/sdk/api/service/DefaultInvoicesService.kt +++ b/sdk/src/main/kotlin/com/processout/sdk/api/service/DefaultInvoicesService.kt @@ -6,10 +6,13 @@ import com.processout.sdk.api.model.request.POCreateInvoiceRequest import com.processout.sdk.api.model.request.POInvoiceAuthorizationRequest import com.processout.sdk.api.model.request.POInvoiceRequest import com.processout.sdk.api.model.request.PONativeAlternativePaymentMethodRequest +import com.processout.sdk.api.model.request.napm.v2.PONativeAlternativePaymentAuthorizationRequest +import com.processout.sdk.api.model.request.napm.v2.PONativeAlternativePaymentRequest import com.processout.sdk.api.model.response.POInvoice import com.processout.sdk.api.model.response.PONativeAlternativePaymentMethod import com.processout.sdk.api.model.response.PONativeAlternativePaymentMethodCapture import com.processout.sdk.api.model.response.PONativeAlternativePaymentMethodTransactionDetails +import com.processout.sdk.api.model.response.napm.v2.PONativeAlternativePaymentAuthorizationResponse import com.processout.sdk.api.repository.InvoicesRepository import com.processout.sdk.core.* import com.processout.sdk.core.POFailure.Code.Cancelled @@ -162,6 +165,16 @@ internal class DefaultInvoicesService( } } + override suspend fun authorize( + request: PONativeAlternativePaymentAuthorizationRequest + ): ProcessOutResult = + repository.authorizeInvoice(request) + + override suspend fun nativeAlternativePayment( + request: PONativeAlternativePaymentRequest + ): ProcessOutResult = + repository.nativeAlternativePayment(request) + override suspend fun initiatePayment( request: PONativeAlternativePaymentMethodRequest ): ProcessOutResult = diff --git a/sdk/src/main/kotlin/com/processout/sdk/api/service/POInvoicesService.kt b/sdk/src/main/kotlin/com/processout/sdk/api/service/POInvoicesService.kt index 062651f2f..65cdce2ff 100644 --- a/sdk/src/main/kotlin/com/processout/sdk/api/service/POInvoicesService.kt +++ b/sdk/src/main/kotlin/com/processout/sdk/api/service/POInvoicesService.kt @@ -4,10 +4,13 @@ import com.processout.sdk.api.model.request.POCreateInvoiceRequest import com.processout.sdk.api.model.request.POInvoiceAuthorizationRequest import com.processout.sdk.api.model.request.POInvoiceRequest import com.processout.sdk.api.model.request.PONativeAlternativePaymentMethodRequest +import com.processout.sdk.api.model.request.napm.v2.PONativeAlternativePaymentAuthorizationRequest +import com.processout.sdk.api.model.request.napm.v2.PONativeAlternativePaymentRequest import com.processout.sdk.api.model.response.POInvoice import com.processout.sdk.api.model.response.PONativeAlternativePaymentMethod import com.processout.sdk.api.model.response.PONativeAlternativePaymentMethodCapture import com.processout.sdk.api.model.response.PONativeAlternativePaymentMethodTransactionDetails +import com.processout.sdk.api.model.response.napm.v2.PONativeAlternativePaymentAuthorizationResponse import com.processout.sdk.core.ProcessOutCallback import com.processout.sdk.core.ProcessOutResult import com.processout.sdk.core.annotation.ProcessOutInternalApi @@ -63,6 +66,24 @@ interface POInvoicesService { threeDSService: PO3DSService ): ProcessOutResult + /** + * Authorize invoice with the given request. + */ + /** @suppress */ + @ProcessOutInternalApi + suspend fun authorize( + request: PONativeAlternativePaymentAuthorizationRequest + ): ProcessOutResult + + /** + * Fetch native alternative payment details. + */ + /** @suppress */ + @ProcessOutInternalApi + suspend fun nativeAlternativePayment( + request: PONativeAlternativePaymentRequest + ): ProcessOutResult + /** * Initiates native alternative payment with the given request. */ diff --git a/sdk/src/main/kotlin/com/processout/sdk/di/NetworkGraph.kt b/sdk/src/main/kotlin/com/processout/sdk/di/NetworkGraph.kt index c4e15f9b2..add1d7f3d 100644 --- a/sdk/src/main/kotlin/com/processout/sdk/di/NetworkGraph.kt +++ b/sdk/src/main/kotlin/com/processout/sdk/di/NetworkGraph.kt @@ -2,6 +2,9 @@ package com.processout.sdk.di import com.processout.sdk.api.model.response.PODynamicCheckoutPaymentMethod import com.processout.sdk.api.model.response.PODynamicCheckoutPaymentMethod.* +import com.processout.sdk.api.model.response.napm.v2.NativeAlternativePaymentNextStep +import com.processout.sdk.api.model.response.napm.v2.PONativeAlternativePaymentCustomerInstruction +import com.processout.sdk.api.model.response.napm.v2.PONativeAlternativePaymentNextStep.SubmitData.Parameter import com.processout.sdk.api.network.* import com.processout.sdk.api.network.interceptor.BasicAuthInterceptor import com.processout.sdk.api.network.interceptor.RetryInterceptor @@ -53,18 +56,48 @@ internal class DefaultNetworkGraph( override val moshi: Moshi by lazy { Moshi.Builder() .add(Date::class.java, Rfc3339DateJsonAdapter()) - .add( - PolymorphicJsonAdapterFactory.of(PODynamicCheckoutPaymentMethod::class.java, "type") - .withSubtype(Card::class.java, "card") - .withSubtype(CardCustomerToken::class.java, "card_customer_token") - .withSubtype(GooglePay::class.java, "googlepay") - .withSubtype(AlternativePayment::class.java, "apm") - .withSubtype(AlternativePaymentCustomerToken::class.java, "apm_customer_token") - .withDefaultValue(Unknown) - ) + .addNativeAlternativePaymentAdapter() + .addDynamicCheckoutAdapter() .build() } + private fun Moshi.Builder.addNativeAlternativePaymentAdapter() = + add( + PolymorphicJsonAdapterFactory.of(NativeAlternativePaymentNextStep::class.java, "type") + .withSubtype(NativeAlternativePaymentNextStep.SubmitData::class.java, "submit_data") + .withSubtype(NativeAlternativePaymentNextStep.Redirect::class.java, "redirect") + .withDefaultValue(NativeAlternativePaymentNextStep.Unknown) + ).add( + PolymorphicJsonAdapterFactory.of(Parameter::class.java, "type") + .withSubtype(Parameter.Text::class.java, "text") + .withSubtype(Parameter.SingleSelect::class.java, "single-select") + .withSubtype(Parameter.Bool::class.java, "boolean") + .withSubtype(Parameter.Digits::class.java, "digits") + .withSubtype(Parameter.PhoneNumber::class.java, "phone") + .withSubtype(Parameter.Email::class.java, "email") + .withSubtype(Parameter.Card::class.java, "card") + .withSubtype(Parameter.Otp::class.java, "otp") + .withDefaultValue(Parameter.Unknown) + ).add( + PolymorphicJsonAdapterFactory.of(PONativeAlternativePaymentCustomerInstruction::class.java, "type") + .withSubtype(PONativeAlternativePaymentCustomerInstruction.Text::class.java, "text") + .withSubtype(PONativeAlternativePaymentCustomerInstruction.Image::class.java, "image_url") + .withSubtype(PONativeAlternativePaymentCustomerInstruction.Barcode::class.java, "barcode") + .withSubtype(PONativeAlternativePaymentCustomerInstruction.Group::class.java, "group") + .withDefaultValue(PONativeAlternativePaymentCustomerInstruction.Unknown) + ) + + private fun Moshi.Builder.addDynamicCheckoutAdapter() = + add( + PolymorphicJsonAdapterFactory.of(PODynamicCheckoutPaymentMethod::class.java, "type") + .withSubtype(Card::class.java, "card") + .withSubtype(CardCustomerToken::class.java, "card_customer_token") + .withSubtype(GooglePay::class.java, "googlepay") + .withSubtype(AlternativePayment::class.java, "apm") + .withSubtype(AlternativePaymentCustomerToken::class.java, "apm_customer_token") + .withDefaultValue(Unknown) + ) + private val retrofit: Retrofit by lazy { Retrofit.Builder() .baseUrl(baseUrl)