mangopay-1.9: src/Web/MangoPay/Accounts.hs
{-# LANGUAGE DeriveDataTypeable, ScopedTypeVariables, OverloadedStrings, FlexibleContexts, FlexibleInstances, PatternGuards, ConstraintKinds #-}
-- | handle bank accounts
module Web.MangoPay.Accounts where
import Web.MangoPay.Monad
import Web.MangoPay.Types
import Web.MangoPay.Users
import Data.Text
import Data.Text.Encoding (encodeUtf8)
import Data.Typeable (Typeable)
import Data.Aeson
import Data.Aeson.Types
import Data.Maybe (fromMaybe)
import Data.Time.Clock.POSIX (POSIXTime)
import Control.Applicative
import qualified Data.ByteString as BS
import Data.CountryCodes (CountryCode)
-- | create an account
createAccount :: (MPUsableMonad m) => BankAccount -> AccessToken -> MangoPayT m BankAccount
createAccount ba = createGeneric path ba
where path = BS.concat ["/users/",encodeUtf8 uid,"/bankaccounts/",encodeUtf8 $ typeName $ baDetails ba]
uid = fromMaybe (error "no user provided for account") $ baUserId ba
-- | fetch an account from its Id
fetchAccount :: (MPUsableMonad m) => AnyUserId -> BankAccountId -> AccessToken -> MangoPayT m BankAccount
fetchAccount uid = fetchGeneric path
where path = Data.Text.concat ["/users/",uid,"/bankaccounts/"]
-- | list all accounts for a given user
listAccounts :: (MPUsableMonad m) => AnyUserId -> Maybe Pagination -> AccessToken -> MangoPayT m (PagedList BankAccount)
listAccounts uid = genericList ["/users/",uid,"/bankaccounts/"]
-- | account details, depending on the type
data BankAccountDetails=IBAN {
atIBAN :: Text
,atBIC :: Text
} | GB {
atAccountNumber :: Text
,atSortCode :: Text
} | US {
atAccountNumber :: Text
,atABA :: Text
} | CA {
atAccountNumber :: Text
,atBankName :: Text
,atInstitutionNumber :: Text
,atBranchCode :: Text
} | Other {
atAccountNumber :: Text
,atBIC :: Text
,atCountry :: CountryCode
} deriving (Show,Read,Eq,Ord,Typeable)
-- | from json as per MangoPay format
instance FromJSON BankAccountDetails where
parseJSON (Object v) =do
typ<-v .: "Type"
case typ of
"IBAN"->IBAN <$>
v .: "IBAN" <*>
v .: "BIC"
"GB"->GB <$>
v .: "AccountNumber" <*>
v .: "SortCode"
"US"->US <$>
v .: "AccountNumber" <*>
v .: "ABA"
"CA"->CA <$>
v .: "AccountNumber" <*>
v .: "BankName" <*>
v .: "InstitutionNumber" <*>
v .: "BranchCode"
"OTHER"->Other <$>
v .: "AccountNumber" <*>
v .: "BIC" <*>
v .: "Country"
_->fail $ "BankAccountDetails: unknown type:" ++ typ
parseJSON _=fail "BankAccountDetails"
-- | type name for details
typeName :: BankAccountDetails -> Text
typeName (IBAN {})="IBAN"
typeName (GB {})="GB"
typeName (US {})="US"
typeName (CA {})="CA"
typeName (Other {})="OTHER"
-- | the details attribute to be added to the account object
toJSONPairs :: BankAccountDetails -> [Pair]
toJSONPairs (IBAN iban bic)=["IBAN" .= iban,"BIC" .= bic]
toJSONPairs (GB nb sc)=["AccountNumber" .= nb,"SortCode" .= sc]
toJSONPairs (US nb aba)=["AccountNumber" .= nb,"ABA" .= aba]
toJSONPairs (CA nb bn inb bc)=["AccountNumber" .= nb,"BankName" .= bn,"InstitutionNumber" .= inb, "BranchCode" .= bc]
toJSONPairs (Other nb bic c)=["AccountNumber" .= nb,"BIC" .= bic,"Country" .= c]
-- | Id of a bank account
type BankAccountId = Text
-- | bank account details
data BankAccount = BankAccount {
baId :: Maybe BankAccountId
,baCreationDate :: Maybe POSIXTime
,baUserId :: Maybe AnyUserId
,baTag :: Maybe Text
,baDetails :: BankAccountDetails
,baOwnerName :: Text
,baOwnerAddress :: Maybe Text
} deriving (Show,Eq,Ord,Typeable)
-- | to json as per MangoPay format
instance ToJSON BankAccount where
toJSON ba=object $ ["OwnerName" .= baOwnerName ba,"Type" .= typeName (baDetails ba)
,"OwnerAddress" .= baOwnerAddress ba, "UserId" .= baUserId ba, "Tag" .= baTag ba]
++ toJSONPairs (baDetails ba)
-- | from json as per MangoPay format
instance FromJSON BankAccount where
parseJSON o@(Object v) =
BankAccount <$>
v .:? "Id" <*>
v .:? "CreationDate" <*>
v .:? "UserId" <*>
v .:? "Tag" <*>
parseJSON o <*>
v .: "OwnerName" <*>
v .:? "OwnerAddress"
parseJSON _=fail "BankAccount"
-- | type of payment
data PaymentType = CARD | BANK_WIRE | AUTOMATIC_DEBIT | DIRECT_DEBIT
deriving (Show,Read,Eq,Ord,Bounded,Enum,Typeable)
-- | to json as per MangoPay format
instance ToJSON PaymentType where
toJSON =toJSON . show
-- | from json as per MangoPay format
instance FromJSON PaymentType where
parseJSON (String s)
| ((a,_):_)<-reads $ unpack s=pure a
parseJSON _ =fail "PaymentType"