Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
# Changelog

## 0.1.8 (unreleased)

- Fix subscription renewals being recorded as one-time payments. Stripe removed
`PaymentIntent.invoice` in API version `2025-03-31.basil`, so
`payment_intent.succeeded` now finds the invoice through the Invoice Payments
API. Apps on earlier releases may have renewal charges in the `payments`
table; they are the rows whose payment intent belongs to a subscription
invoice.
- An older `customer.subscription.updated` can no longer revive a canceled
subscription (thanks @milehighideas, #68).
- Webhook processing failures now return 500 so Stripe redelivers the event,
including failures while syncing a checkout's invoice or checking whether a
payment belongs to a subscription. Previously these were logged and
acknowledged with 200.
- Webhook logs no longer include raw errors, which could contain the payload,
signature header, or customer fields. Add the new `onError` option to
`registerRoutes` to report the underlying error yourself.
- Invoices without a customer are skipped instead of failing validation, and
expanded customer, subscription, and invoice objects in event payloads are
read correctly.

## 0.1.7

- Adds a /test entrypoint for testing, compatibile with convex-test's new
Expand Down
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,21 @@ registerRoutes(http, components.stripe, {
export default http;
```

If processing an event fails, the route responds with a 500 so Stripe retries
the delivery. The component only logs a fixed message plus the event ID and
type, because errors can contain the raw payload, the signature header, or
customer fields. To see the underlying error, pass `onError` and send it to
your own logging or monitoring:

```typescript
registerRoutes(http, components.stripe, {
onError: async (ctx, error, { stage, event }) => {
// stage is "signature" or "processing"; event is set once verified
reportToMonitoring(error, { stage, eventId: event?.id });
},
});
```

## Database Schema

The component creates these tables in its namespace:
Expand Down
Loading
Loading