webhook

package
v1.0.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 21, 2025 License: MIT Imports: 10 Imported by: 0

README

Webhooks API

Secure webhook signature validation and typed event parsing for all Paystack webhook events.

Overview

Paystack sends webhooks to notify your application about events that happen in your account. This package provides:

  • Signature Validation - Verify webhook authenticity using HMAC-SHA512
  • Event Parsing - Strongly typed event data structures
  • Helper Methods - Easy conversion to specific event types

Quick Start

Basic Webhook Handler
import (
    "net/http"
    "github.com/huysamen/paystack-go/api/webhook"
)

func webhookHandler(w http.ResponseWriter, r *http.Request) {
    validator := webhook.NewValidator("sk_live_your_secret_key")
    
    event, err := validator.ValidateRequest(r)
    if err != nil {
        http.Error(w, "Invalid signature", http.StatusBadRequest)
        return
    }
    
    // Process the event
    if err := handleEvent(event); err != nil {
        http.Error(w, "Processing failed", http.StatusInternalServerError)
        return
    }
    
    w.WriteHeader(http.StatusOK)
}
Event Processing
func handleEvent(event *webhook.Event) error {
    switch event.Event {
    case webhook.EventChargeSuccess:
        return handleChargeSuccess(event)
    case webhook.EventTransferSuccess:
        return handleTransferSuccess(event)
    case webhook.EventSubscriptionCreate:
        return handleSubscriptionCreate(event)
    default:
        log.Printf("Unhandled event: %s", event.Event)
        return nil
    }
}

func handleChargeSuccess(event *webhook.Event) error {
    data, err := event.AsChargeSuccess()
    if err != nil {
        return fmt.Errorf("failed to parse charge.success: %w", err)
    }
    
    // Verify the transaction for security
    result, err := client.Transactions.Verify(ctx, data.Reference.String())
    if err != nil {
        return fmt.Errorf("verification failed: %w", err)
    }
    
    if err := result.Err(); err != nil {
        return fmt.Errorf("transaction verification failed: %w", err)
    }
    
    // Process successful payment
    return processPayment(result.Data)
}

Supported Events

Payment Events
Event Description Helper Method
charge.success Successful payment AsChargeSuccess()
charge.dispute.create Chargeback initiated AsChargeDisputeCreate()
charge.dispute.remind Dispute reminder AsChargeDisputeRemind()
charge.dispute.resolve Dispute resolved AsChargeDisputeResolve()
Customer Events
Event Description Helper Method
customeridentification.failed Customer ID verification failed AsCustomerIdentificationFailed()
customeridentification.success Customer ID verification succeeded AsCustomerIdentificationSuccess()
Account Events
Event Description Helper Method
dedicatedaccount.assign.failed Virtual account assignment failed AsDedicatedAccountAssignFailed()
dedicatedaccount.assign.success Virtual account assigned AsDedicatedAccountAssignSuccess()
Invoice Events
Event Description Helper Method
invoice.create Invoice created AsInvoiceCreate()
invoice.update Invoice updated AsInvoiceUpdate()
invoice.payment_failed Invoice payment failed AsInvoicePaymentFailed()
Payment Request Events
Event Description Helper Method
paymentrequest.pending Payment request created AsPaymentRequestPending()
paymentrequest.success Payment request paid AsPaymentRequestSuccess()
Refund Events
Event Description Helper Method
refund.failed Refund failed AsRefundFailed()
refund.pending Refund pending AsRefundPending()
refund.processed Refund processed AsRefundProcessed()
refund.processing Refund processing AsRefundProcessing()
Subscription Events
Event Description Helper Method
subscription.create Subscription created AsSubscriptionCreate()
subscription.disable Subscription disabled AsSubscriptionDisable()
subscription.not_renew Subscription won't renew AsSubscriptionNotRenew()
subscription.expiring_cards Cards expiring soon AsSubscriptionExpiringCards()
Transfer Events
Event Description Helper Method
transfer.failed Transfer failed AsTransferFailed()
transfer.reversed Transfer reversed AsTransferReversed()
transfer.success Transfer successful AsTransferSuccess()

Detailed Examples

