git.iko.soy/typeable/connexpay
on master help sign in
Explicitly split Payment errors from Connection errors.

The latter would normally be an exception, while the former must be handled as a part of payment workflow.

commitff0dd027e19d790796380588d4ec07aeb6580984 authorNick <nick@typeable.io> dateMon 6 May 2024, 13:00 (2 years ago) parent44b3181
4 files changed+25−14
connexpay/src/Web/Connexpay.hs+2−1 connexpay/src/Web/Connexpay/Data.hs+16−6 connexpay/src/Web/Connexpay/Init.hs+1−1 connexpay/src/Web/Connexpay/Types.hs+6−6
connexpay/src/Web/Connexpay.hs+2−1
@@ -2,8 +2,9 @@ module Web.Connexpay ( module Payments
22 , initConnexpay
33 , Connexpay(..)
44 , ConnexpayM
5− , PaymentError(..)
65 , PaymentFailure(..)
6+ , ConnectionError(..)
7+ , ConnexpayError(..)
78 , TransactionStatus(..)
89 , describeFailure
910 , runConnexpay
connexpay/src/Web/Connexpay/Data.hs+16−6
@@ -1,10 +1,11 @@
11{-# LANGUAGE OverloadedStrings #-}
22module Web.Connexpay.Data ( TransactionStatus(..)
33 , PaymentFailure(..)
4+ , ConnectionError(..)
5+ , ConnexpayError(..)
46 , describeFailure
57 , guessFailure
68 , ErrorMessage(..)
7− , PaymentError(..)
89 ) where
910
1011import Data.Aeson
@@ -69,8 +70,17 @@ instance FromJSON ErrorMessage where
6970 <*> o .: "errorId"
7071 parseJSON v = typeMismatch "ErrorMessage" v
7172
72−data PaymentError = ParseError String
73− | InvalidUrl String String
74− | HttpFailure HttpExceptionContent
75− | PaymentFailure PaymentFailure
76− deriving (Show)
73+data ConnectionError = ParseError String
74+ | InvalidUrl String String
75+ | HttpFailure HttpExceptionContent
76+ deriving Show
77+
78+-- | Error type for Connexpay.
79+-- There are two possible cases here:
80+-- * Connection failure means the payment may or may not have gotten through.
81+-- This would be typically thrown as an exception in an application.
82+-- * Payment failure means Connexpay returned an error and the payment wasn't authorised.
83+-- No exception here, this must be handled as usual.
84+data ConnexpayError = ConnectionError ConnectionError
85+ | PaymentFailure PaymentFailure
86+ deriving (Show)
connexpay/src/Web/Connexpay/Init.hs+1−1
@@ -23,7 +23,7 @@ initConnexpay :: (Text -> IO ()) -- ^ Logging function
2323 -> Bool -- ^ Whether to use TLS. If unsure, say True.
2424 -> Text -- ^ Login name.
2525 -> Text -- ^ Password.
26− -> IO (Either PaymentError Connexpay)
26+ -> IO (Either ConnexpayError Connexpay)
2727initConnexpay logf mgr devguid url tls login password =
2828 do v <- newEmptyMVar
2929 let env = Connexpay { logAction = logf
connexpay/src/Web/Connexpay/Types.hs+6−6
@@ -32,22 +32,22 @@ data Connexpay = Connexpay { logAction :: Text -> IO ()
3232 , password :: Text
3333 }
3434
35−newtype ConnexpayM a = ConnexpayM (ReaderT Connexpay (ExceptT PaymentError IO) a)
36− deriving (Functor, Applicative, Monad, MonadIO, MonadReader Connexpay, MonadError PaymentError)
35+newtype ConnexpayM a = ConnexpayM (ReaderT Connexpay (ExceptT ConnexpayError IO) a)
36+ deriving (Functor, Applicative, Monad, MonadIO, MonadReader Connexpay, MonadError ConnexpayError)
3737
3838instance MonadHttp ConnexpayM where
39− handleHttpException (JsonHttpException e) = throwError (ParseError e)
40− handleHttpException (VanillaHttpException (InvalidUrlException url why)) = throwError (InvalidUrl url why)
39+ handleHttpException (JsonHttpException e) = throwError (ConnectionError $ ParseError e)
40+ handleHttpException (VanillaHttpException (InvalidUrlException url why)) = throwError (ConnectionError $ InvalidUrl url why)
4141 handleHttpException (VanillaHttpException (HttpExceptionRequest _ (StatusCodeException resp bs)))
4242 | Just err <- decodeStrict @ErrorMessage bs
4343 , Just f <- guessFailure (statusCode $ responseStatus resp) err.message = throwError (PaymentFailure f)
44− handleHttpException (VanillaHttpException (HttpExceptionRequest _ c)) = throwError (HttpFailure c)
44+ handleHttpException (VanillaHttpException (HttpExceptionRequest _ c)) = throwError (ConnectionError $ HttpFailure c)
4545
4646 getHttpConfig = do mgr <- asks (.manager)
4747 pure (defaultHttpConfig { httpConfigAltManager = Just mgr })
4848
4949
50−runConnexpay :: Connexpay -> ConnexpayM a -> IO (Either PaymentError a)
50+runConnexpay :: Connexpay -> ConnexpayM a -> IO (Either ConnexpayError a)
5151runConnexpay cp (ConnexpayM a) = runExceptT (runReaderT a cp)
5252
5353runConnexpay_ :: Connexpay -> ConnexpayM a -> IO ()