Verifiers¶
once.verifiers.stripe_params ¶
stripe_params(key: str, params: Mapping[str, Any], *, metadata_key: str = METADATA_KEY) -> dict[str, Any]
Tag create params with the once key and use it as the Idempotency-Key.
Returns keyword arguments for a StripeClient create call::
client.v1.payment_intents.create(**stripe_params(idempotency_key, {...}))
Existing metadata is kept. The Idempotency-Key makes Stripe replay the first response if the same request is sent again within 24 hours.
once.verifiers.stripe_verifier ¶
stripe_verifier(kind: Kind, *, client: Any = None, api_key: str | None = None, metadata_key: str = METADATA_KEY, list_params: Callable[[dict[str, Any]], Mapping[str, Any]] | None = None, scan: int = 100, result: Callable[[dict[str, Any]], Any] | None = None) -> Verifier
Build a verifier that finds the Stripe object tagged with the once key.
kind is "charge", "payment_intent", or "refund". client is a
stripe.StripeClient, or anything shaped like one (tests pass a fake). If
it is None, a StripeClient is made on first use from api_key (or
stripe.api_key), which needs the stripe package
(pip install agent-once[stripe]).
Charges and PaymentIntents are looked up with the search API first. Search
can lag new objects by a minute or so, so if it finds nothing, the newest
scan objects from the list API are checked too. Refunds have no search,
so only the list is used. list_params maps the tool args to list filters
such as {"customer": args["customer"]}, to narrow the scan.
If search isn't available to the account (Stripe doesn't offer it in some
regions, or a restricted key can't use it), the list is used instead and
search is skipped from then on. With scan=0 that error is raised.
The found object's status decides the outcome. Charges: succeeded is
returned, failed is NOT_HAPPENED. PaymentIntents: succeeded and
requires_capture are returned, canceled is NOT_HAPPENED. Refunds:
succeeded and pending are returned, failed and canceled are
NOT_HAPPENED. Any other status (processing, requires_action,
requires_payment_method, ...) raises StripeInconclusive, so the record
stays unknown until it settles.
Returns the object as a plain dict (or result(obj) if given), or
NOT_HAPPENED. NOT_HAPPENED needs a list that was read to the end: if more
than scan objects match the filters and none of the first scan is
the one, StripeInconclusive is raised and the record stays unknown.
With scan=0 a search miss alone returns NOT_HAPPENED, so only use it
with stripe_params, whose Idempotency-Key makes a rerun safe for 24 hours.
Other Stripe errors propagate, which also leaves the record unknown.
once.verifiers.http_verifier ¶
http_verifier(url: str, *, method: str = 'GET', headers: Mapping[str, str] | None = None, happened: Collection[int] = OK, not_happened: Collection[int] = (404,), timeout: float = 10.0, result: Callable[[Any], Any] | None = None) -> Verifier
Build a verifier that asks an HTTP endpoint whether the effect happened.
url is a template. {key} is the once key and any other {name} is
the tool argument of that name, each percent-encoded, for example
"https://api.example.com/orders/{order_id}/emails/{key}". Strings go
in as they are; other values as JSON, so None is null and True is
true. A tool argument named key with {key} in the template
raises ValueError, since the template can't tell the two apart.
A status in happened returns the response body: parsed JSON, the text
if it is not JSON, or None if it is empty. A status in not_happened
returns NOT_HAPPENED, so the call runs again. Any other status, or a
network error, raises, which leaves the record unknown.
result maps the body to what the tool itself returns, so a verified
result looks like a normal one. It may also return NOT_HAPPENED, for APIs
that answer 200 with something like {"found": false}.