Processing Payment Success
func handleChargeSuccess(event *webhook.Event) error {
    data, err := event.AsChargeSuccess()
    if err != nil {
        return err
    }
    
    // Extract payment details
    reference := data.Reference.String()
    amount := data.Amount.Int64()
    currency := data.Currency.String()
    customerEmail := data.Customer.Email.String()
    
    log.Printf("Payment successful: %s paid %d %s (ref: %s)",
        customerEmail, amount, currency, reference)
    
    // Update your database
    return updateOrderStatus(reference, "paid", amount)
}
Handling Transfer Events
func handleTransferSuccess(event *webhook.Event) error {
    data, err := event.AsTransferSuccess()
    if err != nil {
        return err
    }
    
    transferCode := data.TransferCode.String()
    amount := data.Amount.Int64()
    recipientName := data.Recipient.Name.String()
    
    log.Printf("Transfer successful: %d kobo to %s (code: %s)",
        amount, recipientName, transferCode)
    
    // Update payout status
    return updatePayoutStatus(transferCode, "completed")
}
Managing Subscription Events
func handleSubscriptionCreate(event *webhook.Event) error {
    data, err := event.AsSubscriptionCreate()
    if err != nil {
        return err
    }
    
    subscriptionCode := data.SubscriptionCode.String()
    customerEmail := data.Customer.Email.String()
    planName := data.Plan.Name.String()
    
    log.Printf("New subscription: %s subscribed to %s (code: %s)",
        customerEmail, planName, subscriptionCode)
    
    // Activate user features
    return activateSubscription(customerEmail, planName, subscriptionCode)
}

func handleSubscriptionDisable(event *webhook.Event) error {
    data, err := event.AsSubscriptionDisable()
    if err != nil {
        return err
    }
    
    subscriptionCode := data.SubscriptionCode.String()
    customerEmail := data.Customer.Email.String()
    
    log.Printf("Subscription disabled: %s (code: %s)",
        customerEmail, subscriptionCode)
    
    // Deactivate user features
    return deactivateSubscription(subscriptionCode)
}
Handling Disputes
func handleChargeDisputeCreate(event *webhook.Event) error {
    data, err := event.AsChargeDisputeCreate()
    if err != nil {
        return err
    }
    
    disputeID := data.ID.Uint64()
    transactionRef := data.Transaction.Reference.String()
    reason := data.Reason.String()
    amount := data.Transaction.Amount.Int64()
    
    log.Printf("Dispute created: ID %d for transaction %s (reason: %s, amount: %d)",
        disputeID, transactionRef, reason, amount)
    
    // Notify relevant team
    return notifyDisputeTeam(disputeID, transactionRef, reason)
}
Subscription Card Expiry
func handleSubscriptionExpiringCards(event *webhook.Event) error {
    data, err := event.AsSubscriptionExpiringCards()
    if err != nil {
        return err
    }
    
    // This event contains an array of expiring cards
    if !data.Entries.Valid {
        return fmt.Errorf("invalid expiring cards data")
    }
    
    entries, ok := data.Entries.Metadata["entries"].([]interface{})
    if !ok {
        return fmt.Errorf("unexpected expiring cards format")
    }
    
    for _, entry := range entries {
        cardData, ok := entry.(map[string]interface{})
        if !ok {
            continue
        }
        
        customerEmail, _ := cardData["customer_email"].(string)
        cardLast4, _ := cardData["last4"].(string)
        expMonth, _ := cardData["exp_month"].(string)
        expYear, _ := cardData["exp_year"].(string)
        
        log.Printf("Card expiring: %s's card ending in %s expires %s/%s",
            customerEmail, cardLast4, expMonth, expYear)
        
        // Notify customer
        if err := notifyCardExpiry(customerEmail, cardLast4, expMonth, expYear); err != nil {
            log.Printf("Failed to notify customer %s: %v", customerEmail, err)
        }
    }
    
    return nil
}

Security Best Practices

1. Always Validate Signatures
func webhookHandler(w http.ResponseWriter, r *http.Request) {
    // NEVER process webhooks without signature validation
    validator := webhook.NewValidator("sk_live_your_secret_key")
    
    event, err := validator.ValidateRequest(r)
    if err != nil {
        log.Printf("Invalid webhook signature: %v", err)
        http.Error(w, "Unauthorized", http.StatusUnauthorized)
        return
    }
    
    // Now safe to process
    handleEvent(event)
}
2. Verify Critical Events via API

