Skip to content

feat: add X-Request-ID header support for idempotency (#3)#4

Merged
dapi merged 4 commits intomasterfrom
feature/3-add-x-request-id-idempotency
Feb 4, 2026
Merged

feat: add X-Request-ID header support for idempotency (#3)#4
dapi merged 4 commits intomasterfrom
feature/3-add-x-request-id-idempotency

Conversation

@dapi
Copy link
Member

@dapi dapi commented Feb 4, 2026

Summary

  • Add request_id: keyword parameter to payment methods for idempotency support
  • The X-Request-ID header is sent with API requests when request_id is provided
  • Enables CloudPayments server-side result caching for 1 hour
  • Fully backward compatible — request_id: is optional

API

# Charge with idempotency
client.payments.tokens.charge(attributes, request_id: "charge:#{invoice_id}")

# Refund with idempotency
client.payments.refund(transaction_id, amount, request_id: "refund:#{transaction_id}")

# Subscription with idempotency
client.subscriptions.create(attributes, request_id: "subscription:#{account_id}")

Changes

File Change
lib/cloud_payments/client.rb Add request_id: to perform_request and headers
lib/cloud_payments/namespaces/base.rb Add request_id: to request method
lib/cloud_payments/namespaces/*.rb Add request_id: to charge/auth/refund/create methods
spec/cloud_payments/client_spec.rb Test X-Request-ID header behavior
README.md Documentation with usage examples
Gemfile Add base64 gem for Ruby 3.4+ compatibility

Design Decision

Used explicit request_id: parameter instead of Thread.current block approach:

  • Avoids Fiber-local storage issues in async environments (Falcon, async-http)
  • More explicit and predictable API
  • Ruby 3.0+ compatible

Test plan

  • All existing tests pass (486 examples, 0 failures)
  • New tests for X-Request-ID header presence/absence
  • Tests verify empty string and nil are not sent as header

Closes #3

🤖 Generated with Claude Code

dapi and others added 4 commits February 4, 2026 20:27
Add `with_request_id` block for thread-safe idempotency key management.
The X-Request-ID header is sent with API requests when set, enabling
CloudPayments server-side result caching for 1 hour.

- Add `CloudPayments.with_request_id` method with thread-local storage
- Add `CloudPayments.current_request_id` method
- Modify Client#headers to include X-Request-ID when set
- Add comprehensive tests for idempotency functionality
- Update README with usage examples
- Add base64 gem for Ruby 3.4+ compatibility

Refs #3

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…#3)

Replace thread-local storage with explicit request_id: keyword parameter
passed through the method chain. This approach:

- Avoids Thread.current/Fiber issues in async environments
- Makes the API more explicit and predictable
- Uses Ruby 3.0+ compatible explicit hash syntax

API: method(attributes, request_id: "key")

Refs #3

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Strip whitespace from request_id before sending
- Filter whitespace-only strings (e.g. "   ")
- Add integration test for Base#request with request_id
- Add integration test for Tokens#charge with request_id
- Add tests for whitespace handling in headers

Refs #3

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add GitHub Actions workflow for CI (Ruby 3.1, 3.2, 3.3, 3.4)
- Add mise.toml for Ruby version management (3.3)
- Delete outdated .travis.yml (was Ruby 2.3-2.7)
- Set required_ruby_version >= 3.1 in gemspec

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@dapi dapi merged commit fc32f17 into master Feb 4, 2026
4 checks passed
@dapi dapi deleted the feature/3-add-x-request-id-idempotency branch February 4, 2026 19:24
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.

Add X-Request-ID header support for idempotency

1 participant