Skip to documentation content

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.

  1. Prepare

    Request Stripe context

    Use one exact linked invoice or a complete inline CanonicalInvoice.

  2. Pay

    Execute Stripe once

    Use merchant-controlled Stripe credentials and payment idempotency.

  3. 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.

Normalize a PaymentIntent
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.

Track one operation
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

FailureAction
Authentication or permissionCorrect the provider-scoped Carden key; repeated retries cannot grant access.
ValidationCorrect factual invoice or report fields; never synthesize missing commercial data.
Timeout or connectionRetry safe preparation or the same immutable report under a bounded policy.
ConflictReview idempotency, source revision, event identity, or cumulative payment facts.
Stripe ambiguityReconcile 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.