For important events like successful payments, always verify via API:

func handleChargeSuccess(event *webhook.Event) error {
    data, err := event.AsChargeSuccess()
    if err != nil {
        return err
    }
    
    // Verify via API for additional security
    result, err := client.Transactions.Verify(ctx, data.Reference.String())
    if err != nil {
        return fmt.Errorf("verification failed: %w", err)
    }
    
    if err := result.Err(); err != nil {
        return fmt.Errorf("transaction not successful: %w", err)
    }
    
    // Verify amounts match
    if result.Data.Amount.Int64() != data.Amount.Int64() {
        return fmt.Errorf("amount mismatch: webhook=%d, api=%d",
            data.Amount.Int64(), result.Data.Amount.Int64())
    }
    
    // Now safe to process
    return processPayment(result.Data)
}
3. Idempotency

Handle duplicate webhooks gracefully:

func processPayment(transaction types.Transaction) error {
    reference := transaction.Reference.String()
    
    // Check if already processed
    if isPaymentProcessed(reference) {
        log.Printf("Payment %s already processed, skipping", reference)
        return nil
    }
    
    // Process payment
    err := updateOrderStatus(reference, "paid", transaction.Amount.Int64())
    if err != nil {
        return err
    }
    
    // Mark as processed
    return markPaymentProcessed(reference)
}
4. Error Handling and Retries

Paystack will retry failed webhooks, so handle errors appropriately:

func handleEvent(event *webhook.Event) error {
    switch event.Event {
    case webhook.EventChargeSuccess:
        if err := handleChargeSuccess(event); err != nil {
            // Log error but return nil to prevent retries for business logic errors
            if isBusinesLogicError(err) {
                log.Printf("Business logic error for %s: %v", event.Event, err)
                return nil
            }
            // Return error for temporary failures (DB down, etc.)
            return err
        }
    }
    return nil
}

func isBusinesLogicError(err error) bool {
    // Determine if error is due to business logic vs infrastructure
    return strings.Contains(err.Error(), "order not found") ||
           strings.Contains(err.Error(), "already processed")
}

Testing

Testing with Real Fixtures

The SDK includes real webhook JSON fixtures:

func TestWebhookParsing(t *testing.T) {
    // Load fixture
    data, err := os.ReadFile("../../resources/examples/webhook/charge.success.json")
    require.NoError(t, err)
    
    // Parse event
    var event webhook.Event
    err = json.Unmarshal(data, &event)
    require.NoError(t, err)
    
    // Test specific event type
    chargeData, err := event.AsChargeSuccess()
    require.NoError(t, err)
    
    // Verify fields
    assert.Equal(t, "charge.success", event.Event)
    assert.True(t, chargeData.Amount.Int64() > 0)
    assert.NotEmpty(t, chargeData.Reference.String())
}
Mock Webhook Testing
func TestWebhookHandler(t *testing.T) {
    // Create test event
    eventData := map[string]interface{}{
        "event": "charge.success",
        "data": map[string]interface{}{
            "reference": "test_ref_123",
            "amount": 100000,
            "currency": "NGN",
            "status": "success",
        },
    }
    
    body, _ := json.Marshal(eventData)
    
    // Create signature
    validator := webhook.NewValidator("test_secret")
    signature := validator.GenerateSignature(body) // You'll need to implement this for testing
    
    // Create request
    req := httptest.NewRequest("POST", "/webhook", bytes.NewReader(body))
    req.Header.Set("X-Paystack-Signature", signature)
    
    // Test handler
    recorder := httptest.NewRecorder()
    webhookHandler(recorder, req)
    
    assert.Equal(t, http.StatusOK, recorder.Code)
}

See api/webhook/webhook_test.go for comprehensive examples using real JSON fixtures from resources/examples/webhook/.

Documentation

Index

Constants

