packages feed

stripe-wreq 1.0.1.15 → 1.0.1.16

raw patch · 3 files changed

+239/−237 lines, 3 filesdep ~basedep ~bytestringdep ~textPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base, bytestring, text

API changes (from Hackage documentation)

Files

changelog.md view
@@ -1,6 +1,12 @@ Changelog ========= +1.0.1.16 - 2023-06-26+--------------------------------------------------++Update stuff++ 1.0.1.15 - 2023-02-01 -------------------------------------------------- 
library/Stripe/Wreq.hs view
@@ -1,185 +1,187 @@-{-# OPTIONS_GHC -Wall -fno-warn-missing-signatures #-}--{- | Typical use of this module:--1. Run 'get', 'post', or 'delete' to get a 'WreqResponse'.-2. Use 'wreqResponse' to convert the Wreq response to a 'Response'.-3. Use 'responseValue' to obtain the response payload as an Aeson-   'Data.Aeson.Value' (or an 'Error' if the request was not successful). -}-+-- | Typical use of this module:+--+-- 1. Run 'get', 'post', or 'delete' to get a 'WreqResponse'.+-- 2. Use 'wreqResponse' to convert the Wreq response to a 'Response'.+-- 3. Use 'responseValue' to obtain the response payload as an Aeson+--   'Data.Aeson.Value' (or an 'Error' if the request was not successful). module Stripe.Wreq-  (-  -- * Request-  -- ** GET-    get, get', Get (..)-  -- ** POST-  , post, post', Post (..)-  -- ** DELETE-  , delete, delete', Delete (..)--  -- * Response-  , WreqResponse, Response (..)-  , wreqResponse, responseValue, responseValueError--  -- * Error-  , Error (..), UserMessage (..), LogMessage (..), userError, logError+  ( -- * Request -  -- * Status code-  , StatusCode (..)-  -- ** Predicates-  -- $predicates-  , isSuccess, isError, isClientError, isServerError-  -- ** Client error codes-  -- $constants-  , badRequest400, unauthorized401, requestFailed402-  , notFound404, conflict409, tooManyRequests429+    -- ** GET+    get,+    get',+    Get (..), -  -- * Re-exports from Wreq-  , FormParam (..), Session, Network.Wreq.Session.newAPISession+    -- ** POST+    post,+    post',+    Post (..), -  ) where+    -- ** DELETE+    delete,+    delete',+    Delete (..), --- aeson-import qualified Data.Aeson-import qualified Data.Aeson.Key-import qualified Data.Aeson.KeyMap+    -- * Response+    WreqResponse,+    Response (..),+    wreqResponse,+    responseValue,+    responseValueError, --- base-import qualified Control.Exception-import           Control.Monad     ((>=>))-import qualified Data.Bifunctor-import qualified Data.Semigroup-import           Data.String       (fromString)-import           Prelude           hiding (userError)+    -- * Error+    Error (..),+    UserMessage (..),+    LogMessage (..),+    userError,+    logError, --- bytestring-import qualified Data.ByteString-import qualified Data.ByteString.Lazy+    -- * Status code+    StatusCode (..), --- lens-import Control.Lens ((&), (.~), (?~), (^.), (<>~))+    -- ** Predicates+    -- $predicates+    isSuccess,+    isError,+    isClientError,+    isServerError, --- stripe-concepts-import Stripe.Concepts (ApiSecretKey (..), RequestApiVersion (..), ApiVersion (..))+    -- ** Client error codes+    -- $constants+    badRequest400,+    unauthorized401,+    requestFailed402,+    notFound404,+    conflict409,+    tooManyRequests429, --- text-import           Data.Text (Text)-import qualified Data.Text+    -- * Re-exports from Wreq+    FormParam (..),+    Session,+    Network.Wreq.Session.newAPISession,+  )+where --- wreq-import           Network.Wreq         (FormParam (..))-import qualified Network.Wreq-import           Network.Wreq.Session (Session)-import qualified Network.Wreq.Session+import Control.Exception qualified+import Control.Lens ((&), (.~), (<>~), (?~), (^.))+import Control.Monad ((>=>))+import Data.Aeson qualified+import Data.Aeson.Key qualified+import Data.Aeson.KeyMap qualified+import Data.Bifunctor qualified+import Data.ByteString qualified+import Data.ByteString.Lazy qualified+import Data.Semigroup qualified+import Data.String (fromString)+import Data.Text (Text)+import Data.Text qualified+import Network.Wreq (FormParam (..))+import Network.Wreq qualified+import Network.Wreq.Session (Session)+import Network.Wreq.Session qualified+import Stripe.Concepts (ApiSecretKey (..), ApiVersion (..), RequestApiVersion (..))+import Prelude hiding (userError)  ------------------------------------------------------------ -{- | An HTTP status code returned by Stripe.--"Stripe uses conventional HTTP response codes to indicate the success or failure-of an API request." - <https://stripe.com/docs/api#errors Stripe> -}--newtype StatusCode = StatusCode Int deriving Eq--{- $predicates--Some basic functions for interpreting status codes. -}+-- | An HTTP status code returned by Stripe.+--+-- "Stripe uses conventional HTTP response codes to indicate the success or failure+-- of an API request." - <https://stripe.com/docs/api#errors Stripe>+newtype StatusCode = StatusCode Int deriving (Eq) -{- | "Codes in the 2xx range indicate success." --<https://stripe.com/docs/api#errors Stripe> -}+-- $predicates+--+-- Some basic functions for interpreting status codes. +-- | "Codes in the 2xx range indicate success." -+-- <https://stripe.com/docs/api#errors Stripe> isSuccess :: StatusCode -> Bool isSuccess (StatusCode x) = x >= 200 && x < 300 -{- | @isError x@ is equivalent to @'isClientError' x || 'isServerError' x@. -}-+-- | @isError x@ is equivalent to @'isClientError' x || 'isServerError' x@. isError :: StatusCode -> Bool isError (StatusCode x) = x >= 400 && x < 600 -{- | "Codes in the 4xx range indicate an error that failed given the information-provided (e.g., a required parameter was omitted, a charge failed, etc.)." --<https://stripe.com/docs/api#errors Stripe> -}-+-- | "Codes in the 4xx range indicate an error that failed given the information+-- provided (e.g., a required parameter was omitted, a charge failed, etc.)." -+-- <https://stripe.com/docs/api#errors Stripe> isClientError :: StatusCode -> Bool isClientError (StatusCode x) = x >= 400 && x < 500 -{- | "Codes in the 5xx range indicate an error with Stripe's servers." --<https://stripe.com/docs/api#errors Stripe> -}-+-- | "Codes in the 5xx range indicate an error with Stripe's servers." -+-- <https://stripe.com/docs/api#errors Stripe> isServerError :: StatusCode -> Bool isServerError (StatusCode x) = x >= 500 && x < 600 -{- $constants--Constants for each of the error codes enumerated in the Stripe API-documentation, for your convenience. -}--{- | 400 - Bad Request--"The request was unacceptable, often due to missing a required parameter." --<https://stripe.com/docs/api#errors Stripe> -}+-- $constants+--+-- Constants for each of the error codes enumerated in the Stripe API+-- documentation, for your convenience. +-- | 400 - Bad Request+--+-- "The request was unacceptable, often due to missing a required parameter." -+-- <https://stripe.com/docs/api#errors Stripe> badRequest400 :: StatusCode badRequest400 = StatusCode 400 -{- | 401 - Unauthorized--"No valid API key provided." - <https://stripe.com/docs/api#errors Stripe> -}-+-- | 401 - Unauthorized+--+-- "No valid API key provided." - <https://stripe.com/docs/api#errors Stripe> unauthorized401 :: StatusCode unauthorized401 = StatusCode 401 -{- | 402 - Request Failed--"The parameters were valid but the request failed." --<https://stripe.com/docs/api#errors Stripe> -}-+-- | 402 - Request Failed+--+-- "The parameters were valid but the request failed." -+-- <https://stripe.com/docs/api#errors Stripe> requestFailed402 :: StatusCode requestFailed402 = StatusCode 402 -{- | 404 - Not Found--"The requested resource doesn't exist." --<https://stripe.com/docs/api#errors Stripe> -}-+-- | 404 - Not Found+--+-- "The requested resource doesn't exist." -+-- <https://stripe.com/docs/api#errors Stripe> notFound404 :: StatusCode notFound404 = StatusCode 404 -{- | 409 - Conflict--"The request conflicts with another request (perhaps due to using the same-idempotent key)." - <https://stripe.com/docs/api#errors Stripe> -}-+-- | 409 - Conflict+--+-- "The request conflicts with another request (perhaps due to using the same+-- idempotent key)." - <https://stripe.com/docs/api#errors Stripe> conflict409 :: StatusCode conflict409 = StatusCode 409 -{- | 429 - Too Many Requests--"Too many requests hit the API too quickly. We recommend an exponential backoff-of your requests." - <https://stripe.com/docs/api#errors Stripe> -}-+-- | 429 - Too Many Requests+--+-- "Too many requests hit the API too quickly. We recommend an exponential backoff+-- of your requests." - <https://stripe.com/docs/api#errors Stripe> tooManyRequests429 :: StatusCode tooManyRequests429 = StatusCode 429  ------------------------------------------------------------ -data Get =-  Get-    { getPath     :: [Text]          -- ^ URL path components-    , getParams   :: [(Text, Text)]  -- ^ Query params-    }+data Get = Get+  { -- | URL path components+    getPath :: [Text],+    -- | Query params+    getParams :: [(Text, Text)]+  } -data Post =-  Post-    { postPath     :: [Text]         -- ^ URL path components-    , postParams   :: [FormParam]    -- ^ Parameters to send in the request body-    }+data Post = Post+  { -- | URL path components+    postPath :: [Text],+    -- | Parameters to send in the request body+    postParams :: [FormParam]+  } -data Delete =-  Delete-    { deletePath   :: [Text]         -- ^ URL path components-    , deleteParams :: [(Text, Text)] -- ^ Query params-    }+data Delete = Delete+  { -- | URL path components+    deletePath :: [Text],+    -- | Query params+    deleteParams :: [(Text, Text)]+  }  get :: Session -> ApiSecretKey -> Get -> IO WreqResponse get session key x = get' session key DefaultApiVersion x@@ -188,9 +190,11 @@ get' session key v x = Network.Wreq.Session.getWith opts session url   where     url = makeUrl (getPath x)-    opts = wreqDefaults & Network.Wreq.auth ?~ auth key-                        & Network.Wreq.params .~ (getParams x)-                        & Network.Wreq.headers <>~ (requestApiVersionHeaders v)+    opts =+      wreqDefaults+        & Network.Wreq.auth ?~ auth key+        & Network.Wreq.params .~ (getParams x)+        & Network.Wreq.headers <>~ (requestApiVersionHeaders v)  post :: Session -> ApiSecretKey -> Post -> IO WreqResponse post session key x = post' session key DefaultApiVersion x@@ -200,8 +204,10 @@   where     url = makeUrl (postPath x)     params = postParams x-    opts = wreqDefaults & Network.Wreq.auth ?~ auth key-                        & Network.Wreq.headers <>~ (requestApiVersionHeaders v)+    opts =+      wreqDefaults+        & Network.Wreq.auth ?~ auth key+        & Network.Wreq.headers <>~ (requestApiVersionHeaders v)  delete :: Session -> ApiSecretKey -> Delete -> IO WreqResponse delete session key x = delete' session key DefaultApiVersion x@@ -210,16 +216,18 @@ delete' session key v x = Network.Wreq.Session.deleteWith opts session url   where     url = makeUrl (deletePath x)-    opts = wreqDefaults & Network.Wreq.auth ?~ auth key-                        & Network.Wreq.params .~ (deleteParams x)-                        & Network.Wreq.headers <>~ (requestApiVersionHeaders v)+    opts =+      wreqDefaults+        & Network.Wreq.auth ?~ auth key+        & Network.Wreq.params .~ (deleteParams x)+        & Network.Wreq.headers <>~ (requestApiVersionHeaders v)  urlBase :: Text urlBase = Data.Text.pack "https://api.stripe.com/v1"  makeUrl :: [Text] -> String makeUrl =-    Data.Text.unpack+  Data.Text.unpack     . Data.Text.intercalate (Data.Text.pack "/")     . (urlBase :) @@ -228,7 +236,6 @@  -- When using the default API version, no header is required. requestApiVersionHeaders DefaultApiVersion = []- -- Overriding with a specific API version requires one header field. requestApiVersionHeaders (OverrideApiVersion v) = [apiVersionHeader v] @@ -238,137 +245,125 @@     name = fromString "Stripe-Version"     value = fromString (Data.Text.unpack v) -{- | Set a "response checker" that overrides Wreq's default one which causes-exceptions to be thrown for non-2xx HTTP status codes -}-+-- | Set a "response checker" that overrides Wreq's default one which causes+-- exceptions to be thrown for non-2xx HTTP status codes noCheckResponse :: Network.Wreq.Options -> Network.Wreq.Options noCheckResponse = Network.Wreq.checkResponse ?~ (\_ _ -> return ()) -{- | Represent a Stripe API key as a Wreq 'Network.Wreq.Auth' value.--"Authentication to the API is performed via HTTP Basic Auth. Provide your API-key as the basic auth username value. You do not need to provide a password." --<https://stripe.com/docs/api#authentication Stripe> -}-+-- | Represent a Stripe API key as a Wreq 'Network.Wreq.Auth' value.+--+-- "Authentication to the API is performed via HTTP Basic Auth. Provide your API+-- key as the basic auth username value. You do not need to provide a password." -+-- <https://stripe.com/docs/api#authentication Stripe> auth :: ApiSecretKey -> Network.Wreq.Auth auth (ApiSecretKey key) = Network.Wreq.basicAuth key Data.ByteString.empty  ------------------------------------------------------------ -{- | An error message suitable for being shown to a user. -}-+-- | An error message suitable for being shown to a user. newtype UserMessage = UserMessage Text deriving (Eq, Show) -{- | An error message that should go into an error log, /not/ shown to a user.--}-+-- | An error message that should go into an error log, /not/ shown to a user. newtype LogMessage = LogMessage Text deriving (Eq, Show) -data Error =-  Error-    { userMessages :: [UserMessage]-    , logMessages  :: [LogMessage]-    }-    deriving (Eq, Show)+data Error = Error+  { userMessages :: [UserMessage],+    logMessages :: [LogMessage]+  }+  deriving (Eq, Show) -instance Data.Semigroup.Semigroup Error-  where-    Error x y <> Error x' y' =-        Error-            ((Data.Semigroup.<>) x x')-            ((Data.Semigroup.<>) y y')+instance Data.Semigroup.Semigroup Error where+  Error x y <> Error x' y' =+    Error+      ((Data.Semigroup.<>) x x')+      ((Data.Semigroup.<>) y y') -instance Monoid Error-  where-    mappend = (Data.Semigroup.<>)-    mempty = Error mempty mempty+instance Monoid Error where+  mappend = (Data.Semigroup.<>)+  mempty = Error mempty mempty  instance Control.Exception.Exception Error -userError-    :: Text -- ^ An error message intended to be shown to a user.-    -> Error--userError x = Error { userMessages = [UserMessage x], logMessages = [] }--logError-    :: Text -- ^ An error message intended to go into a log file,-            --   /not/ to be shown to a user.-    -> Error+userError ::+  -- | An error message intended to be shown to a user.+  Text ->+  Error+userError x = Error {userMessages = [UserMessage x], logMessages = []} -logError x = Error { userMessages = [], logMessages = [LogMessage x] }+logError ::+  -- | An error message intended to go into a log file,+  --   /not/ to be shown to a user.+  Text ->+  Error+logError x = Error {userMessages = [], logMessages = [LogMessage x]}  ------------------------------------------------------------  type WreqResponse = Network.Wreq.Response Data.ByteString.Lazy.ByteString -data Response =-  Response-    { responseBody :: Either Text Data.Aeson.Value-        -- ^ Every Stripe response should have a JSON body; but if not, this-        --   will be a 'Left' value with an error message from the JSON parser.-    , responseCode :: StatusCode-        -- ^ The status code of the HTTP response.-    }--{- | Convert a 'WreqResponse' into a 'Response' by parsing the JSON response-body (the Stripe API always returns JSON) and getting the HTTP status code. -}+data Response = Response+  { -- | Every Stripe response should have a JSON body; but if not, this+    --   will be a 'Left' value with an error message from the JSON parser.+    responseBody :: Either Text Data.Aeson.Value,+    -- | The status code of the HTTP response.+    responseCode :: StatusCode+  } +-- | Convert a 'WreqResponse' into a 'Response' by parsing the JSON response+-- body (the Stripe API always returns JSON) and getting the HTTP status code. wreqResponse :: WreqResponse -> Response wreqResponse r =   Response     { responseBody =         r ^. Network.Wreq.responseBody-           & Data.Aeson.eitherDecode-           & Data.Bifunctor.first Data.Text.pack-    , responseCode =-        r ^. Network.Wreq.responseStatus-           . Network.Wreq.statusCode-           & StatusCode+          & Data.Aeson.eitherDecode+          & Data.Bifunctor.first Data.Text.pack,+      responseCode =+        r+          ^. Network.Wreq.responseStatus+            . Network.Wreq.statusCode+          & StatusCode     } -{- | Interpret a response, returning 'Right' with the parsed JSON payload if-everything is okay, or 'Left' with an error if the response contains any-indication that something went wrong. -}-+-- | Interpret a response, returning 'Right' with the parsed JSON payload if+-- everything is okay, or 'Left' with an error if the response contains any+-- indication that something went wrong. responseValue :: Response -> Either Error Data.Aeson.Value responseValue r =-    case (responseBody r) of-        Left e    -> Left (logError e)-        Right val ->-            case isSuccess (responseCode r) of-                True  -> Right val-                False -> Left (responseValueError val)--{- | If the response object looks like this:--> {->   "error": {->       "type": "card_error",->       "message": "..."->     }->   }-> }--then we use the value of the @message@ field as a 'UserMessage'. Otherwise it is-a 'LogMessage'.--"@message@: A human-readable message providing more details about the error. For-card errors, these messages can be shown to your users. [...] Card errors are-the most common type of error you should expect to handle. They result when the-user enters a card that can't be charged for some reason." --<https://stripe.com/docs/api#errors Stripe> -}+  case (responseBody r) of+    Left e -> Left (logError e)+    Right val ->+      case isSuccess (responseCode r) of+        True -> Right val+        False -> Left (responseValueError val) +-- | If the response object looks like this:+--+-- > {+-- >   "error": {+-- >       "type": "card_error",+-- >       "message": "..."+-- >     }+-- >   }+-- > }+--+-- then we use the value of the @message@ field as a 'UserMessage'. Otherwise it is+-- a 'LogMessage'.+--+-- "@message@: A human-readable message providing more details about the error. For+-- card errors, these messages can be shown to your users. [...] Card errors are+-- the most common type of error you should expect to handle. They result when the+-- user enters a card that can't be charged for some reason." -+-- <https://stripe.com/docs/api#errors Stripe> responseValueError :: Data.Aeson.Value -> Error responseValueError val-    | isCardError  =  foldMap userError (msg val)-    | otherwise    =  foldMap logError  (msg val)+  | isCardError = foldMap userError (msg val)+  | otherwise = foldMap logError (msg val)   where-     isCardError = typ val == Just (Data.Text.pack "card_error")      msg = aesonAttr "error" >=> aesonAttr "message" >=> aesonText-    typ = aesonAttr "error" >=> aesonAttr "type"    >=> aesonText+    typ = aesonAttr "error" >=> aesonAttr "type" >=> aesonText  ------------------------------------------------------------ 
stripe-wreq.cabal view
@@ -1,7 +1,7 @@ cabal-version: 3.0  name: stripe-wreq-version: 1.0.1.15+version: 1.0.1.16 synopsis: Use the Stripe API via Wreq category: Web @@ -25,16 +25,17 @@  library     hs-source-dirs: library-    default-language: Haskell2010+    default-language: GHC2021+    ghc-options: -Wall -fno-warn-missing-signatures      exposed-modules:         Stripe.Wreq      build-depends:       , aeson ^>= 2.0.3 || ^>= 2.1-      , base ^>= 4.14 || ^>= 4.15 || ^>= 4.16 || ^>= 4.17-      , bytestring ^>= 0.10.12 || ^>= 0.11+      , base ^>= 4.16 || ^>= 4.17 || ^>= 4.18+      , bytestring ^>= 0.11       , lens ^>= 5.0.1 || ^>= 5.1 || ^>= 5.2       , stripe-concepts ^>= 1.0.3-      , text ^>= 1.2.4 || ^>= 2.0+      , text ^>= 1.2.5 || ^>= 2.0       , wreq ^>= 0.5.3