module Web.MangoPay.Accounts where
import Web.MangoPay.Monad
import Web.MangoPay.Types
import Web.MangoPay.Users
import Data.Text as T
import Data.Text.Encoding (encodeUtf8)
import Data.Typeable (Typeable)
import Data.Aeson
import Data.Aeson.Types
import Data.Maybe (fromMaybe)
import Control.Applicative
import qualified Data.ByteString as BS
import qualified Data.CountryCodes as C
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
fetchAccount :: (MPUsableMonad m) => AnyUserId -> BankAccountId -> AccessToken -> MangoPayT m BankAccount
fetchAccount uid = fetchGeneric path
where path = T.concat ["/users/",uid,"/bankaccounts/"]
listAccounts :: (MPUsableMonad m) => AnyUserId -> GenericSort -> Maybe Pagination -> AccessToken -> MangoPayT m (PagedList BankAccount)
listAccounts uid gs = genericListExtra (sortAttributes gs) ["/users/",uid,"/bankaccounts/"]
data BankAccountDetails=IBAN {
atIBAN :: Text
,atBIC :: Maybe Text
} | GB {
atAccountNumber :: Text
,atSortCode :: Text
} | US {
atAccountNumber :: Text
,atABA :: Text
} | CA {
atAccountNumber :: Text
,atBankName :: Text
,atInstitutionNumber :: Text
,atBranchCode :: Text
} | Other {
atAccountNumber :: Text
,atBIC :: Maybe Text
,atCountry :: C.CountryCode
} deriving (Show,Read,Eq,Ord,Typeable)
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"
typeName :: BankAccountDetails -> Text
typeName (IBAN {})="IBAN"
typeName (GB {})="GB"
typeName (US {})="US"
typeName (CA {})="CA"
typeName (Other {})="OTHER"
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]
accountCountry :: BankAccount -> Maybe C.CountryCode
accountCountry ba = case baDetails ba of
GB{} -> Just C.GB
US{} -> Just C.US
CA{} -> Just C.CA
Other _ _ c -> Just c
IBAN ib _ -> C.fromMText $ T.take 2 ib
type BankAccountId = Text
data BankAccount = BankAccount {
baId :: Maybe BankAccountId
,baCreationDate :: Maybe MpTime
,baUserId :: Maybe AnyUserId
,baTag :: Maybe Text
,baDetails :: BankAccountDetails
,baOwnerName :: Text
,baOwnerAddress :: Maybe Text
} deriving (Show,Eq,Ord,Typeable)
instance ToJSON BankAccount where
toJSON ba=objectSN $ ["OwnerName" .= baOwnerName ba,"Type" .= typeName (baDetails ba)
,"OwnerAddress" .= baOwnerAddress ba, "UserId" .= baUserId ba, "Tag" .= baTag ba]
++ toJSONPairs (baDetails ba)
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"
data PaymentType = CARD | BANK_WIRE | AUTOMATIC_DEBIT | DIRECT_DEBIT
deriving (Show,Read,Eq,Ord,Bounded,Enum,Typeable)
instance ToJSON PaymentType where
toJSON =toJSON . show
instance FromJSON PaymentType where
parseJSON (String s)
| ((a,_):_)<-reads $ unpack s=pure a
parseJSON _ =fail "PaymentType"