From f5ead5af74099cef17e81aadf559477a4bbc96cf Mon Sep 17 00:00:00 2001 From: "Kjell M. Myksvoll" Date: Tue, 3 Dec 2019 14:57:16 +0100 Subject: [PATCH] Fix and update error messages for Stripe 'card' errors Now logs card failures as 'info' messages. --- .../customer/endpoint/store/SubscriberDAOImpl.kt | 13 +++++++++---- .../org/ostelco/prime/storage/graph/Neo4jStore.kt | 6 +++--- .../prime/paymentprocessor/subscribers/Reporter.kt | 2 +- .../kotlin/org/ostelco/prime/apierror/ApiError.kt | 2 +- .../org/ostelco/prime/apierror/ApiErrorCodes.kt | 1 + 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/customer-endpoint/src/main/kotlin/org/ostelco/prime/customer/endpoint/store/SubscriberDAOImpl.kt b/customer-endpoint/src/main/kotlin/org/ostelco/prime/customer/endpoint/store/SubscriberDAOImpl.kt index d140d0537..6bd693eb0 100644 --- a/customer-endpoint/src/main/kotlin/org/ostelco/prime/customer/endpoint/store/SubscriberDAOImpl.kt +++ b/customer-endpoint/src/main/kotlin/org/ostelco/prime/customer/endpoint/store/SubscriberDAOImpl.kt @@ -2,6 +2,7 @@ package org.ostelco.prime.customer.endpoint.store import arrow.core.Either import arrow.core.flatMap +import arrow.core.left import org.ostelco.prime.activation.Activation import org.ostelco.prime.apierror.ApiError import org.ostelco.prime.apierror.ApiErrorCode @@ -29,6 +30,7 @@ import org.ostelco.prime.model.Subscription import org.ostelco.prime.model.withSimProfileStatusAsInstalled import org.ostelco.prime.module.getResource import org.ostelco.prime.paymentprocessor.PaymentProcessor +import org.ostelco.prime.paymentprocessor.core.CardError import org.ostelco.prime.paymentprocessor.core.PlanAlredyPurchasedError import org.ostelco.prime.paymentprocessor.core.ProductInfo import org.ostelco.prime.paymentprocessor.core.SourceDetailsInfo @@ -304,12 +306,15 @@ class SubscriberDAOImpl : SubscriberDAO { saveCard).fold( { paymentError -> when (paymentError) { - is PlanAlredyPurchasedError -> Either.left(mapPaymentErrorToApiError("Already subscribed to plan. ", + is CardError -> mapPaymentErrorToApiError("Payment source rejected. ", + ApiErrorCode.PAYMENT_SOURCE_REJECTED, + paymentError).left() + is PlanAlredyPurchasedError -> mapPaymentErrorToApiError("Already subscribed to plan. ", ApiErrorCode.ALREADY_SUBSCRIBED_TO_PLAN, - paymentError)) - else -> Either.left(mapPaymentErrorToApiError("Failed to purchase product. ", + paymentError).left() + else -> mapPaymentErrorToApiError("Failed to purchase product. ", ApiErrorCode.FAILED_TO_PURCHASE_PRODUCT, - paymentError)) + paymentError).left() } // if no error, check if this was a topup of empty account, in that case send activate }, { productInfo -> diff --git a/neo4j-store/src/main/kotlin/org/ostelco/prime/storage/graph/Neo4jStore.kt b/neo4j-store/src/main/kotlin/org/ostelco/prime/storage/graph/Neo4jStore.kt index 4613b3483..e8aa8845f 100644 --- a/neo4j-store/src/main/kotlin/org/ostelco/prime/storage/graph/Neo4jStore.kt +++ b/neo4j-store/src/main/kotlin/org/ostelco/prime/storage/graph/Neo4jStore.kt @@ -1567,8 +1567,8 @@ object Neo4jStoreSingleton : GraphStore { it }.linkReversalActionToTransaction(transaction) { paymentProcessor.removeInvoice(it.id) - logger.warn(NOTIFY_OPS_MARKER, """ - Failed to pay invoice for customer ${customer.id}, invoice-id: ${it.id}. + logger.info(NOTIFY_OPS_MARKER, """ + Payment of invoice ${it.id} failed for customer ${customer.id}. Verify that the invoice has been deleted or voided in Stripe dashboard. """.trimIndent()) }.bind() @@ -1576,7 +1576,7 @@ object Neo4jStoreSingleton : GraphStore { /* Force immediate payment of the invoice. */ val (invoicePaymentInfo) = paymentProcessor.payInvoice(invoice.id) .mapLeft { - logger.warn("Payment of invoice ${invoice.id} failed for customer ${customer.id}.") + logger.info("Charging for invoice ${invoice.id} for product $sku failed for customer ${customer.id}.") /* Adds failed purchase to customer history. */ AuditLog.warn(customerId = customer.id, message = "Failed to complete purchase of product $sku for ${formatMoney(price)} " + diff --git a/payment-processor/src/main/kotlin/org/ostelco/prime/paymentprocessor/subscribers/Reporter.kt b/payment-processor/src/main/kotlin/org/ostelco/prime/paymentprocessor/subscribers/Reporter.kt index 4f8a86dde..247a78550 100644 --- a/payment-processor/src/main/kotlin/org/ostelco/prime/paymentprocessor/subscribers/Reporter.kt +++ b/payment-processor/src/main/kotlin/org/ostelco/prime/paymentprocessor/subscribers/Reporter.kt @@ -205,7 +205,7 @@ object Reporter { event) ) event.type == "payment_intent.payment_failed" -> logger.warn( - format("Failed to create payment ${intent.id} for ${currency(intent.amount, intent.currency)}", + format("Creating payment ${intent.id} of ${currency(intent.amount, intent.currency)} failed", event) ) event.type == "payment_intent.succeeded" -> logger.debug( diff --git a/prime-modules/src/main/kotlin/org/ostelco/prime/apierror/ApiError.kt b/prime-modules/src/main/kotlin/org/ostelco/prime/apierror/ApiError.kt index 708681923..7e6900655 100644 --- a/prime-modules/src/main/kotlin/org/ostelco/prime/apierror/ApiError.kt +++ b/prime-modules/src/main/kotlin/org/ostelco/prime/apierror/ApiError.kt @@ -34,7 +34,7 @@ object ApiErrorMapper { /* Log level depends on the type of payment error. */ fun mapPaymentErrorToApiError(description: String, errorCode: ApiErrorCode, paymentError: PaymentError): ApiError { if (paymentError is org.ostelco.prime.paymentprocessor.core.CardError) { - logger.warn("{}: {}, paymentError: {}", errorCode, description, asJson(paymentError)) + logger.info("{}: {}, paymentError: {}", errorCode, description, asJson(paymentError)) } else { logger.error("{}: {}, paymentError: {}", errorCode, description, asJson(paymentError)) } diff --git a/prime-modules/src/main/kotlin/org/ostelco/prime/apierror/ApiErrorCodes.kt b/prime-modules/src/main/kotlin/org/ostelco/prime/apierror/ApiErrorCodes.kt index 42835ebb1..4739d6da8 100644 --- a/prime-modules/src/main/kotlin/org/ostelco/prime/apierror/ApiErrorCodes.kt +++ b/prime-modules/src/main/kotlin/org/ostelco/prime/apierror/ApiErrorCodes.kt @@ -13,6 +13,7 @@ enum class ApiErrorCode { FAILED_TO_SET_DEFAULT_PAYMENT_SOURCE, FAILED_TO_FETCH_PAYMENT_SOURCES_LIST, FAILED_TO_REMOVE_PAYMENT_SOURCE, + PAYMENT_SOURCE_REJECTED, // payment monitor FAILED_TO_CHECK_API_VERSION,