Skip to content

feat(billing-platform): add ChargeService.refund_charge endpoint (REVENG-157)#304

Closed
armcknight wants to merge 3 commits into
andrewmcknight/reveng-157-protos-record-charge-refundsfrom
andrewmcknight/reveng-157-protos-refund-charge
Closed

feat(billing-platform): add ChargeService.refund_charge endpoint (REVENG-157)#304
armcknight wants to merge 3 commits into
andrewmcknight/reveng-157-protos-record-charge-refundsfrom
andrewmcknight/reveng-157-protos-refund-charge

Conversation

@armcknight

@armcknight armcknight commented Jun 11, 2026

Copy link
Copy Markdown
Member

Summary

Adds ChargeService.refund_charge, the proto contract for admin-initiated refunds. The endpoint takes a Stripe charge id + amount, calls Stripe to create the refund, records a PlatformRefund row, and enforces an over-refund guard so cumulative refunds against a single charge can't exceed the charge total.

  • services/charge/v1/endpoint_refund_charge.proto (new) — RefundChargeRequest (stripe_charge_id, amount, optional reason) and RefundChargeResponse (refund, charge).

Reuses the PlatformRefund and PlatformCharge messages from charge.proto (extended by #303).

Proto stack

Proto PR Paired getsentry PR Contents
#303 (base) getsentry#20611 StripeRefund + PlatformRefund shared types, record_charge_refunds, handle_charge_refunded
#304 (this PR) getsentry#20612 endpoint_refund_charge.proto
#305 getsentry#20613 endpoint_list_refunds.proto

Stacked on #303 (for PlatformRefund). Sibling to #305 — independent of each other.

Test plan

  • Rust + Python bindings regenerated by CI
  • Consumed by getsentry#20612 once this lands and the sentry-protos pin is bumped

🤖 Generated with Claude Code

Andrew McKnight and others added 2 commits June 10, 2026 16:40
…le_charge_refunded endpoints

Adds the proto contracts the getsentry ``charge.refunded`` webhook path
will need (REVENG-157):

- ``common/v1/stripe_charge.proto``: new ``StripeRefund`` message +
  ``repeated refunds`` field on ``StripeCharge`` so webhook handlers
  receive per-refund metadata (id, amount, reason) and can record refunds
  idempotently — the aggregate ``amount_refunded`` on the charge alone
  isn't enough.
- ``services/charge/v1/charge.proto``: new ``PlatformRefund`` canonical
  projection, paralleling ``PlatformCharge``. The shared response type
  for every charge-service refund endpoint.
- ``services/charge/v1/endpoint_record_charge_refunds.proto``:
  ``ChargeService.record_charge_refunds`` — records per-refund rows from
  a Stripe webhook payload idempotently (keyed on refund stripe_id) and
  syncs the aggregate ``amount_refunded`` / ``refunded`` state.
- ``services/invoicer/v1/endpoint_handle_charge_refunded.proto``:
  ``InvoicerService.handle_charge_refunded`` — presentation handler that
  the webhook layer calls; delegates to ``record_charge_refunds`` and
  returns ``handled=False`` when the charge isn't platform so the caller
  falls through to legacy.

The other two refund endpoints (``refund_charge``, ``list_refunds_by_invoice``)
are split into separate PRs paired with their getsentry consumers.

Rust bindings + Cargo.lock + python bindings regen are handled by CI.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the proto contract for admin-initiated refunds against a platform
charge (REVENG-157). The endpoint takes a Stripe charge id + amount,
calls Stripe to create the refund, records a ``PlatformRefund`` row,
and enforces an over-refund guard so cumulative refunds against a
single charge can't exceed the charge total.

Builds on the ``PlatformRefund`` message added in the previous PR in
this proto stack.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@linear-code

linear-code Bot commented Jun 11, 2026

Copy link
Copy Markdown

REVENG-157

@github-actions

Copy link
Copy Markdown

The latest Buf updates on your PR. Results from workflow ci / buf-checks (pull_request).

BuildFormatLintBreakingUpdated (UTC)
✅ passed✅ passed✅ passed✅ passedJun 11, 2026, 4:31 AM

@armcknight armcknight force-pushed the andrewmcknight/reveng-157-protos-record-charge-refunds branch from fc673f0 to 83023b0 Compare June 11, 2026 05:29
@armcknight

Copy link
Copy Markdown
Member Author

Closing — we've decided not to support admin-initiated refunds for now. The webhook ingestion path (#303 + getsentry#20611) is the only refund flow we need; refunds originate in Stripe (e.g. via the Stripe dashboard) and are mirrored locally via charge.refunded webhooks. Leaving the branch in place in case we revisit admin-initiated refunds later.

@armcknight armcknight closed this Jun 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant