Skip to content
This repository was archived by the owner on Feb 4, 2025. It is now read-only.
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 @@ -10,8 +10,9 @@ import org.junit.Assert.assertThat
import org.junit.Assert.assertTrue
import org.junit.Test
import org.wordpress.android.fluxc.model.SiteModel
import org.wordpress.android.fluxc.model.payments.inperson.WCCapturePaymentErrorType.CAPTURE_ERROR
import org.wordpress.android.fluxc.model.payments.inperson.WCCapturePaymentErrorType
import org.wordpress.android.fluxc.model.payments.inperson.WCCapturePaymentErrorType.MISSING_ORDER
import org.wordpress.android.fluxc.model.payments.inperson.WCCapturePaymentErrorType.CAPTURE_ERROR
import org.wordpress.android.fluxc.model.payments.inperson.WCCapturePaymentErrorType.PAYMENT_ALREADY_CAPTURED
import org.wordpress.android.fluxc.model.payments.inperson.WCCapturePaymentErrorType.SERVER_ERROR
import org.wordpress.android.fluxc.model.payments.inperson.WCPaymentAccountResult.WCPaymentAccountStatus
Expand Down Expand Up @@ -123,6 +124,24 @@ class MockedStack_InPersonPaymentsTest : MockedStack_Base() {
assertTrue(result.error?.type == SERVER_ERROR)
}

@Test
fun whenAmountTooSmallErrorThenAmountTooSmallErrorReturned() = runBlocking {
interceptor.respondWithError("wc-pay-capture-terminal-payment-response-amount-too-small.json", 400)

val result = restClient.capturePayment(
WOOCOMMERCE_PAYMENTS,
testSite,
DUMMY_PAYMENT_ID,
-10L
)

assertTrue(result.error!!.type == CAPTURE_ERROR)
assertEquals("amount_too_small", result.error!!.extraData!!["error_type"])
val extraDetails = result.error!!.extraData!!["extra_details"] as Map<*, *>
assertEquals(50.0, extraDetails["minimum_amount"])
assertEquals("USD", extraDetails["minimum_amount_currency"])
}

@Test
fun whenLoadAccountInvalidStatusThenFallbacksToUnknown() = runBlocking {
interceptor.respondWith("wc-pay-load-account-response-new-status.json")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"code": "wcpay_capture_error",
"message": "Payment capture failed to complete with the following message: Minimum required amount was not reached. The minimum amount to capture is 0.5 USD.",
"data": {
"status": 400,
"extra_details": {
"minimum_amount": 50,
"minimum_amount_currency": "USD"
},
"error_type": "amount_too_small"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ class WCCapturePaymentResponsePayload(

class WCCapturePaymentError(
val type: WCCapturePaymentErrorType = GENERIC_ERROR,
val message: String = ""
val message: String = "",
val extraData: Map<String, Any>? = null
) : OnChangedError

enum class WCCapturePaymentErrorType {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package org.wordpress.android.fluxc.network.rest.wpcom.wc.payments.inperson

import com.android.volley.VolleyError
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import org.wordpress.android.fluxc.generated.endpoint.WOOCOMMERCE
import org.wordpress.android.fluxc.model.SiteModel
import org.wordpress.android.fluxc.model.payments.inperson.WCCapturePaymentError
Expand All @@ -26,9 +29,13 @@ import org.wordpress.android.fluxc.store.WCInPersonPaymentsStore.InPersonPayment
import org.wordpress.android.fluxc.store.WCInPersonPaymentsStore.InPersonPaymentsPluginType.STRIPE
import org.wordpress.android.fluxc.store.WCInPersonPaymentsStore.InPersonPaymentsPluginType.WOOCOMMERCE_PAYMENTS
import org.wordpress.android.fluxc.utils.toWooPayload
import org.wordpress.android.util.AppLog
import javax.inject.Inject

class InPersonPaymentsRestClient @Inject constructor(private val wooNetwork: WooNetwork) {
class InPersonPaymentsRestClient @Inject constructor(
private val wooNetwork: WooNetwork,
private val gson: Gson,
) {
suspend fun fetchConnectionToken(
activePlugin: InPersonPaymentsPluginType,
site: SiteModel
Expand Down Expand Up @@ -71,15 +78,22 @@ class InPersonPaymentsRestClient @Inject constructor(private val wooNetwork: Woo
response.data?.let { data ->
WCCapturePaymentResponsePayload(site, paymentId, orderId, data.status)
} ?: WCCapturePaymentResponsePayload(
mapToCapturePaymentError(error = null, message = "status field is null, but isError == false"),
mapToCapturePaymentError(
error = null,
message = "status field is null, but isError == false"
),
site,
paymentId,
orderId
)
}

is WPAPIResponse.Error -> {
WCCapturePaymentResponsePayload(
mapToCapturePaymentError(response.error, response.error.message ?: "Unexpected error"),
mapToCapturePaymentError(
response.error,
response.error.message ?: "Unexpected error"
),
site,
paymentId,
orderId
Expand Down Expand Up @@ -146,9 +160,13 @@ class InPersonPaymentsRestClient @Inject constructor(private val wooNetwork: Woo
)
)
}

is WPAPIResponse.Error -> {
WCTerminalStoreLocationResult(
mapToStoreLocationForSiteError(response.error, response.error.message ?: "Unexpected error")
mapToStoreLocationForSiteError(
response.error,
response.error.message ?: "Unexpected error"
)
)
}
}
Expand Down Expand Up @@ -194,7 +212,10 @@ class InPersonPaymentsRestClient @Inject constructor(private val wooNetwork: Woo
return response.toWooPayload()
}

private fun mapToCapturePaymentError(error: WPAPINetworkError?, message: String): WCCapturePaymentError {
private fun mapToCapturePaymentError(
error: WPAPINetworkError?,
message: String
): WCCapturePaymentError {
val type = when {
error == null -> GENERIC_ERROR
error.errorCode == "wcpay_missing_order" -> MISSING_ORDER
Expand All @@ -206,7 +227,23 @@ class InPersonPaymentsRestClient @Inject constructor(private val wooNetwork: Woo
error.type == GenericErrorType.NETWORK_ERROR -> NETWORK_ERROR
else -> GENERIC_ERROR
}
return WCCapturePaymentError(type, message)
return WCCapturePaymentError(
type = type,
message = message,
extraData = error?.volleyError?.getExtraData()
)
}

@Suppress("TooGenericExceptionCaught")
private fun VolleyError.getExtraData(): Map<String, Any>? {
val jsonString = this.networkResponse?.data?.toString(Charsets.UTF_8)
return try {
val mapType = object : TypeToken<Map<String, Any>>() {}.type
return gson.fromJson<Map<String, Any>>(jsonString, mapType)["data"] as Map<String, Any>?
} catch (e: Throwable) {
AppLog.e(AppLog.T.API, "Error parsing volley error $jsonString", e)
null
}
}

private fun mapToStoreLocationForSiteError(error: WPAPINetworkError?, message: String):
Expand Down
Loading