git.iko.soy/typeable/connexpay
on master help sign in
Docs.
commit42d971ccf89d0df4b0582268f08441f5421f5651 authorNick <nick@typeable.io> dateSun 24 Mar 2024, 21:36 (3 years ago) parent7d319d9
5 files changed+70−20
README.org+23 src/Tool.hs+1−1 src/Web/Connexpay.hs+8−3 src/Web/Connexpay/Init.hs+9−1 src/Web/Connexpay/Payments.hs+29−15
README.org+23
@@ -5,6 +5,29 @@
55
66ConnexPay is a credit card payment processing provider.
77
8+* How to use this library
9+
10+Here is a short example:
11+
12+#+begin_src
13+let logf msg = Text.putStrLn ("Connexpay log: " <> msg)
14+ cc = CreditCard ...
15+ amount = Money @USD 5.00
16+ vendor = Just "Best vendor out there"
17+httpmgr <- tlsManager
18+pay <- initConnexpay logf httpmgr deviceGuid cpHost True login password
19+
20+runConnexpay pay $ do
21+ sale <- authorisePayment cc amount vendor
22+ capturePayment sale.paymentGuid
23+#+end_src
24+
25+For more information, see Haddock docs.
26+
27+NOTE:
28+'PaymentError' type isn't used yet, but it will after more testing.
29+Connexpay test environment doesn't seem to report errors adequately.
30+
831* Links
932
1033Credit card sales API: https://docs.connexpay.com/reference/credit-card-sales
src/Tool.hs+1−1
@@ -74,7 +74,7 @@ main = do cmdLine <- execParser (info cmdParser mempty)
7474 Right cpi -> print =<< runConnexpay cpi (doThing cmdLine.operation)
7575
7676doThing :: Command -> ConnexpayM ()
77−doThing (AuthSale cc amt) = liftIO . print =<< authorisePayment cc usd
77+doThing (AuthSale cc amt) = liftIO . print =<< authorisePayment cc usd Nothing
7878 where usd = Money amt
7979doThing (VoidSale guid) = liftIO . print =<< voidPayment guid Nothing
8080doThing (CaptureSale guid) = liftIO . print =<< capturePayment guid
src/Web/Connexpay.hs+8−3
@@ -1,6 +1,11 @@
1−module Web.Connexpay ( module Export
1+module Web.Connexpay ( module Payments
2+ , initConnexpay
3+ , Connexpay
4+ , ConnexpayM
5+ , PaymentError(..)
6+ , runConnexpay
27 ) where
38
4−import Web.Connexpay.Init as Export
5−import Web.Connexpay.Payments as Export
9+import Web.Connexpay.Init
10+import Web.Connexpay.Payments as Payments
611import Web.Connexpay.Types as Export
src/Web/Connexpay/Init.hs+9−1
@@ -14,7 +14,15 @@ import Data.Text (Text)
1414import Network.HTTP.Client (Manager)
1515import Numeric.Natural
1616
17−initConnexpay :: (Text -> IO ()) -> Manager -> DeviceGuid -> Text -> Bool -> Text -> Text -> IO (Either PaymentError Connexpay)
17+-- | Initialise Connexpay state. Log in, authenticate, and obtain bearer token.
18+initConnexpay :: (Text -> IO ()) -- ^ Logging function
19+ -> Manager -- ^ HTTP client manager
20+ -> DeviceGuid -- ^ Device GUID. You must obtain this from ConnexPay
21+ -> Text -- ^ Connexpay host to connect with
22+ -> Bool -- ^ Whether to use TLS. If unsure, say True.
23+ -> Text -- ^ Login name.
24+ -> Text -- ^ Password.
25+ -> IO (Either PaymentError Connexpay)
1826initConnexpay logf mgr devguid url tls login password =
1927 do v <- newEmptyMVar
2028 let env = Connexpay { logAction = logf
src/Web/Connexpay/Payments.hs+29−15
@@ -30,10 +30,10 @@ import Web.Connexpay.Utils
3030-- | Credit card info
3131-- No 'Show' instance should be made for this type
3232-- in order to avoid sensitive data leaks.
33−data CreditCard = CreditCard { number :: Text
34− , cardholder :: Maybe Text
35− , expiration :: (Word, Word) -- ^ Expiration date (month,year)
36− , cvv :: Maybe Text
33+data CreditCard = CreditCard { number :: Text -- ^ Credit card number, as 'Text'.
34+ , cardholder :: Maybe Text -- ^ Cardholder name, optional.
35+ , expiration :: (Word, Word) -- ^ Expiration date (month,year).
36+ , cvv :: Maybe Text -- ^ CVC/CVV code.
3737 }
3838
3939type ShowError = TypeError.Text "CreditCard must not be shown in order to avoid leaking sensitive data"
@@ -89,14 +89,23 @@ instance FromJSON AuthResponse where
8989 <*> o .:? "processorResponseMessage"
9090 parseJSON v = typeMismatch "AuthReponse" v
9191
92−authorisePayment :: CreditCard -> Money USD -> ConnexpayM AuthResponse
93−authorisePayment cc amt = do resp <- sendRequestJson "authonlys" body
94− pure (responseBody resp)
95− where body = [ "Card" .= cc
96− , "Amount" .= getAmount amt
97− ]
98−
99−voidPayment :: SaleGuid -> Maybe (Money USD) -> ConnexpayM ()
92+-- | Authorise a credit card payment.
93+authorisePayment :: CreditCard -- ^ Credit card details (see 'CreditCard')
94+ -> Money USD -- ^ Amount to charge, USD
95+ -> Maybe Text -- ^ Merchant description that will appear in a customer's statement.
96+ -> ConnexpayM AuthResponse
97+authorisePayment cc amt vendor = do resp <- sendRequestJson "authonlys" body
98+ pure (responseBody resp)
99+ where body = execWriter $
100+ do tell [ "Card" .= cc ]
101+ tell ["Amount" .= getAmount amt ]
102+ whenJust vendor $ \v ->
103+ tell [ "StatementDescription" .= v ]
104+
105+-- | Void payment
106+voidPayment :: SaleGuid -- ^ Sales GUID, obtained from 'authorisePayment'.
107+ -> Maybe (Money USD) -- ^ Optionally, you may only void a partial sum, with the rest being subsequently charged.
108+ -> ConnexpayM ()
100109voidPayment pid amt = sendRequest_ "void" body
101110 where body = execWriter $
102111 do tell [ "AuthOnlyGuid" .= show pid ]
@@ -109,12 +118,17 @@ data CPTransaction = CPTransaction { expectedPayments :: Int32 }
109118instance ToJSON CPTransaction where
110119 toJSON t = object [ "ExpectedPayments" .= t.expectedPayments ]
111120
112−
113−capturePayment :: SaleGuid -> ConnexpayM ()
121+-- | Capture payment, previously authorised through 'authorisePayment'.
122+capturePayment :: SaleGuid -- ^ Sales GUID, obtained from 'authorisePayment'.
123+ -> ConnexpayM ()
114124capturePayment pid = sendRequest_ "Captures" body
115125 where body = [ "AuthOnlyGuid" .= show pid
116126 , "ConnexPayTransaction" .= CPTransaction 1 ]
117127
118−cancelPayment :: SaleGuid -> ConnexpayM ()
128+-- | Cancel voided or captured payment.
129+-- In case of an authorised-only payment, voiding is performed.
130+-- Otherwise, a payment goes through a refund process.
131+cancelPayment :: SaleGuid -- ^ Sales GUID, obtained from 'authorisePayment'.
132+ -> ConnexpayM ()
119133cancelPayment pid = sendRequest_ "cancel" body
120134 where body = [ "SaleGuid" .= show pid ]