@@ -4,13 +4,20 @@
4module Web.Connexpay.Payments ( CreditCard(..)
4module Web.Connexpay.Payments ( CreditCard(..)
5 , AuthResponse(..)
5 , AuthResponse(..)
6 , authorisePayment
6 , authorisePayment
12+import Web.Connexpay.Utils
14+import Control.Monad (void)
9import Control.Monad.Reader (asks)
15import Control.Monad.Reader (asks)
10import Control.Monad.Writer.Strict
16import Control.Monad.Writer.Strict
11import Data.Aeson
17import Data.Aeson
12−import Data.Aeson.Types (typeMismatch)
18+import Data.Aeson.Types (Pair, typeMismatch)
13import Data.Money
19import Data.Money
14import Data.Text (Text)
21import Data.Text (Text)
15import Data.Text qualified as Text
22import Data.Text qualified as Text
16import Data.Text.Encoding qualified as Text
23import Data.Text.Encoding qualified as Text
@@ -49,14 +56,24 @@ padDate :: Text -> Text
49padDate t | Text.length t == 1 = "0" <> t
56padDate t | Text.length t == 1 = "0" <> t
50 | otherwise = t
57 | otherwise = t
52−whenJust :: Monad m => Maybe a -> (a -> m ()) -> m ()
59+sendRequest' :: HttpResponse resp => Proxy resp -> Text -> [Pair] -> ConnexpayM resp
53−whenJust (Just x) f = f x
60+sendRequest' resp endpoint body =
54−whenJust Nothing _ = pure ()
61+ do tok <- bearerToken
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 ])
70+sendRequestJson :: FromJSON a => Text -> [Pair] -> ConnexpayM (JsonResponse a)
71+sendRequestJson = sendRequest' jsonResponse
56−tshow :: Show a => a -> Text
73+sendRequest_ :: Text -> [Pair] -> ConnexpayM ()
57−tshow = Text.pack . show
74+sendRequest_ ep = void . sendRequest' ignoreResponse ep
59−data AuthResponse = AuthResponse { paymentGuid :: Text
76+data AuthResponse = AuthResponse { paymentGuid :: SaleGuid
60 , status :: TransactionStatus
77 , status :: TransactionStatus
61 , processorStatusCode :: Maybe Text
78 , processorStatusCode :: Maybe Text
62 , processorMessage :: Maybe Text
79 , processorMessage :: Maybe Text
@@ -70,15 +87,23 @@ instance FromJSON AuthResponse where
70 parseJSON v = typeMismatch "AuthReponse" v
87 parseJSON v = typeMismatch "AuthReponse" v
72authorisePayment :: CreditCard -> Money USD -> ConnexpayM AuthResponse
89authorisePayment :: CreditCard -> Money USD -> ConnexpayM AuthResponse
73−authorisePayment cc amt = do guid <- asks (.deviceGuid)
90+authorisePayment cc amt = do resp <- sendRequestJson "authonlys" body
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
80 pure (responseBody resp)
91 pure (responseBody resp)
81− where reqBody guid = object [ "Card" .= cc
92+ where body = [ "Card" .= cc
82− , "Amount" .= getAmount amt
93+ , "Amount" .= getAmount amt
83− , "DeviceGuid" .= show guid
94+ ]
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 ]
103+capturePayment :: SaleGuid -> ConnexpayM ()
104+capturePayment pid = sendRequest_ "Captures" body
105+ where body = [ "AuthOnlyGuid" .= show pid ]
107+cancelPayment :: SaleGuid -> ConnexpayM ()
108+cancelPayment pid = sendRequest_ "cancel" body
109+ where body = [ "SaleGuid" .= show pid ]