{-# OPTIONS_GHC -cpp -pgmPcpphs -optP--cpp #-}
{-# LANGUAGE CPP #-}
module Stripe.Client
  ( -- * Basics
    ApiKey, StripeClient, makeStripeClient, ClientError(..)
    -- * Helper types
  , TimeStamp(..), StripeList(..)
    -- * Customers
  , createCustomer, retrieveCustomer, updateCustomer, listCustomers
  , CustomerId(..), Customer(..), CustomerCreate(..), CustomerUpdate(..)
    -- * Product catalog
  , ProductId(..), PriceId(..), Product(..), Price(..), PriceRecurring(..)
  , ProductCreate(..), PriceCreate(..), PriceCreateRecurring(..)
  , createProduct, retrieveProduct
  , createPrice, retrievePrice, listPrices
    -- * Subscriptions
  , SubscriptionId(..), SubscriptionItemId(..), Subscription(..), SubscriptionItem(..), SubscriptionCreate(..), SubscriptionCreateItem(..)
  , createSubscription, retrieveSubscription, listSubscriptions
    -- * Customer Portal
  , CustomerPortalId(..), CustomerPortal(..), CustomerPortalCreate(..)
  , createCustomerPortal
    -- * Checkout
  , CheckoutSessionId(..), CheckoutSession(..), CheckoutSessionCreate(..), CheckoutSessionCreateLineItem(..)
  , createCheckoutSession, retrieveCheckoutSession
    -- * Events
  , retrieveEvent, listEvents
  , EventId(..), Event(..), EventData(..)
  )
where

import Stripe.Api
import Stripe.Resources
import Stripe.Client.Internal.Helpers

import Data.Proxy
import Servant.API
import Servant.Client
import Network.HTTP.Client (Manager)
import qualified Data.Text as T
import qualified Data.Text.Encoding as T

-- | Your Stripe API key. Can be obtained from the Stripe dashboard. Format: @sk_<mode>_<redacted>@
type ApiKey = T.Text

-- | Holds a 'Manager' and your API key.
data StripeClient
  = StripeClient
  { StripeClient -> BasicAuthData
scBasicAuthData :: BasicAuthData
  , StripeClient -> Manager
scManager :: Manager
  , StripeClient -> Int
scMaxRetries :: Int
  }

-- | Construct a 'StripeClient'. Note that the passed 'Manager' must support https (e.g. via @http-client-tls@)
makeStripeClient ::
  ApiKey
  -> Manager
  -> Int
  -- ^ Number of automatic retries the library should attempt. See also <https://stripe.com/docs/error-handling#safely-retrying-requests-with-idempotency Stripe Error Handling>
  -> StripeClient
makeStripeClient :: ApiKey -> Manager -> Int -> StripeClient
makeStripeClient ApiKey
k = BasicAuthData -> Manager -> Int -> StripeClient
StripeClient (ByteString -> ByteString -> BasicAuthData
BasicAuthData (ApiKey -> ByteString
T.encodeUtf8 ApiKey
k) ByteString
"")

api :: Proxy StripeApi
api :: Proxy StripeApi
api = Proxy StripeApi
forall k (t :: k). Proxy t
Proxy

stripeBaseUrl :: BaseUrl
stripeBaseUrl :: BaseUrl
stripeBaseUrl = Scheme -> String -> Int -> String -> BaseUrl
BaseUrl Scheme
Https String
"api.stripe.com" Int
443 String
""

#define EP(N, ARG, R) \
    N##' :: BasicAuthData -> ARG -> ClientM R;\
    N :: StripeClient -> ARG -> IO (Either ClientError R);\
    N sc a = runRequest (scMaxRetries sc) 0 $ runClientM (N##' (scBasicAuthData sc) a) (mkClientEnv (scManager sc) stripeBaseUrl)

#define EP2(N, ARG, ARG2, R) \
    N##' :: BasicAuthData -> ARG -> ARG2 -> ClientM R;\
    N :: StripeClient -> ARG -> ARG2 -> IO (Either ClientError R);\
    N sc a b = runRequest (scMaxRetries sc) 0 $ runClientM (N##' (scBasicAuthData sc) a b) (mkClientEnv (scManager sc) stripeBaseUrl)

#define EP3(N, ARG, ARG2, ARG3, R) \
    N##' :: BasicAuthData -> ARG -> ARG2 -> ARG3 -> ClientM R;\
    N :: StripeClient -> ARG -> ARG2 -> ARG3 -> IO (Either ClientError R);\
    N sc a b c = runRequest (scMaxRetries sc) 0 $ runClientM (N##' (scBasicAuthData sc) a b c) (mkClientEnv (scManager sc) stripeBaseUrl)

EP(createCustomer, CustomerCreate, Customer)
EP(retrieveCustomer, CustomerId, Customer)
EP2(updateCustomer, CustomerId, CustomerUpdate, Customer)
EP(listCustomers, Maybe CustomerId, (StripeList Customer))

EP(createProduct, ProductCreate, Product)
EP(retrieveProduct, ProductId, Product)

EP(createPrice, PriceCreate, Price)
EP(retrievePrice, PriceId, Price)
EP(listPrices, Maybe T.Text, (StripeList Price))

EP(createSubscription, SubscriptionCreate, Subscription)
EP(retrieveSubscription, SubscriptionId, Subscription)
EP(listSubscriptions, Maybe CustomerId, (StripeList Subscription))

EP(createCheckoutSession, CheckoutSessionCreate, CheckoutSession)
EP(retrieveCheckoutSession, CheckoutSessionId, CheckoutSession)

EP(createCustomerPortal, CustomerPortalCreate, CustomerPortal)

EP(retrieveEvent, EventId, Event)
EP(listEvents, Maybe EventId, (StripeList Event))

(BasicAuthData -> CustomerCreate -> ClientM Customer
createCustomer' :<|> BasicAuthData -> CustomerId -> ClientM Customer
retrieveCustomer' :<|> BasicAuthData -> CustomerId -> CustomerUpdate -> ClientM Customer
updateCustomer' :<|> BasicAuthData -> Maybe CustomerId -> ClientM (StripeList Customer)
listCustomers')
  :<|> (BasicAuthData -> ProductCreate -> ClientM Product
createProduct' :<|> BasicAuthData -> ProductId -> ClientM Product
retrieveProduct')
  :<|> (BasicAuthData -> PriceCreate -> ClientM Price
createPrice' :<|> BasicAuthData -> PriceId -> ClientM Price
retrievePrice' :<|> BasicAuthData -> Maybe ApiKey -> ClientM (StripeList Price)
listPrices')
  :<|> (BasicAuthData -> SubscriptionCreate -> ClientM Subscription
createSubscription' :<|> BasicAuthData -> SubscriptionId -> ClientM Subscription
retrieveSubscription' :<|> BasicAuthData
-> Maybe CustomerId -> ClientM (StripeList Subscription)
listSubscriptions')
  :<|> (BasicAuthData -> CheckoutSessionCreate -> ClientM CheckoutSession
createCheckoutSession' :<|> BasicAuthData -> CheckoutSessionId -> ClientM CheckoutSession
retrieveCheckoutSession')
  :<|> (BasicAuthData -> CustomerPortalCreate -> ClientM CustomerPortal
createCustomerPortal')
  :<|> (BasicAuthData -> EventId -> ClientM Event
retrieveEvent' :<|> BasicAuthData -> Maybe EventId -> ClientM (StripeList Event)
listEvents')
  = Proxy StripeApi -> Client ClientM StripeApi
forall api.
HasClient ClientM api =>
Proxy api -> Client ClientM api
client Proxy StripeApi
api