View Source
const (
	EventChargeSuccess = "charge.success"

	EventChargeDisputeCreate           = "charge.dispute.create"
	EventChargeDisputeRemind           = "charge.dispute.remind"
	EventChargeDisputeResolve          = "charge.dispute.resolve"
	EventCustomerIdentificationFailed  = "customeridentification.failed"
	EventCustomerIdentificationSuccess = "customeridentification.success"
	EventDedicatedAccountAssignFailed  = "dedicatedaccount.assign.failed"
	EventDedicatedAccountAssignSuccess = "dedicatedaccount.assign.success"
	EventInvoiceCreate                 = "invoice.create"
	EventInvoicePaymentFailed          = "invoice.payment_failed"
	EventInvoiceUpdate                 = "invoice.update"
	EventPaymentRequestPending         = "paymentrequest.pending"
	EventPaymentRequestSuccess         = "paymentrequest.success"
	EventRefundFailed                  = "refund.failed"
	EventRefundPending                 = "refund.pending"
	EventRefundProcessed               = "refund.processed"
	EventRefundProcessing              = "refund.processing"
	EventSubscriptionCreate            = "subscription.create"
	EventSubscriptionDisable           = "subscription.disable"
	EventSubscriptionExpiringCards     = "subscription.expiring_cards"
	EventSubscriptionNotRenew          = "subscription.not_renew"
	EventTransferFailed                = "transfer.failed"
	EventTransferReversed              = "transfer.reversed"
	EventTransferSuccess               = "transfer.success"
)

Variables

This section is empty.

Functions

func ParseEventData

func ParseEventData[T any](event *Event) (*T, error)

Types

type ChargeDisputeEvent

type ChargeDisputeEvent struct {
	ID                   data.Int              `json:"id"`
	RefundAmount         data.Int              `json:"refund_amount"`
	Currency             data.String           `json:"currency"`
	Status               data.String           `json:"status"`
	Resolution           data.NullString       `json:"resolution"`
	Domain               data.String           `json:"domain"`
	Transaction          *types.Transaction    `json:"transaction"`
	TransactionReference data.NullString       `json:"transaction_reference"`
	Category             data.String           `json:"category"`
	Customer             *types.Customer       `json:"customer"`
	BIN                  data.String           `json:"bin"`
	Last4                data.String           `json:"last4"`
	DueAt                data.NullTime         `json:"dueAt"`
	ResolvedAt           data.NullTime         `json:"resolvedAt"`
	Evidence             *any                  `json:"evidence"`
	Attachments          *any                  `json:"attachments"`
	Note                 data.NullString       `json:"note"`
	History              []DisputeHistoryEntry `json:"history"`
	Messages             []DisputeMessage      `json:"messages"`
	CreatedAt            data.Time             `json:"created_at"`
	UpdatedAt            data.Time             `json:"updated_at"`
}

type ChargeSuccessEvent

type ChargeSuccessEvent struct {
	ID                 data.Int             `json:"id"`
	Domain             data.String          `json:"domain"`
	Status             data.String          `json:"status"`
	Reference          data.String          `json:"reference"`
	ReceiptNumber      data.NullString      `json:"receipt_number"`
	Amount             data.Int             `json:"amount"`
	Message            data.NullString      `json:"message"`
	GatewayResponse    data.String          `json:"gateway_response"`
	PaidAt             data.NullTime        `json:"paid_at"`
	CreatedAt          data.Time            `json:"created_at"`
	Channel            data.String          `json:"channel"`
	Currency           data.String          `json:"currency"`
	IPAddress          data.String          `json:"ip_address"`
	Metadata           types.Metadata       `json:"metadata"`
	Log                *any                 `json:"log"`
	Fees               data.Int             `json:"fees"`
	FeesSplit          *any                 `json:"fees_split"`
	Authorization      *types.Authorization `json:"authorization"`
	Customer           *types.Customer      `json:"customer"`
	Plan               *any                 `json:"plan"`
	Split              *any                 `json:"split"`
	OrderID            *any                 `json:"order_id"`
	PaidAt2            data.NullTime        `json:"paidAt"`
	RequestedAmount    data.Int             `json:"requested_amount"`
	PosTransactionData *any                 `json:"pos_transaction_data"`
	Source             *any                 `json:"source"`
	FeesBreakdown      *any                 `json:"fees_breakdown"`
}

type CustomerIdentification

type CustomerIdentification struct {
	Type          data.String `json:"type"`
	Value         data.String `json:"value"`
	Country       data.String `json:"country"`
	BVN           data.String `json:"bvn"`
	AccountNumber data.String `json:"account_number"`
	BankCode      data.String `json:"bank_code"`
}

type CustomerIdentificationFailedEvent

