(ns paddleguru.schema.stripe | |
(:require [paddleguru.util :as u] | |
[paddleguru.schema :as ps] | |
[schema.core :as s])) | |
(def ChargeID | |
(s/named s/Str "Charge identifier.")) | |
(def CustomerID | |
(s/named s/Str "The identifier of the customer to be retrieved.")) | |
(def BalanceTxID | |
(s/named s/Str "ID of a balance transaction.")) | |
(def RecipientID s/Str) | |
(def Expansion | |
"Supply a keyword like :balance_transaction or a sequence to expand | |
multiple fields. To expand nested fields, string the items together | |
in the keyword with a dot, like :balance_transaction.source." | |
(s/either s/Keyword [s/Keyword])) | |
(def CardToken | |
(s/named s/Str "Token returned by a call to Stripe.js.")) | |
(def BankToken | |
(s/named s/Str "Token representing a user's bank account.")) | |
(def ExpMonth | |
(-> (s/both s/Int (s/pred (u/between 1 13))) | |
(s/named "Two digit number representing the card's expiration month."))) | |
(def ExpYear | |
(-> (s/both s/Int (s/pred (some-fn | |
(u/between 1 13) | |
(u/between 2000 10000)))) | |
(s/named | |
"Two digit number representing the card's expiration year."))) | |
(def CardNumber | |
(s/named s/Str "Credit card # with no separators.")) | |
(def CVC | |
(s/named s/Str "Card security code. HIGHLY recommended.")) | |
(def FullName | |
(s/named s/Str "The cardholder's full name.")) | |
(def CardMap | |
{:number CardNumber | |
:exp_month ExpMonth | |
:exp_year ExpYear | |
(s/optional-key :cvc) CVC | |
(s/optional-key :name) FullName | |
(s/optional-key :address_line1) s/Str | |
(s/optional-key :address_city) s/Str | |
(s/optional-key :address_zip) s/Str | |
(s/optional-key :address_state) s/Str | |
(s/optional-key :address_country) s/Str}) | |
(def CardObject | |
{:id s/Str | |
:object (s/eq "card") | |
:last4 s/Str | |
:type s/Str | |
:exp_month ExpMonth | |
:exp_year ExpYear | |
:fingerprint s/Str | |
:country (s/maybe s/Str) | |
:customer (s/maybe s/Str) | |
:name FullName | |
:address_line1 (s/maybe s/Str) | |
:address_line2 (s/maybe s/Str) | |
:address_city (s/maybe s/Str) | |
:address_zip (s/maybe s/Str) | |
:address_state (s/maybe s/Str) | |
:address_country (s/maybe s/Str) | |
:cvc_check (s/enum "pass" "fail") | |
:address_line1_check (s/maybe s/Str) | |
:address_zip_check (s/maybe s/Str)}) | |
(def BankMap | |
{:account_number (s/named s/Str "Checking account number.") | |
:routing_number | |
(s/named s/Str "Bank routing number. ACH, not wire.")}) | |
(def Card | |
(s/either CardToken CardMap)) | |
(def Metadata | |
(-> {u/Named s/Str} | |
(s/both (s/pred #(< (count %) 10))) | |
(s/named | |
"Metadata feature supported by the Stripe API. Keyword keys are converted to strings on the way over. | |
Only 10 KV pairs are currently supported."))) | |
(def CustomerReq | |
{(s/optional-key :card) Card | |
(s/optional-key :description) s/Str | |
(s/optional-key :email) s/Str | |
(s/optional-key :metadata) Metadata}) | |
(def Currency | |
"Currently only USD is supported, because we're located in the | |
US. Generalize if Stripe opens this up." | |
(s/eq "usd")) | |
;; Balance Transaction API | |
(def FeeDetails | |
"Details about this particular Stripe fee in the Balance Transaction | |
fee breakdown list." | |
{:amount s/Int | |
:currency Currency | |
:type s/Str | |
:description (s/maybe s/Str) | |
:application (s/maybe s/Str)}) | |
(def TransactionType | |
(s/enum "charge" "refund" "adjustment" "application_fee" | |
"application_fee_refund" "transfer" "transfer_cancel" | |
"transfer_failure")) | |
(def BalanceTx | |
{:id BalanceTxID | |
:object (s/eq "balance_transaction") | |
:amount s/Int | |
:available_on ps/UnixTimestamp | |
:created ps/UnixTimestamp | |
:currency Currency | |
:fee s/Int | |
:fee_details [FeeDetails] | |
:net s/Int | |
:status (s/enum "pending" "available") | |
:type TransactionType | |
:description (s/maybe s/Str) | |
:source (-> (s/either s/Str {s/Keyword s/Any}) | |
(s/named "The source Stripe object. Either the ID or, | |
if expanded, the object.")) | |
(s/optional-key :recipient) (s/either (s/eq "self") RecipientID)}) | |
;; ## Charge API | |
(def ChargeAmount | |
(-> (s/both s/Int (s/pred #(> % 50))) | |
(s/named | |
"A positive integer in cents representing how much to | |
charge the card. The minimum amount is 50 cents."))) | |
(def ChargeReq | |
(-> {:amount ChargeAmount | |
(s/optional-key :expand) Expansion | |
(s/optional-key :currency) Currency | |
(s/optional-key :card) Card | |
(s/optional-key :customer) CustomerID | |
(s/optional-key :description) s/Str | |
(s/optional-key :metadata) Metadata | |
(s/optional-key :capture) boolean} | |
(s/both (s/pred (some-fn :card :customer))) | |
(s/named "Supported options for a Stripe charge request."))) | |
(def RefundReq | |
(-> {:id ChargeID | |
(s/optional-key :expand) Expansion | |
(s/optional-key :amount) ps/PositiveInt | |
(s/optional-key :refund_application_fee) s/Bool} | |
(s/named "Supported options for a Stripe refund request."))) | |
(def Refund | |
{:amount ChargeAmount | |
:object (s/eq "refund") | |
:currency Currency | |
:created ps/UnixTimestamp | |
:balance_transaction (s/either BalanceTxID BalanceTx)}) | |
(def Charge | |
{:id ChargeID | |
:object (s/eq "charge") | |
:created ps/UnixTimestamp | |
:livemode s/Bool | |
:paid s/Bool | |
:amount ChargeAmount | |
:currency Currency | |
:refunded s/Bool | |
:card CardObject | |
:captured s/Bool | |
:refunds [Refund] | |
:balance_transaction (s/either BalanceTxID BalanceTx) | |
:failure_message (s/maybe s/Str) | |
:failure_code (s/maybe s/Str) | |
:amount_refunded ps/NonNegativeInt | |
:customer (s/maybe CustomerID) | |
:invoice (s/maybe s/Str) | |
:description (s/maybe s/Str) | |
:dispute (s/maybe s/Str) | |
:metadata Metadata | |
:statement_description (s/maybe s/Str)}) | |
;; ## Recipient Info | |
(def RecipientName | |
"The recipient's full, legal name. For type individual, should be in | |
the format 'First Last', 'First Middle Last', or 'First M Last' (no | |
prefixes or suffixes). For corporation, the full incorporated | |
name." | |
s/Str) | |
(def RecipientType | |
(s/enum "individual" "corporation")) | |
(def TaxID | |
(-> (s/maybe s/Str) | |
(s/named "The recipient's tax ID, as a | |
string. For type individual, the full SSN; for type | |
corporation, the full EIN."))) | |
(def RecipientReq | |
"Parameters to be passed on recipient creation." | |
{:name RecipientName | |
:type RecipientType | |
(s/optional-key :tax_id) TaxID | |
(s/optional-key :email) (s/maybe s/Str) | |
(s/optional-key :description) s/Str | |
(s/optional-key :metadata) Metadata | |
(s/optional-key :bank_account) (s/maybe | |
(s/either BankToken | |
(assoc BankMap | |
:country (s/eq "US"))))}) | |
(def RecipientUpdate | |
"Parameters to be passed on recipient update." | |
(-> RecipientReq | |
(ps/toggle-optional :name) | |
(dissoc :type))) | |
(def DisabledStatus | |
(-> (s/maybe s/Bool) | |
(s/named "When a transfer sent to this bank account | |
fails, we’ll set the disabled property to true and will not | |
continue to send transfers until the bank details are updated."))) | |
(def BankAccount | |
{:id s/Str | |
:object (s/eq "bank_account") | |
:verified s/Bool | |
:currency Currency | |
:bank_name (s/named s/Str "Name of the bank associated with the | |
routing number, e.g. WELLS FARGO.") | |
:last4 s/Str | |
:country (s/named s/Str "Two-letter ISO code representing the | |
country the bank account is located in") | |
:disabled DisabledStatus | |
:fingerprint (-> (s/maybe s/Str) | |
(s/named "Uniquely identifies this particular bank | |
account. You can use this attribute to check | |
whether two bank accounts are the same.")) | |
:validated (-> (s/maybe s/Bool) | |
(s/named "Whether or not the bank account exists. If | |
false, there isn’t enough information to know (e.g. for smaller | |
credit unions), or the validation is not being run.")) }) | |
(def Recipient | |
"Stripe's representation of a recipient." | |
{:id RecipientID | |
:object (s/eq "recipient") | |
:created ps/UnixTimestamp | |
:livemode s/Bool | |
:type RecipientType | |
:active_account (s/maybe BankAccount) | |
:description (s/maybe s/Str) | |
:email (s/maybe s/Str) | |
:metadata Metadata | |
:name RecipientName | |
:verified (s/maybe s/Bool)}) | |
(def DeletedResponse | |
{:deleted (s/eq "true") | |
:id s/Str}) | |
;; ## Balance Schema | |
(def BalanceAmount | |
{:amount ps/NonNegativeInt | |
:currency Currency}) | |
(def Balance | |
{:object (s/eq "balance") | |
:livemode s/Bool | |
:available [BalanceAmount] | |
:pending [BalanceAmount]}) | |
;; ## Transfer Schema | |
(def TransferID s/Str) | |
(def TransferDescription | |
(s/named s/Str "An arbitrary string which you can attach to a | |
transfer object. It is displayed when in the web interface alongside | |
the transfer.")) | |
(def StatementDescription | |
(-> s/Str | |
(s/both s/Str (s/pred #(<= (count %) 15))) | |
(s/named "An arbitrary string which will be displayed on the | |
recipient's bank statement. This should not include your company name, | |
as that will already be part of the descriptor. The maximum length of | |
this string is 15 characters; longer strings will be truncated. For | |
example, if your website is EXAMPLE.COM and you pass in INVOICE 1234, | |
the user will see EXAMPLE.COM INVOICE 1234. Note: While most banks | |
display this information consistently, some may display it incorrectly | |
or not at all."))) | |
(def TransferReq | |
"Supported inputs for creating a Transfer object." | |
{:amount ps/PositiveInt | |
:currency Currency | |
:recipient (s/either (s/eq "self") RecipientID) | |
(s/optional-key :description) TransferDescription | |
(s/optional-key :statement_description) StatementDescription | |
(s/optional-key :metadata) Metadata}) | |
(def TransferUpdate | |
"Supported inputs for updating a Transfer object." | |
{(s/optional-key :description) TransferDescription | |
(s/optional-key :metadata) Metadata}) | |
(def Transfer | |
{:id TransferID | |
:object (s/eq "transfer") | |
:livemode s/Bool | |
:created ps/UnixTimestamp | |
:currency Currency | |
:date ps/UnixTimestamp | |
:status (s/enum "paid" "pending" "failed") | |
:account BankAccount | |
:balance_transaction BalanceTxID | |
:description (s/maybe TransferDescription) | |
:metadata Metadata | |
:recipient (-> (s/maybe RecipientID) | |
(s/named "Nil if the transfer is to the Stripe | |
account's linked bank account.")) | |
:statement_description (s/maybe StatementDescription)}) | |
;; ## Event API | |
(def EventID s/Str) | |
(def Event | |
"Event object sent in by Stripe's webhook system." | |
{:id EventID | |
:created ps/UnixTimestamp | |
:livemode s/Bool | |
:type s/Str | |
:data {:object {s/Keyword s/Any}} | |
:object s/Str | |
:pending_webhooks ps/NonNegativeInt | |
:request (s/named s/Str "Request identifier? Sort of unclear.")}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment