Lightweight Stripe API Library
(require stripe-integration) | |
package: stripe-integration |
An unofficial client of the Stripe API for use in Racket.
Tested against API version 2019-09-09.
Includes exponential backoff when Stripe’s servers request it, and idempotency key handling for sensitive calls.
1 Why not just stripe?
Because that’s not my trademark and I wanted a name that hit a sweet spot between:
being searchable on a package index that lacks the integration outright, and;
respecting a name that should be available to its rightful owner.
I found an example of other unofficial libraries taking a similar approach, and Stripe keeps links to them. For that reason I’ll use this name unless I am asked to change it.
2 Idempotency keys?
An idempotency key is Stripe’s answer for how to handle when you, say, lose network connectivity right before the API tells you that a credit card transaction was complete. Instead of tangental validation or trying to incur a new charge, you can instead provide an idempotency key to a new request and Stripe will provide the same response it has available for you on the old call.
3 Client API Reference
value
stripe-host : "api.stripe.com"
value
stripe-endpoint : (parameter/c string?) = stripe-host
value
stripe-secret-key : (parameter/c string?) = ""
value
stripe-bearer? : (parameter/c boolean?) = #f
value
:
(unconstrained-domain-> exact-positive-integer? dict? jsexpr? (or/c boolean? string?))
The HTTP status code, as an exact positive integer.
A dict of headers such that the keys are header names as all lower-case interned symbols. This is to eliminate ambiguity on casing rules and allow eq? tests.
A jsexpr representing the JSON response to a Stripe API request.
A generated idempotency key used to resume sensitive operations on Stripe using non-idempotent requests. For GET and DELETE requests, this is always #f. See the Stripe API reference for more information.
struct
(struct exn:fail:stripe exn:fail (idempotency-key wrapped-exn) #:extra-constructor-name make-exn:fail:stripe) idempotency-key : (or/c string? boolean?) wrapped-exn : exn?
This is thrown by the HTTP request procedures below when a connection to Stripe is interrupted. It will contain an idempotency key that you should persist if this exception came up when attempting a POST that did something sensitive like charge a customer. The key will help you repeat the request without repeating something that should only happen once.
wrapped-exn is the original exception caught before the exn:fail:stripe instance was raised in the original exception’s stead. An instance of exn:fail:stripe has the same continuation marks as wrapped-exn.
procedure
(stripe-get uri #:retry? retry? #:max-tries max-tries) →
exact-positive-integer? dict? jsexpr? (or/c boolean? string?) uri : string? retry? : #t max-tries : 5
procedure
(stripe-delete uri #:retry? retry? #:max-tries max-tries) →
exact-positive-integer? dict? jsexpr? (or/c boolean? string?) uri : string? retry? : #t max-tries : 5
procedure
(stripe-post uri data #:retry? retry? #:max-tries max-tries) →
exact-positive-integer? dict? jsexpr? (or/c boolean? string?) uri : string? data : (or/c dict? string?) retry? : #t max-tries : 5
If retry? is #t, each request will retry with an exponential backoff if Stripe API responds with "HTTP 429 - Too Many Requests". retry? does not cover network connectivity failure, because blocking might not be the best approach. The client will make max-tries attempts before throwing exn:fail, and will wait as many seconds as defined by this procedure:
(define (backoff-time n) (min (+ (expt 2 n) (/ (random 0 1000) 1000)) 32))
The data provided to post will be encoded for use with "Content-Type: application/x-www-form-urlencoded". If the value cannot be encoded, post will raise exn:fail:contract.
All POST requests will include a generated idempotency key to protect against unusual network conditions at bad times (such as when processing a payment). In the event of a exn:fail:network, the exact exception will be transformed into an instance of exn:fail:stripe with the same continuation marks and the idempotency key attached for you to persist.
None of the request procedures will throw an exception in response to 4xx or 5xx HTTP status codes. If the response reports an error, it is still a response and will simply be returned as such.
4 Simple example
This follows the authentication example in the Stripe API reference.
(require stripe-integration json) (stripe-secret-key "test_blahblahblah") (define-values (status headers json ik) (stripe-get "/v1/charges"))
From this you can follow along in the reference using the other request procedures.