Class: ZaiPayment::Resources::Webhook

Inherits:
Object
  • Object
show all
Defined in:
lib/zai_payment/resources/webhook.rb

Overview

Webhook resource for managing Zai webhooks

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(client: nil) ⇒ Webhook



14
15
16
# File 'lib/zai_payment/resources/webhook.rb', line 14

def initialize(client: nil)
  @client = client || Client.new
end

Instance Attribute Details

#clientObject (readonly)

Returns the value of attribute client.



12
13
14
# File 'lib/zai_payment/resources/webhook.rb', line 12

def client
  @client
end

Instance Method Details

#create(url: nil, object_type: nil, enabled: true, description: nil) ⇒ Response

Create a new webhook

Examples:

webhooks = ZaiPayment::Resources::Webhook.new
response = webhooks.create(
  url: "https://example.com/webhooks",
  object_type: "transactions",
  enabled: true
)

See Also:



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/zai_payment/resources/webhook.rb', line 72

def create(url: nil, object_type: nil, enabled: true, description: nil)
  validate_presence!(url, 'url')
  validate_presence!(object_type, 'object_type')
  validate_url!(url)

  body = {
    url: url,
    object_type: object_type,
    enabled: enabled
  }

  body[:description] = description if description

  client.post('/webhooks', body: body)
end

#create_secret_key(secret_key:) ⇒ Response

Create a secret key for webhook signature verification

Examples:

webhooks = ZaiPayment::Resources::Webhook.new
secret_key = SecureRandom.alphanumeric(32)
response = webhooks.create_secret_key(secret_key: secret_key)

See Also:



205
206
207
208
209
210
211
# File 'lib/zai_payment/resources/webhook.rb', line 205

def create_secret_key(secret_key:)
  validate_presence!(secret_key, 'secret_key')
  validate_secret_key!(secret_key)

  body = { secret_key: secret_key }
  client.post('/webhooks/secret_key', body: body)
end

#delete(webhook_id) ⇒ Response

Delete a webhook

Examples:

webhooks = ZaiPayment::Resources::Webhook.new
response = webhooks.delete("webhook_id")

See Also:



131
132
133
134
# File 'lib/zai_payment/resources/webhook.rb', line 131

def delete(webhook_id)
  validate_id!(webhook_id, 'webhook_id')
  client.delete("/webhooks/#{webhook_id}")
end

#generate_signature(payload, secret_key, timestamp = Time.now.to_i) ⇒ String

Generate a signature for webhook verification

This is a utility method that can be used for testing or generating signatures for webhook simulation.

Examples:

webhooks = ZaiPayment::Resources::Webhook.new
signature = webhooks.generate_signature(
  '{"event": "status_updated"}',
  'my_secret_key'
)

See Also:



281
282
283
284
285
286
# File 'lib/zai_payment/resources/webhook.rb', line 281

def generate_signature(payload, secret_key, timestamp = Time.now.to_i)
  signed_payload = "#{timestamp}.#{payload}"
  digest = OpenSSL::Digest.new('sha256')
  hash = OpenSSL::HMAC.digest(digest, secret_key, signed_payload)
  Base64.urlsafe_encode64(hash, padding: false)
end

#list(limit: 10, offset: 0) ⇒ Response

List all webhooks

Examples:

webhooks = ZaiPayment::Resources::Webhook.new
response = webhooks.list
response.data # => [{"id" => "...", "url" => "..."}, ...]

See Also:



30
31
32
33
34
35
36
37
# File 'lib/zai_payment/resources/webhook.rb', line 30

def list(limit: 10, offset: 0)
  params = {
    limit: limit,
    offset: offset
  }

  client.get('/webhooks', params: params)
end

#list_jobs(webhook_id, limit: 10, offset: 0, status: nil, object_id: nil) ⇒ Response

List jobs associated with a webhook

Retrieves an ordered and paginated list of jobs garnered from a webhook.

Examples:

List all jobs for a webhook

webhooks = ZaiPayment::Resources::Webhook.new
response = webhooks.list_jobs("webhook_uuid")
response.data # => [{"id" => "...", "status" => "success", ...}, ...]

