Stripe SDK usage
Prepare Stripe fields and deliver observed outcomes with Node.js, Ruby, Python, PHP, Java, Go, .NET, or direct HTTP.
On this page
Keep the SDK around the Stripe call
The SDK does not become the payment processor
Carden prepares and records data while the merchant backend continues to execute Stripe.
Prepare
Request Stripe context
Use one exact linked invoice or a complete inline CanonicalInvoice.
Pay
Execute Stripe once
Use merchant-controlled Stripe credentials and payment idempotency.
Report
Deliver the observation
Persist an immutable event and retry Carden delivery independently.
Initialize the Carden client in a trusted server process with a Stripe-integration Carden key. Keep the Stripe secret and provider webhook secret in the payment code the merchant already controls.
Prepare a linked invoice for Stripe
A linked-invoice key needs invoices:read and enrichment:write. Supply one invoice selector, exact amount and currency, optional expected revision, and a persisted preparation idempotency key. Every language returns enrichment, preparation, and a diagnostic request ID in its native shape.
Prepare a linked invoice for Stripe
const invoice = await carden.invoices.retrieve(invoiceId);
const prepared = await carden.stripe.createPaymentIntentEnrichmentFromInvoice({
invoiceId: invoice.id,
amountMinor: 11300,
currency: "usd",
expectedRevision: invoice.revision,
idempotencyKey: "prepare_attempt_1042_1",
});
await attemptStore.attachPreparation(attemptId, prepared.preparation);Persist preparation.id with the attempt before Stripe execution, merge only enrichment into the PaymentIntent request, and use preparation.id as enrichmentRequestId on reports. The SDK never selects a customer or payment method and never executes Stripe.
Deliver a saved Stripe payment report
Persist one immutable event for every observed state. A report retry keeps its body and eventId. A later capture or refund keeps attemptId and uses a new eventId with cumulative amounts.
Deliver a saved Stripe payment report
const receipt = await carden.stripe.reportPayment(report, {
maxRetries: 0,
timeoutMs: 5000,
});
await reportOutbox.markDelivered(report.eventId, receipt);Use optional Node.js helpers carefully
The Node.js client exposes paymentObservationFromStripePaymentIntent to normalize a local PaymentIntent snapshot. It reads actual expanded charge totals when available and does not verify a Stripe webhook signature.
import { paymentObservationFromStripePaymentIntent } from "@carden/node";
// Expand latest_charge so captured and refunded totals come from Stripe.
const observation = paymentObservationFromStripePaymentIntent(intent);
// If you retrieved the refund total separately:
// paymentObservationFromStripePaymentIntent(intent, { refundedAmountMinor });carden.stripe.trackPayment(operation, options) executes the supplied merchant operation once, converts its result, and attempts a report. It returns or rethrows the original provider result. It is a convenience wrapper, not a durable outbox.
import { paymentObservationFromStripePaymentIntent } from "@carden/node";
// Persist attempt before using this convenience wrapper.
const result = await carden.stripe.trackPayment(executeStripePayment, {
report: {
eventId: attempt.eventId,
attemptId: attempt.attemptId,
currency: attempt.currency,
amountMinor: attempt.amountMinor,
capturedAmountMinor: attempt.capturedAmountMinor,
refundedAmountMinor: attempt.refundedAmountMinor,
invoiceReference: attempt.invoiceReference,
...(attempt.enrichmentRequestId ? { enrichmentRequestId: attempt.enrichmentRequestId } : {}),
},
selectResult: paymentObservationFromStripePaymentIntent,
reportOptions: { maxRetries: 0, timeoutMs: 1000 },
onReportError: (error, { report }) => {
reportDeliveryMonitor.record({
attemptId: attempt.attemptId,
eventId: report?.eventId ?? attempt.eventId,
errorType: error.name,
});
},
});Handle SDK errors
| Failure | Action |
|---|---|
| Authentication or permission | Correct the provider-scoped Carden key; repeated retries cannot grant access. |
| Validation | Correct factual invoice or report fields; never synthesize missing commercial data. |
| Timeout or connection | Retry safe preparation or the same immutable report under a bounded policy. |
| Conflict | Review idempotency, source revision, event identity, or cumulative payment facts. |
| Stripe ambiguity | Reconcile Stripe separately and keep the Carden report pending or unknown. |
- Test every supported package against the same synthetic contract fixtures.
- Verify no Carden, Stripe, or webhook secret appears in browser bundles, payloads, or logs.
- Exercise duplicate receipts and process restarts without another Stripe operation.
- Keep the package version and deployed v1 contract aligned through the release gate.