type CustomerIdentificationFailedEvent struct {
	ID             data.Int               `json:"id"`
	CustomerID     data.String            `json:"customer_id"`
	CustomerCode   data.String            `json:"customer_code"`
	Email          data.String            `json:"email"`
	Identification CustomerIdentification `json:"identification"`
	CreatedAt      data.Time              `json:"created_at"`
	UpdatedAt      data.Time              `json:"updated_at"`
}

type CustomerIdentificationSuccessEvent

type CustomerIdentificationSuccessEvent struct {
	ID             data.Int               `json:"id"`
	CustomerID     data.String            `json:"customer_id"`
	CustomerCode   data.String            `json:"customer_code"`
	Email          data.String            `json:"email"`
	Identification CustomerIdentification `json:"identification"`
	CreatedAt      data.Time              `json:"created_at"`
	UpdatedAt      data.Time              `json:"updated_at"`
}

type DedicatedAccountEvent

type DedicatedAccountEvent struct {
	ID             data.Int        `json:"id"`
	Domain         data.String     `json:"domain"`
	Status         data.String     `json:"status"`
	AccountName    data.String     `json:"account_name"`
	AccountNumber  data.String     `json:"account_number"`
	BankCode       data.String     `json:"bank_code"`
	BankName       data.String     `json:"bank_name"`
	Customer       *types.Customer `json:"customer"`
	CustomerCode   data.String     `json:"customer_code"`
	ExpiresAt      data.NullTime   `json:"expires_at"`
	CreatedAt      data.Time       `json:"created_at"`
	UpdatedAt      data.Time       `json:"updated_at"`
	Identification types.Metadata  `json:"identification"`
}

type DisputeHistoryEntry

type DisputeHistoryEntry struct {
	Status    data.String `json:"status"`
	By        data.String `json:"by"`
	CreatedAt data.Time   `json:"created_at"`
}

type DisputeMessage

type DisputeMessage struct {
	Sender    data.String `json:"sender"`
	Body      data.String `json:"body"`
	CreatedAt data.Time   `json:"created_at"`
}

type Event

type Event struct {
	Event string          `json:"event"`
	Data  json.RawMessage `json:"data"`
}

func ParseEvent added in v1.0.3

func ParseEvent(r *http.Request) (*Event, error)

func (*Event) AsChargeDispute

func (e *Event) AsChargeDispute() (*ChargeDisputeEvent, error)

func (*Event) AsChargeSuccess

func (e *Event) AsChargeSuccess() (*ChargeSuccessEvent, error)

func (*Event) AsCustomerIdentificationFailed

func (e *Event) AsCustomerIdentificationFailed() (*CustomerIdentificationFailedEvent, error)

func (*Event) AsCustomerIdentificationSuccess

func (e *Event) AsCustomerIdentificationSuccess() (*CustomerIdentificationSuccessEvent, error)

func (*Event) AsDedicatedAccount

func (e *Event) AsDedicatedAccount() (*DedicatedAccountEvent, error)

func (*Event) AsInvoiceCreate

func (e *Event) AsInvoiceCreate() (*InvoiceCreateEvent, error)

func (*Event) AsInvoicePaymentFailed

func (e *Event) AsInvoicePaymentFailed() (*InvoicePaymentFailedEvent, error)

func (*Event) AsInvoiceUpdate

func (e *Event) AsInvoiceUpdate() (*InvoiceUpdateEvent, error)

func (*Event) AsPaymentRequest

func (e *Event) AsPaymentRequest() (*PaymentRequestEvent, error)

func (*Event) AsRefundFailed

func (e *Event) AsRefundFailed() (*RefundFailedEvent, error)

func (*Event) AsRefundPending

func (e *Event) AsRefundPending() (*RefundPendingEvent, error)

func (*Event) AsRefundProcessed

func (e *Event) AsRefundProcessed() (*RefundProcessedEvent, error)

func (*Event) AsSubscriptionCreate

func (e *Event) AsSubscriptionCreate() (*SubscriptionCreateEvent, error)

func (*Event) AsSubscriptionDisable

func (e *Event) AsSubscriptionDisable() (*SubscriptionDisableEvent, error)

func (*Event) AsSubscriptionExpiringCards

