Skip to content
Merged
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
1 change: 1 addition & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Layout/LineLength:
- "lib/stripe/stripe_client.rb"
- "lib/stripe/resources/**/*.rb"
- "lib/stripe/services/**/*.rb"
- "lib/stripe/events/**/*.rb"
- "test/**/*.rb"

Lint/MissingSuper:
Expand Down
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
// Show the repo name in the top window bar.
"window.title": "${rootName}${separator}${activeEditorMedium}",

"editor.formatOnSave": true,
// formatting on save is very slow in ruby
"editor.formatOnSave": false,
"files.trimTrailingWhitespace": true,

// Rubocop settings
Expand Down
2 changes: 1 addition & 1 deletion examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ From the examples folder, run:

e.g.

`RUBYLIB=../lib ruby thinevent_webhook_handler.rb`
`RUBYLIB=../lib ruby event_notification_webhook_handler.rb`

## Adding a new example

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# frozen_string_literal: true
# typed: false

# thinevent_webhook_handler.rb - receive and process thin events like the
# event_notification_webhook_handler.rb - receive and process event notification like the
# v1.billing.meter.error_report_triggered event.
#
# In this example, we:
# - create a StripeClient called client
# - use client.parse_thin_event to parse the received thin event webhook body
# - use client.parse_event_notification to parse the received event notification webhook body
# - call client.v2.core.events.retrieve to retrieve the full event object
# - if it is a V1BillingMeterErrorReportTriggeredEvent event type, call
# event.fetchRelatedObject to retrieve the Billing Meter object associated
Expand All @@ -24,12 +24,10 @@
post "/webhook" do
webhook_body = request.body.read
sig_header = request.env["HTTP_STRIPE_SIGNATURE"]
thin_event = client.parse_thin_event(webhook_body, sig_header, webhook_secret)
event_notification = client.parse_event_notification(webhook_body, sig_header, webhook_secret)

# Fetch the event data to understand the failure
event = client.v2.core.events.retrieve(thin_event.id)
if event.instance_of? Stripe::V1BillingMeterErrorReportTriggeredEvent
meter = event.fetch_related_object
if event_notification.instance_of?(Stripe::Events::V1BillingMeterErrorReportTriggeredEventNotification)
meter = event_notification.fetch_related_object
meter_id = meter.id
puts "Success!", meter_id
end
Expand Down
2 changes: 1 addition & 1 deletion lib/stripe.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
require "stripe/singleton_api_resource"
require "stripe/webhook"
require "stripe/stripe_configuration"
require "stripe/thin_event"
require "stripe/event_notification"

# Named API resources
require "stripe/resources"
Expand Down
70 changes: 70 additions & 0 deletions lib/stripe/event_notification.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# frozen_string_literal: true

module Stripe
module V2
class EventReasonRequest
attr_reader :id, :idempotency_key

def initialize(event_reason_request_payload = {})
@id = event_reason_request_payload[:id]
@idempotency_key = event_reason_request_payload[:idempotency_key]
end
end

class EventReason
attr_reader :type, :request

def initialize(event_reason_payload = {})
@type = event_reason_payload[:type]
@request = EventReasonRequest.new(event_reason_payload[:request])
end
end

class RelatedObject
attr_reader :id, :type, :url

def initialize(related_object)
@id = related_object[:id]
@type = related_object[:type]
@url = related_object[:url]
end
end

class EventNotification
attr_reader :id, :type, :created, :context, :livemode, :reason

def initialize(event_payload, client)
@id = event_payload[:id]
@type = event_payload[:type]
@created = event_payload[:created]
@livemode = event_payload[:livemode]
@context = event_payload[:context]
@reason = EventReason.new(event_payload[:reason]) if event_payload[:reason]
# private unless a child declares an attr_reader
@related_object = RelatedObject.new(event_payload[:related_object]) if event_payload[:related_object]

# internal use
@client = client
end

# Retrieves the Event that generated this EventNotification.
def fetch_event
resp = @client.raw_request(:get, "/v2/core/events/#{id}", opts: { stripe_context: context },
usage: ["fetch_event"])
@client.deserialize(resp.http_body, api_mode: :v2)
end
end

class UnknownEventNotification < EventNotification
attr_reader :related_object

def fetch_related_object
return nil if @related_object.nil?

resp = @client.raw_request(:get, related_object.url, opts: { stripe_context: context },
usage: ["fetch_related_object"])
@client.deserialize(resp.http_body, api_mode: Util.get_api_mode(related_object.url))
end
end
end
end
26 changes: 20 additions & 6 deletions lib/stripe/event_types.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,27 @@

