cielo-0.1.2.0: src/Web/Payments/Cielo.hs
module Web.Payments.Cielo
(
-- * Running the API calls
runCielo
, cieloConfigFromEnv
, productionEnv
, sandboxEnv
-- * Available API Calls
-- ** Generating Merchant Order IDs
, getMerchantOrderId
-- ** Sales
, createSale
, querySale
, captureSale
, voidSale
-- *** Low-Level
, updateSale
-- ** Querying Sales
, querySalesByMerchantOrderId
, queryRecurrentSale
-- ** Recurrent Sales
-- *** Cancelling / Uncancelling
, cancelRecurrentPayment
, uncancelRecurrentPayment
-- *** Updates
, updateRecurrentPaymentEndDate
, updateRecurrentPaymentPayment
, updateRecurrentPaymentInterval
, updateRecurrentPaymentInstallments
, updateRecurrentPaymentCustomer
, updateRecurrentPaymentRecurrencyDay
, updateRecurrentPaymentNextPaymentDate
, updateRecurrentPaymentNextPaymentAmount
-- * Types
, CieloConfig(..)
, CreditCard(..)
, MonadCielo
, CieloError(..)
, Merchant(..)
, Environment(..)
, Sale(..)
, PaymentProvider(..)
, PaymentType(..)
, Currency(..)
, Interval(..)
, RecurrentPayment(..)
, RecurrentPaymentQuery(..)
, Address(..)
, Customer(..)
, Payment(..)
, SalesByMerchantOrderQuery(..)
-- * Re-exports
, Default(..)
, MonadIO
, liftIO
, FromJSON(..)
, ToJSON(..)
)
where
import Control.Exception
import Control.Monad
import Control.Monad.Except
import Control.Monad.Reader
import Data.Aeson
import Data.Convertible
import Data.Default
import Data.Monoid ((<>))
import Data.Text (Text, pack)
import Data.UUID
import Data.UUID.V4
import Network.Wreq hiding (get, post, put)
import System.Environment
import Web.Payments.Cielo.Types
import Web.Payments.Cielo.Util
-- | API Calls happen in a 'MonadCielo' type-class
-- 'CieloM' is a helper instance of this class, which runs exceptions on the IO
-- monad and exposes the configuration through a 'ReaderT'
runCielo :: CieloConfig -> CieloM a -> IO a
runCielo cnf rdr = do
eret <- runExceptT (runReaderT rdr cnf)
case eret of
Left err -> throwIO err
Right ret -> return ret
-- | We can load 'CieloConfig' from the @"CIELO_MERCHANTID"@ and
-- @"CIELO_MERCHANTKEY"@ environment variables
cieloConfigFromEnv :: IO CieloConfig
cieloConfigFromEnv = do
m <- Merchant <$> (pack <$> getEnv "CIELO_MERCHANTID")
<*> (pack <$> getEnv "CIELO_MERCHANTKEY")
return $ CieloConfig m sandboxEnv
-- | Generates a new merchant UIID
getMerchantOrderId :: MonadIO m => m Text
getMerchantOrderId = liftIO $ toText <$> nextRandom
-- | Creates a 'Sale'
createSale :: MonadCielo m => Sale -> m Sale
createSale = post "/1/sales" []
-- | Queries for a 'Sale' given it's paymentId
querySale :: MonadCielo m => Text -> m Sale
querySale paymentId = get ("/1/sales/" <> convert paymentId) []
-- | Queries for a sales given a merchant UUID
querySalesByMerchantOrderId :: MonadCielo m => Text -> m SalesByMerchantOrderQuery
querySalesByMerchantOrderId merchantOrderId = get "/1/sales" [("merchantOrderId", merchantOrderId)]
-- | Queries for a recurrent sale given it's paymentId
queryRecurrentSale :: MonadCielo m => Text -> m RecurrentPaymentQuery
queryRecurrentSale recurrentPaymentId = get ("/1/RecurrentPayment/" <> convert recurrentPaymentId) []
-- | Captures a sale
captureSale
:: MonadCielo m
=> Text
-- ^ Payment ID
-> Maybe Int
-- ^ Amount
-> Maybe Int
-- ^ Service Tax Amount
-> m SaleUpdate
captureSale paymentId mamount mserviceTaxAmount =
updateSale paymentId "capture" query
where
query =
maybe [] (\a -> [("amount", convert (show a))]) mamount ++
maybe [] (\a -> [("serviceTaxAmount", convert (show a))]) mserviceTaxAmount
-- | Voids a sale
voidSale
:: MonadCielo m
=> Text
-- ^ Payment ID
-> Maybe Int
-- ^ Amount
-> m SaleUpdate
voidSale paymentId mamount = updateSale paymentId "void" query
where
query = maybe [] (\a -> [("amount", convert (show a))]) mamount
-- | Updates a sale (Generalized PUT over a type of Sale update @/1/sales/:id/:type@)
updateSale
:: MonadCielo m
=> Text
-- ^ Payment ID
-> Text
-- ^ :type
-> [(Text, Text)]
-- ^ Data to PUT
-> m SaleUpdate
updateSale paymentId paymentType query = put
("/1/sales/" <> convert paymentId <> "/" <> convert paymentType)
query
(object [])
cancelRecurrentPayment :: MonadCielo m => Text -> m ()
cancelRecurrentPayment recurrentPaymentId = void $ sendRaw putWith
("/1/RecurrentPayment/" <> convert recurrentPaymentId <> "/Deactivate")
[]
(object [])
updateRecurrentPaymentEndDate :: MonadCielo m => Text -> Text -> m ()
updateRecurrentPaymentEndDate recurrentPaymentId endDate = void $ sendRaw putWith
("/1/RecurrentPayment/" <> convert recurrentPaymentId <> "/EndDate")
[]
endDate
updateRecurrentPaymentInstallments :: MonadCielo m => Text -> Int -> m ()
updateRecurrentPaymentInstallments recurrentPaymentId installments = void $ sendRaw putWith
("/1/RecurrentPayment/" <> convert recurrentPaymentId <> "/Installments")
[]
installments
updateRecurrentPaymentInterval :: MonadCielo m => Text -> Int -> m ()
updateRecurrentPaymentInterval recurrentPaymentId interval = void $ sendRaw putWith
("/1/RecurrentPayment/" <> convert recurrentPaymentId <> "/Interval")
[]
interval
updateRecurrentPaymentRecurrencyDay :: MonadCielo m => Text -> Int -> m ()
updateRecurrentPaymentRecurrencyDay recurrentPaymentId dayOfMonth = void $ sendRaw putWith
("/1/RecurrentPayment/" <> convert recurrentPaymentId <> "/Amount")
[]
dayOfMonth
updateRecurrentPaymentNextPaymentAmount :: MonadCielo m => Text -> Int -> m ()
updateRecurrentPaymentNextPaymentAmount recurrentPaymentId amount = void $ sendRaw putWith
("/1/RecurrentPayment/" <> convert recurrentPaymentId <> "/Amount")
[]
amount
updateRecurrentPaymentNextPaymentDate :: MonadCielo m => Text -> Text -> m ()
updateRecurrentPaymentNextPaymentDate recurrentPaymentId date = void $ sendRaw putWith
("/1/RecurrentPayment/" <> convert recurrentPaymentId <> "/NextPaymentDate")
[]
date
updateRecurrentPaymentPayment :: MonadCielo m => Text -> Payment -> m ()
updateRecurrentPaymentPayment recurrentPaymentId payment = void $ sendRaw putWith
("/1/RecurrentPayment/" <> convert recurrentPaymentId <> "/Payment")
[]
payment
uncancelRecurrentPayment :: MonadCielo m => Text -> m ()
uncancelRecurrentPayment recurrentPaymentId = void $ sendRaw putWith
("/1/RecurrentPayment/" <> convert recurrentPaymentId <> "/Reactivate")
[]
(object [])
updateRecurrentPaymentCustomer :: MonadCielo m => Text -> Customer -> m ()
updateRecurrentPaymentCustomer recurrentPaymentId = void . sendRaw putWith
("/1/RecurrentPayment/" <> convert recurrentPaymentId <> "/Customer")
[]