func (e *Event) AsSubscriptionExpiringCards() (*SubscriptionExpiringCardsEvent, error)

func (*Event) AsSubscriptionNotRenew

func (e *Event) AsSubscriptionNotRenew() (*SubscriptionNotRenewEvent, error)

func (*Event) AsTransferFailed

func (e *Event) AsTransferFailed() (*TransferFailedEvent, error)

func (*Event) AsTransferReversed

func (e *Event) AsTransferReversed() (*TransferReversedEvent, error)

func (*Event) AsTransferSuccess

func (e *Event) AsTransferSuccess() (*TransferSuccessEvent, error)

type InvoiceCreateEvent

type InvoiceCreateEvent struct {
	Domain       data.String     `json:"domain"`
	InvoiceCode  data.String     `json:"invoice_code"`
	Amount       data.Int        `json:"amount"`
	PeriodStart  data.Time       `json:"period_start"`
	PeriodEnd    data.Time       `json:"period_end"`
	Status       data.String     `json:"status"`
	Paid         data.Bool       `json:"paid"`
	Currency     data.String     `json:"currency"`
	Customer     *types.Customer `json:"customer"`
	Subscription *any            `json:"subscription"`
	ID           data.Int        `json:"id"`
	CreatedAt    data.Time       `json:"created_at"`
	UpdatedAt    data.Time       `json:"updated_at"`
}

type InvoicePaymentFailedEvent

type InvoicePaymentFailedEvent struct {
	ID          data.Int        `json:"id"`
	Domain      data.String     `json:"domain"`
	InvoiceCode data.String     `json:"invoice_code"`
	Amount      data.Int        `json:"amount"`
	PeriodStart data.Time       `json:"period_start"`
	PeriodEnd   data.Time       `json:"period_end"`
	Status      data.String     `json:"status"`
	Paid        data.Bool       `json:"paid"`
	Currency    data.String     `json:"currency"`
	Customer    *types.Customer `json:"customer"`
	Transaction *any            `json:"transaction"`
	CreatedAt   data.Time       `json:"created_at"`
	UpdatedAt   data.Time       `json:"updated_at"`
}

type InvoiceUpdateEvent

type InvoiceUpdateEvent struct {
	ID          data.Int        `json:"id"`
	Domain      data.String     `json:"domain"`
	InvoiceCode data.String     `json:"invoice_code"`
	Amount      data.Int        `json:"amount"`
	PeriodStart data.Time       `json:"period_start"`
	PeriodEnd   data.Time       `json:"period_end"`
	Status      data.String     `json:"status"`
	Paid        data.Bool       `json:"paid"`
	Currency    data.String     `json:"currency"`
	Customer    *types.Customer `json:"customer"`
	Transaction *any            `json:"transaction"`
	CreatedAt   data.Time       `json:"created_at"`
	UpdatedAt   data.Time       `json:"updated_at"`
}

type PaymentRequestEvent

type PaymentRequestEvent struct {
	ID               data.Int        `json:"id"`
	Domain           data.String     `json:"domain"`
	Amount           data.Int        `json:"amount"`
	Currency         data.String     `json:"currency"`
	DueDate          data.NullTime   `json:"due_date"`
	HasInvoice       data.Bool       `json:"has_invoice"`
	InvoiceNumber    data.NullString `json:"invoice_number"`
	Description      data.String     `json:"description"`
	PDF_URL          data.NullString `json:"pdf_url"`
	LineItems        []any           `json:"line_items"`
	Tax              []any           `json:"tax"`
	RequestCode      data.String     `json:"request_code"`
	Status           data.String     `json:"status"`
	Paid             data.Bool       `json:"paid"`
	PaidAt           data.NullTime   `json:"paid_at"`
	Metadata         types.Metadata  `json:"metadata"`
	Notifications    []any           `json:"notifications"`
	OfflineReference data.NullString `json:"offline_reference"`
	// In webhooks this can be ID or object; accept loosely
	Customer  types.Metadata `json:"customer"`
	CreatedAt data.Time      `json:"created_at"`
}

type RefundFailedEvent