Filter jobs by status

response = webhooks.list_jobs("webhook_uuid", status: "failed")

Paginate through jobs

response = webhooks.list_jobs("webhook_uuid", limit: 50, offset: 100)

See Also:



159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/zai_payment/resources/webhook.rb', line 159

def list_jobs(webhook_id, limit: 10, offset: 0, status: nil, object_id: nil)
  validate_id!(webhook_id, 'webhook_id')
  validate_job_status!(status) if status

  params = {
    limit: limit,
    offset: offset
  }
  params[:status] = status if status
  params[:object_id] = object_id if object_id

  client.get("/webhooks/#{webhook_id}/jobs", params: params)
end

#show(webhook_id) ⇒ Response

Get a specific webhook by ID

Examples:

webhooks = ZaiPayment::Resources::Webhook.new
response = webhooks.show("webhook_id")
response.data # => {"id" => "webhook_id", "url" => "...", ...}

See Also:



50
51
52
53
# File 'lib/zai_payment/resources/webhook.rb', line 50

def show(webhook_id)
  validate_id!(webhook_id, 'webhook_id')
  client.get("/webhooks/#{webhook_id}")
end

#show_job(webhook_id, job_id) ⇒ Response

Show a specific job associated with a webhook

Examples:

webhooks = ZaiPayment::Resources::Webhook.new
response = webhooks.show_job("webhook_uuid", "job_id")
response.data # => {"id" => "job_id", "status" => "success", ...}

See Also:



185
186
187
188
189
190
# File 'lib/zai_payment/resources/webhook.rb', line 185

def show_job(webhook_id, job_id)
  validate_id!(webhook_id, 'webhook_id')
  validate_id!(job_id, 'job_id')

  client.get("/webhooks/#{webhook_id}/jobs/#{job_id}")
end

#update(webhook_id, url: nil, object_type: nil, enabled: nil, description: nil) ⇒ Response

Update an existing webhook

Examples:

webhooks = ZaiPayment::Resources::Webhook.new
response = webhooks.update(
  "webhook_id",
  enabled: false
)

Raises:

See Also:



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/zai_payment/resources/webhook.rb', line 105

def update(webhook_id, url: nil, object_type: nil, enabled: nil, description: nil)
  validate_id!(webhook_id, 'webhook_id')

  body = {}
  body[:url] = url if url
  body[:object_type] = object_type if object_type
  body[:enabled] = enabled unless enabled.nil?
  body[:description] = description if description

  validate_url!(url) if url

  raise Errors::ValidationError, 'At least one attribute must be provided for update' if body.empty?

  client.patch("/webhooks/#{webhook_id}", body: body)
end

#verify_signature(payload:, signature_header:, secret_key:, tolerance: 300) ⇒ Boolean

Verify webhook signature

This method verifies that a webhook request came from Zai by validating the HMAC SHA256 signature in the Webhooks-signature header.

Examples:

# In your webhook endpoint (e.g., Rails controller)
def webhook
  payload = request.body.read
  signature_header = request.headers['Webhooks-signature']
  secret_key = ENV['ZAI_WEBHOOK_SECRET']

  if ZaiPayment.webhooks.verify_signature(
    payload: payload,
    signature_header: signature_header,
    secret_key: secret_key
  )
    # Process webhook
    render json: { status: 'success' }
  else
    render json: { error: 'Invalid signature' }, status: :unauthorized
  end
end

Raises:

See Also:



245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'lib/zai_payment/resources/webhook.rb', line 245

def verify_signature(payload:, signature_header:, secret_key:, tolerance: 300)
  validate_presence!(payload, 'payload')
  validate_presence!(signature_header, 'signature_header')
  validate_presence!(secret_key, 'secret_key')

  # Extract timestamp and signature from header
  timestamp, signatures = parse_signature_header(signature_header)

  # Verify timestamp is within tolerance (prevent replay attacks)
  verify_timestamp!(timestamp, tolerance)

  # Generate expected signature
  expected_signature = generate_signature(payload, secret_key, timestamp)

  # Compare signatures using constant-time comparison
  signatures.any? { |sig| secure_compare(expected_signature, sig) }
end