module Stripe
module EventTypes
def self.thin_event_names_to_classes
def self.v2_event_types_to_classes
{
# The beginning of the section generated from our OpenAPI spec
V1BillingMeterErrorReportTriggeredEvent.lookup_type => V1BillingMeterErrorReportTriggeredEvent,
V1BillingMeterNoMeterFoundEvent.lookup_type => V1BillingMeterNoMeterFoundEvent,
V2CoreEventDestinationPingEvent.lookup_type => V2CoreEventDestinationPingEvent,
# The end of the section generated from our OpenAPI spec
# v2 event types: The beginning of the section generated from our OpenAPI spec
Events::V1BillingMeterErrorReportTriggeredEvent.lookup_type =>
Events::V1BillingMeterErrorReportTriggeredEvent,
Events::V1BillingMeterNoMeterFoundEvent.lookup_type => Events::V1BillingMeterNoMeterFoundEvent,
Events::V2CoreEventDestinationPingEvent.lookup_type => Events::V2CoreEventDestinationPingEvent,
# v2 event types: The end of the section generated from our OpenAPI spec
}
end

def self.event_notification_types_to_classes
{
# event notification types: The beginning of the section generated from our OpenAPI spec
Events::V1BillingMeterErrorReportTriggeredEventNotification.lookup_type =>
Events::V1BillingMeterErrorReportTriggeredEventNotification,
Events::V1BillingMeterNoMeterFoundEventNotification.lookup_type =>
Events::V1BillingMeterNoMeterFoundEventNotification,
Events::V2CoreEventDestinationPingEventNotification.lookup_type =>
Events::V2CoreEventDestinationPingEventNotification,
# event notification types: The end of the section generated from our OpenAPI spec
}
end
end
Expand Down
130 changes: 115 additions & 15 deletions lib/stripe/events/v1_billing_meter_error_report_triggered_event.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,122 @@
# frozen_string_literal: true

module Stripe
# Occurs when a Meter has invalid async usage events.
class V1BillingMeterErrorReportTriggeredEvent < Stripe::V2::Event
def self.lookup_type
"v1.billing.meter.error_report_triggered"
module Events
# Occurs when a Meter has invalid async usage events.
class V1BillingMeterErrorReportTriggeredEvent < Stripe::V2::Event
def self.lookup_type
"v1.billing.meter.error_report_triggered"
end

class V1BillingMeterErrorReportTriggeredEventData < Stripe::StripeObject
class Reason < Stripe::StripeObject
class ErrorType < Stripe::StripeObject
class SampleError < Stripe::StripeObject
class Request < Stripe::StripeObject
# The request idempotency key.
attr_reader :identifier

def self.inner_class_types
@inner_class_types = {}
end

def self.field_remappings
@field_remappings = {}
end
end
# The error message.
attr_reader :error_message
# The request causes the error.
attr_reader :request

def self.inner_class_types
@inner_class_types = { request: Request }
end

def self.field_remappings
@field_remappings = {}
end
end
# Open Enum.
attr_reader :code
# The number of errors of this type.
attr_reader :error_count
# A list of sample errors of this type.
attr_reader :sample_errors

def self.inner_class_types
@inner_class_types = { sample_errors: SampleError }
end

def self.field_remappings
@field_remappings = {}
end
end
# The total error count within this window.
attr_reader :error_count
# The error details.
attr_reader :error_types

def self.inner_class_types
@inner_class_types = { error_types: ErrorType }
end

def self.field_remappings
@field_remappings = {}
end
end
# This contains information about why meter error happens.
attr_reader :reason
# Extra field included in the event's `data` when fetched from /v2/events.
attr_reader :developer_message_summary
# The start of the window that is encapsulated by this summary.
attr_reader :validation_start
# The end of the window that is encapsulated by this summary.
attr_reader :validation_end

def self.inner_class_types
@inner_class_types = { reason: Reason }
end

def self.field_remappings
@field_remappings = {}
end
end

def self.inner_class_types
@inner_class_types = { data: V1BillingMeterErrorReportTriggeredEventData }
end
attr_reader :data, :related_object

# Retrieves the related object from the API. Makes an API request on every call.
def fetch_related_object
_request(
method: :get,
path: related_object.url,
base_address: :api,
opts: { stripe_context: context }
)
end
end
# There is additional data present for this event, accessible with the `data` property.
# See the Stripe API docs for more information.

# Retrieves the related object from the API. Make an API request on every call.
def fetch_related_object
_request(
method: :get,
path: related_object.url,
base_address: :api,
opts: { stripe_account: context }
)

# Occurs when a Meter has invalid async usage events.
class V1BillingMeterErrorReportTriggeredEventNotification < Stripe::V2::EventNotification
def self.lookup_type
"v1.billing.meter.error_report_triggered"
end

attr_reader :related_object

# Retrieves the Meter related to this EventNotification from the Stripe API. Makes an API request on every call.
def fetch_related_object
resp = @client.raw_request(
:get,
related_object.url,
opts: { stripe_context: context },
usage: ["fetch_related_object"]
)
@client.deserialize(resp.http_body, api_mode: Util.get_api_mode(related_object.url))
end
end
end
end
Loading
Loading