DOWNLOAD
Keep Stripe credentials in your trusted gateway
curl --proto '=https' --tlsv1.2 -fsSLO https://mandateshield.com/sdk/v1.10.0/mandateshield.mjs
curl --proto '=https' --tlsv1.2 -fsSLO https://mandateshield.com/sdk/v1.10.0/mandateshield-gateway.mjs
curl --proto '=https' --tlsv1.2 -fsSLO https://mandateshield.com/sdk/v1.10.0/mandateshield-stripe-payment-intents.mjs
curl --proto '=https' --tlsv1.2 -fsSLO https://mandateshield.com/sdk/v1.10.0/SHA256SUMS
if command -v sha256sum >/dev/null 2>&1; then
grep -E ' (mandateshield|mandateshield-gateway|mandateshield-stripe-payment-intents)\.mjs$' SHA256SUMS | sha256sum -c -
else
grep -E ' (mandateshield|mandateshield-gateway|mandateshield-stripe-payment-intents)\.mjs$' SHA256SUMS | shasum -a 256 -c -
fiThe customer-side adapter keeps the charge-creation Stripe secret, PaymentMethod ID and client secret inside your gateway. If you enable hosted reconciliation, configure a separate restricted Stripe lookup key; MandateShield stores it encrypted and uses it only to retrieve and verify the bound PaymentIntent outcome.
INTEGRATE
Bind the authorized envelope to Stripe
import { createClient } from "./mandateshield.mjs"
import {
createMandateShieldGateway
} from "./mandateshield-gateway.mjs"
import {
createStripePaymentIntentsAdapter,
STRIPE_PAYMENT_INTENTS_AUDIENCE
} from "./mandateshield-stripe-payment-intents.mjs"
const processor = createClient({
apiKey: process.env.MANDATESHIELD_PROCESSOR_KEY
})
const stripe = createStripePaymentIntentsAdapter({
secretKey: process.env.STRIPE_SECRET_KEY,
stripeAccountId: process.env.STRIPE_CONNECTED_ACCOUNT,
merchantId: "merchant_storefront",
processorAudience: STRIPE_PAYMENT_INTENTS_AUDIENCE,
apiVersion: process.env.STRIPE_API_VERSION
})
const gateway = createMandateShieldGateway({
journal: globalLinearizableGatewayJournal,
mandateShield: processor,
provider: stripe
})
const finalPurchase = {
...finalPurchaseFacts,
payee_identity: {
profile: "MANDATESHIELD_PAYEE_IDENTITY_V1",
provider: "STRIPE",
merchant_id: finalPurchaseFacts.merchant_id,
binding: {
connected_account_id: process.env.STRIPE_CONNECTED_ACCOUNT,
merchant_account_id: process.env.STRIPE_CONNECTED_ACCOUNT
},
verification: {
method: "STRIPE_ACCOUNT_CONFIGURATION",
verifier: "customer-stripe-gateway",
evidence_ref:
`urn:stripe:connected-account:${process.env.STRIPE_CONNECTED_ACCOUNT}`
}
}
}
// Sign and strictly verify this exact finalPurchase before gateway execution.
const result = await gateway.execute({
receipt_id: reservation.signed_receipt.receipt_id,
compact: reservation.signed_receipt.compact,
expected_envelope: finalPurchase,
expected_audience: STRIPE_PAYMENT_INTENTS_AUDIENCE,
provider_input: {
payment_method_id: trustedServerSidePaymentMethodId
}
})Every process and region for this Gate must use the same globally shared, linearizable journal namespace. Its required GLOBAL_SHARED_LINEARIZABLE declaration is a customer assertion, not an independent database attestation; per-region or split-brain journals are unsafe.
The adapter declares SIGNED_EXECUTION_PERMIT_V1. The Gate includes the exact Stripe account, environment, merchant, amount, currency, request resource and SHA-256 form-body digest in the CONSUME binding. It then atomically redeems the resulting permit before Stripe can be called. Signature-only or replayed permits never unlock submission.
SUPPORTED V1 PROFILE
Deliberately narrow payment semantics
- Card PaymentIntents with automatic capture only.
- One explicitly configured Stripe connected account.
- Canonical payee identity binds both connected and merchant account into the signed final envelope; merchant_id alone is rejected.
- Exact authorized minor units, currency and merchant mapping.
- Immutable envelope and PaymentMethod snapshots before any network wait; journal identity also binds the signed-receipt digest.
- One create request with
confirm=true, using the provider idempotency key carried by the freshly redeemed signed permit. - The permit body digest covers the exact amount, currency, automatic-capture mode, card method, PaymentMethod ID and MandateShield metadata sent to Stripe.
- The pre-issued provider request ID is included as
metadata[mandateshield_provider_request_id]and must be echoed exactly during response checks and reconciliation, enabling provider-side lookup without changing the signed body after permit issuance. - Customer-supplied durable compare-and-set journal required.
- Stripe credentials can target only the official API; custom endpoints are restricted to an explicit localhost test mode.
FAILURE SEMANTICS
Unknown never means safe to retry
Succeeded commits. A failed or action-required card attempt is first canceled with a stable key and releases only after Stripe returns the exact bound PaymentIntent with status=canceled. Failed cancellation, processing, network ambiguity, malformed responses and binding mismatches remain pending or unknown.
This server-only profile never exposes client_secret or next_action; an intent requiring customer action follows the same verified-cancel policy. An unknown create without a provider reference can reuse its exact permit-bound provider key only inside a fixed 20-hour recovery window. After that window, the adapter makes no new create request and requires provider-side reconciliation.
After Stripe returns a PaymentIntent reference, report the exact provider_submission_id, permit_id, claim_id, payment reference and bounded caller outcome to POST /api/v2/provider-submissions. The caller observation is stored as CALLER_ASSERTED evidence, then MandateShield retrieves that exact PaymentIntent through the configured restricted key and re-checks account, environment, amount, currency, request ID and MandateShield metadata.
Only an exactly bound succeeded or canceled PaymentIntent can produce PROVIDER_API_VERIFIED evidence with independent_verification=true and autonomously COMMIT or RELEASE. Processing, API unavailability, not-found responses and binding conflicts remain pending or conflicting and stay fail-closed for reconciliation.
A correctly signed Stripe webhook may wake reconciliation and preserve an authenticated hint, but remains CALLER_ASSERTED. It is not the trust source for a terminal transition; the independent Stripe API lookup is.
This is a first-party integration module, not a Stripe partnership, certification, uptime promise or settlement guarantee.