type RefundFailedEvent struct {
	ID             data.Int           `json:"id"`
	Integration    data.Int           `json:"integration"`
	Domain         data.String        `json:"domain"`
	Transaction    *types.Transaction `json:"transaction"`
	Dispute        *any               `json:"dispute"`
	Amount         data.Int           `json:"amount"`
	DeductedAmount data.Int           `json:"deducted_amount"`
	FullyDeducted  data.Bool          `json:"fully_deducted"`
	Currency       data.String        `json:"currency"`
	Status         data.String        `json:"status"`
	RefundedBy     data.String        `json:"refunded_by"`
	RefundedAt     data.NullTime      `json:"refunded_at"`
	ExpectedAt     data.Time          `json:"expected_at"`
	CreatedAt      data.Time          `json:"created_at"`
	UpdatedAt      data.Time          `json:"updated_at"`
}

type RefundPendingEvent

type RefundPendingEvent struct {
	ID             data.Int           `json:"id"`
	Integration    data.Int           `json:"integration"`
	Domain         data.String        `json:"domain"`
	Transaction    *types.Transaction `json:"transaction"`
	Dispute        *any               `json:"dispute"`
	Amount         data.Int           `json:"amount"`
	DeductedAmount data.Int           `json:"deducted_amount"`
	FullyDeducted  data.Bool          `json:"fully_deducted"`
	Currency       data.String        `json:"currency"`
	Status         data.String        `json:"status"`
	RefundedBy     data.String        `json:"refunded_by"`
	RefundedAt     data.NullTime      `json:"refunded_at"`
	ExpectedAt     data.Time          `json:"expected_at"`
	CreatedAt      data.Time          `json:"created_at"`
	UpdatedAt      data.Time          `json:"updated_at"`
}

type RefundProcessedEvent

type RefundProcessedEvent struct {
	ID             data.Int           `json:"id"`
	Integration    data.Int           `json:"integration"`
	Domain         data.String        `json:"domain"`
	Transaction    *types.Transaction `json:"transaction"`
	Dispute        *any               `json:"dispute"`
	Amount         data.Int           `json:"amount"`
	DeductedAmount data.Int           `json:"deducted_amount"`
	FullyDeducted  data.Bool          `json:"fully_deducted"`
	Currency       data.String        `json:"currency"`
	Status         data.String        `json:"status"`
	RefundedBy     data.String        `json:"refunded_by"`
	RefundedAt     data.NullTime      `json:"refunded_at"`
	ExpectedAt     data.Time          `json:"expected_at"`
	CreatedAt      data.Time          `json:"created_at"`
	UpdatedAt      data.Time          `json:"updated_at"`
}

type SubscriptionCreateEvent

type SubscriptionCreateEvent struct {
	Domain           data.String          `json:"domain"`
	Status           data.String          `json:"status"`
	SubscriptionCode data.String          `json:"subscription_code"`
	Amount           data.Int             `json:"amount"`
	CronExpression   data.String          `json:"cron_expression"`
	NextPaymentDate  data.Time            `json:"next_payment_date"`
	OpenInvoice      data.NullString      `json:"open_invoice"`
	Integration      data.Int             `json:"integration"`
	Plan             *any                 `json:"plan"`
	Authorization    *types.Authorization `json:"authorization"`
	Customer         *types.Customer      `json:"customer"`
	ID               data.Int             `json:"id"`
	CreatedAt        data.Time            `json:"created_at"`
	UpdatedAt        data.Time            `json:"updated_at"`
}

type SubscriptionDisableEvent

type SubscriptionDisableEvent struct {
	ID               data.Int             `json:"id"`
	Domain           data.String          `json:"domain"`
	Status           data.String          `json:"status"`
	SubscriptionCode data.String          `json:"subscription_code"`
	EmailToken       data.String          `json:"email_token"`
	Amount           data.Int             `json:"amount"`
	CronExpression   data.String          `json:"cron_expression"`
	NextPaymentDate  data.NullTime        `json:"next_payment_date"`
	OpenInvoice      data.NullString      `json:"open_invoice"`
	Customer         *types.Customer      `json:"customer"`
	Plan             *any                 `json:"plan"`
	Authorization    *types.Authorization `json:"authorization"`
	Invoices         []any                `json:"invoices"`
	CreatedAt        data.Time            `json:"created_at"`
	UpdatedAt        data.Time            `json:"updated_at"`
}

type SubscriptionExpiringCardsEvent

