@@ -4,13 +4,20 @@
44module Web.Connexpay.Payments ( CreditCard(..)
55 , AuthResponse(..)
66 , authorisePayment
7+ , voidPayment
8+ , capturePayment
9+ , cancelPayment
710 ) where
811
12+import Web.Connexpay.Utils
13+
14+import Control.Monad (void)
915import Control.Monad.Reader (asks)
1016import Control.Monad.Writer.Strict
1117import Data.Aeson
12−import Data.Aeson.Types (typeMismatch)
18+import Data.Aeson.Types (Pair, typeMismatch)
1319import Data.Money
20+import Data.Proxy
1421import Data.Text (Text)
1522import Data.Text qualified as Text
1623import Data.Text.Encoding qualified as Text
@@ -49,14 +56,24 @@ padDate :: Text -> Text
4956padDate t | Text.length t == 1 = "0" <> t
5057 | otherwise = t
5158
52−whenJust :: Monad m => Maybe a -> (a -> m ()) -> m ()
53−whenJust (Just x) f = f x
54−whenJust Nothing _ = pure ()
59+sendRequest' :: HttpResponse resp => Proxy resp -> Text -> [Pair] -> ConnexpayM resp
60+sendRequest' resp endpoint body =
61+ do tok <- bearerToken
62+ host <- asks (.url)
63+ let auth = header "Authorization" ("Bearer " <> Text.encodeUtf8 tok)
64+ url = http host /: "api" /: "v1" /: endpoint
65+ jbody <- ReqBodyJson . object <$> addGuid body
66+ req POST url jbody resp auth
67+ where addGuid b = do guid <- asks (.deviceGuid)
68+ return (b <> [ "DeviceGuid" .= show guid ])
69+
70+sendRequestJson :: FromJSON a => Text -> [Pair] -> ConnexpayM (JsonResponse a)
71+sendRequestJson = sendRequest' jsonResponse
5572
56−tshow :: Show a => a -> Text
57−tshow = Text.pack . show
73+sendRequest_ :: Text -> [Pair] -> ConnexpayM ()
74+sendRequest_ ep = void . sendRequest' ignoreResponse ep
5875
59−data AuthResponse = AuthResponse { paymentGuid :: Text
76+data AuthResponse = AuthResponse { paymentGuid :: SaleGuid
6077 , status :: TransactionStatus
6178 , processorStatusCode :: Maybe Text
6279 , processorMessage :: Maybe Text
@@ -70,15 +87,23 @@ instance FromJSON AuthResponse where
7087 parseJSON v = typeMismatch "AuthReponse" v
7188
7289authorisePayment :: CreditCard -> Money USD -> ConnexpayM AuthResponse
73−authorisePayment cc amt = do guid <- asks (.deviceGuid)
74− tok <- bearerToken
75− host <- asks (.url)
76− let body = ReqBodyJson (reqBody guid)
77− auth = header "Authorization" ("Bearer " <> Text.encodeUtf8 tok)
78− url = https host /: "api" /: "v1" /: "authonlys"
79− resp <- req POST url body jsonResponse auth
90+authorisePayment cc amt = do resp <- sendRequestJson "authonlys" body
8091 pure (responseBody resp)
81− where reqBody guid = object [ "Card" .= cc
82− , "Amount" .= getAmount amt
83− , "DeviceGuid" .= show guid
84− ]
92+ where body = [ "Card" .= cc
93+ , "Amount" .= getAmount amt
94+ ]
95+
96+voidPayment :: SaleGuid -> Maybe (Money USD) -> ConnexpayM ()
97+voidPayment pid amt = sendRequest_ "void" body
98+ where body = execWriter $
99+ do tell [ "AuthOnlyGuid" .= show pid ]
100+ whenJust amt $ \m ->
101+ tell [ "Amount" .= getAmount m ]
102+
103+capturePayment :: SaleGuid -> ConnexpayM ()
104+capturePayment pid = sendRequest_ "Captures" body
105+ where body = [ "AuthOnlyGuid" .= show pid ]
106+
107+cancelPayment :: SaleGuid -> ConnexpayM ()
108+cancelPayment pid = sendRequest_ "cancel" body
109+ where body = [ "SaleGuid" .= show pid ]