module Web.Stripe.Charge
( Charge(..)
, ChargeId(..)
, chargeToken
, chargeTokenById
, chargeCustomer
, chargeCustomerById
, chargeRCard
, getCharge
, getCharges
, partialRefund
, partialRefundById
, fullRefund
, fullRefundById
, Amount(..)
, Count(..)
, Currency(..)
, Description(..)
, Offset(..)
, UTCTime(..)
, StripeConfig(..)
, StripeT(StripeT)
, runStripeT
) where
import Control.Applicative ((<$>), (<*>))
import Control.Monad (liftM, mzero)
import Control.Monad.Error (MonadIO)
import Data.Aeson (FromJSON (..), Value (..), (.:), (.:?))
import qualified Data.ByteString as B
import qualified Data.Text as T
import Network.HTTP.Types (StdMethod (..))
import Web.Stripe.Card (Card, RequestCard, rCardKV)
import Web.Stripe.Client (StripeConfig (..), StripeRequest (..),
StripeT (..), baseSReq, query, queryData,
runStripeT)
import Web.Stripe.Customer (Customer (..), CustomerId (..))
import Web.Stripe.Token (Token (..), TokenId (..))
import Web.Stripe.Utils (Amount (..), Count (..), Currency (..),
Description (..), Offset (..),
UTCTime (..), fromSeconds, optionalArgs,
showByteString, textToByteString)
data Charge = Charge
{ chargeId :: ChargeId
, chargeCreated :: UTCTime
, chargeDescription :: Maybe Description
, chargeCurrency :: Currency
, chargeAmount :: Amount
, chargeLive :: Bool
, chargePaid :: Bool
, chargeRefunded :: Bool
, chargeCard :: Card
} deriving Show
newtype ChargeId = ChargeId { unChargeId :: T.Text } deriving (Show, Eq)
chargeToken :: MonadIO m => Token -> Amount -> Currency
-> Maybe Description -> Maybe Amount -> StripeT m Charge
chargeToken = chargeTokenById . tokId
chargeTokenById :: MonadIO m => TokenId -> Amount -> Currency
-> Maybe Description -> Maybe Amount -> StripeT m Charge
chargeTokenById (TokenId tid) = charge [("card", textToByteString tid)]
chargeCustomer :: MonadIO m => Customer -> Amount -> Currency
-> Maybe Description -> Maybe Amount -> StripeT m Charge
chargeCustomer = chargeCustomerById . custId
chargeCustomerById :: MonadIO m => CustomerId -> Amount -> Currency
-> Maybe Description -> Maybe Amount -> StripeT m Charge
chargeCustomerById (CustomerId cid) = charge [("customer", textToByteString cid)]
chargeRCard :: MonadIO m => RequestCard -> Amount -> Currency
-> Maybe Description -> Maybe Amount -> StripeT m Charge
chargeRCard rc = charge (rCardKV rc)
charge :: MonadIO m => [(B.ByteString, B.ByteString)] -> Amount -> Currency
-> Maybe Description -> Maybe Amount -> StripeT m Charge
charge adata a c mcd maf =
snd `liftM` query (chargeRq []) { sMethod = POST, sData = fdata }
where
fdata = optionalArgs odata ++ adata ++ bdata
odata = [ ("description", textToByteString . unDescription <$> mcd)
, ("application_fee", showByteString . unAmount <$> maf)
]
bdata = [ ("amount", showByteString . unAmount $ a)
, ("currency", textToByteString $ unCurrency c)
]
getCharge :: MonadIO m => ChargeId -> StripeT m Charge
getCharge (ChargeId cid) = snd `liftM` query (chargeRq [cid])
getCharges :: MonadIO m => Maybe CustomerId -> Maybe Count -> Maybe Offset
-> StripeT m [Charge]
getCharges mcid mc mo = liftM snd $
queryData ((chargeRq []) { sQString = optionalArgs oqs })
where
oqs = [ ("count", show . unCount <$> mc)
, ("offset", show . unOffset <$> mo)
, ("customer", T.unpack . unCustomerId <$> mcid)
]
partialRefund :: MonadIO m => Charge -> Amount -> StripeT m Charge
partialRefund = partialRefundById . chargeId
partialRefundById :: MonadIO m => ChargeId -> Amount -> StripeT m Charge
partialRefundById cid = refundChargeById cid . Just
fullRefund :: MonadIO m => Charge -> StripeT m Charge
fullRefund = fullRefundById . chargeId
fullRefundById :: MonadIO m => ChargeId -> StripeT m Charge
fullRefundById cid = refundChargeById cid Nothing
refundChargeById :: MonadIO m => ChargeId -> Maybe Amount -> StripeT m Charge
refundChargeById (ChargeId cid) ma =
snd `liftM` query (chargeRq [cid, "refund"]) { sMethod = POST, sData = fd }
where fd = optionalArgs [("amount", showByteString . unAmount <$> ma)]
chargeRq :: [T.Text] -> StripeRequest
chargeRq pcs = baseSReq { sDestination = "charges":pcs }
instance FromJSON Charge where
parseJSON (Object v) = Charge
<$> (ChargeId <$> v .: "id")
<*> (fromSeconds <$> v .: "created")
<*> (fmap Description <$> v .:? "description")
<*> (Currency <$> v .: "currency")
<*> (Amount <$> v .: "amount")
<*> v .: "livemode"
<*> v .: "paid"
<*> v .: "refunded"
<*> v .: "card"
parseJSON _ = mzero