type SubscriptionExpiringCardsEvent struct {
	// Expiring cards payload is an array of entries; we accept Metadata for flexibility
	Entries types.Metadata `json:"-"`
}

type SubscriptionNotRenewEvent

type SubscriptionNotRenewEvent struct {
	ID               data.Int             `json:"id"`
	Domain           data.String          `json:"domain"`
	Status           data.String          `json:"status"`
	SubscriptionCode data.String          `json:"subscription_code"`
	EmailToken       data.String          `json:"email_token"`
	Amount           data.Int             `json:"amount"`
	CronExpression   data.String          `json:"cron_expression"`
	NextPaymentDate  data.NullTime        `json:"next_payment_date"`
	OpenInvoice      data.NullString      `json:"open_invoice"`
	Customer         *types.Customer      `json:"customer"`
	Plan             *any                 `json:"plan"`
	Authorization    *types.Authorization `json:"authorization"`
	Invoices         []any                `json:"invoices"`
	CreatedAt        data.Time            `json:"created_at"`
	UpdatedAt        data.Time            `json:"updated_at"`
}

type TransferFailedEvent

type TransferFailedEvent struct {
	Amount        data.Int        `json:"amount"`
	Currency      data.String     `json:"currency"`
	Domain        data.String     `json:"domain"`
	Failures      *any            `json:"failures"`
	ID            data.Int        `json:"id"`
	Integration   types.Metadata  `json:"integration"`
	Reason        data.String     `json:"reason"`
	Reference     data.String     `json:"reference"`
	Source        data.String     `json:"source"`
	SourceDetails *any            `json:"source_details"`
	Status        data.String     `json:"status"`
	TitanCode     data.NullString `json:"titan_code"`
	TransferCode  data.String     `json:"transfer_code"`
	TransferredAt data.NullTime   `json:"transferred_at"`
	Recipient     types.Recipient `json:"recipient"`
	Session       *any            `json:"session"`
	CreatedAt     data.Time       `json:"created_at"`
	UpdatedAt     data.Time       `json:"updated_at"`
}

type TransferReversedEvent

type TransferReversedEvent struct {
	Amount        data.Int        `json:"amount"`
	Currency      data.String     `json:"currency"`
	Domain        data.String     `json:"domain"`
	Failures      *any            `json:"failures"`
	ID            data.Int        `json:"id"`
	Integration   types.Metadata  `json:"integration"`
	Reason        data.String     `json:"reason"`
	Reference     data.String     `json:"reference"`
	Source        data.String     `json:"source"`
	SourceDetails *any            `json:"source_details"`
	Status        data.String     `json:"status"`
	TitanCode     data.NullString `json:"titan_code"`
	TransferCode  data.String     `json:"transfer_code"`
	TransferredAt data.NullTime   `json:"transferred_at"`
	Recipient     types.Recipient `json:"recipient"`
	Session       *any            `json:"session"`
	CreatedAt     data.Time       `json:"created_at"`
	UpdatedAt     data.Time       `json:"updated_at"`
}

type TransferSuccessEvent

type TransferSuccessEvent struct {
	Amount        data.Int        `json:"amount"`
	Currency      data.String     `json:"currency"`
	Domain        data.String     `json:"domain"`
	Failures      *any            `json:"failures"`
	ID            data.Int        `json:"id"`
	Integration   types.Metadata  `json:"integration"`
	Reason        data.String     `json:"reason"`
	Reference     data.String     `json:"reference"`
	Source        data.String     `json:"source"`
	SourceDetails *any            `json:"source_details"`
	Status        data.String     `json:"status"`
	TitanCode     data.NullString `json:"titan_code"`
	TransferCode  data.String     `json:"transfer_code"`
	TransferredAt data.NullTime   `json:"transferred_at"`
	Recipient     types.Recipient `json:"recipient"`
	Session       *any            `json:"session"`
	CreatedAt     data.Time       `json:"created_at"`
	UpdatedAt     data.Time       `json:"updated_at"`
}

type Validator

type Validator struct {
	// contains filtered or unexported fields
}

func NewValidator

func NewValidator(secretKey string) *Validator

func (*Validator) ValidateRequest

func (v *Validator) ValidateRequest(r *http.Request) (*Event, error)

func (*Validator) ValidateSignature

func (v *Validator) ValidateSignature(payload []byte, signature string) bool

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL