Skip to content

Commit

Permalink
Refactor webhooks package (#57)
Browse files Browse the repository at this point in the history
  • Loading branch information
frankienicoletti committed Jun 19, 2018
1 parent 731eb61 commit cffc983
Show file tree
Hide file tree
Showing 17 changed files with 596 additions and 246 deletions.
4 changes: 4 additions & 0 deletions README.md
Expand Up @@ -3,6 +3,10 @@ Recurly is a Go (golang) API Client for the [Recurly](https://recurly.com/) API.

[![Build Status](https://travis-ci.org/blacklightcms/recurly.svg?branch=master)](https://travis-ci.org/blacklightcms/recurly) [![GoDoc](https://godoc.org/github.com/blacklightcms/recurly?status.svg)](https://godoc.org/github.com/blacklightcms/recurly)

## Note on Credit Invoices feature

Recurly requires the credit invoices feature to be turned on by Nov 1, 2018. There are some changes to the API that will occur when the feature is turned on that are separate from version updates. As we are updating this library, comments will be left where functions and constants will be deprecated, and some deprecated constants will be renamed with the suffix `Deprecated`. Many of the new data structures can coexist with existing data structures (which will later be removed). Please note that at least one webhook structure is changing and cannot coexist with the previous version. Please see the comments in the `webhooks` package for more information and use `webhooks.ParseOriginal` to only parse the original versions. `webhooks.Parse` parses new notifications as well as the deprecated invoice notifications will may still be sent for legacy invoices after the credit invoices feature is turned on.

## References
* [API Reference](http://godoc.org/github.com/blacklightcms/recurly)
* [Recurly API Documentation](https://dev.recurly.com/docs/)
Expand Down
35 changes: 29 additions & 6 deletions invoices.go
Expand Up @@ -6,13 +6,22 @@ import (
)

// Invoice state constants.
// https://docs.recurly.com/docs/credit-invoices-release#section-invoice-attribute-changes
const (
InvoiceStateOpen = "open" // pending collection
InvoiceStatePending = "pending" // new status will replace "open"
InvoiceStateCollected = "collected" // successfully collected
InvoiceStatePaid = "paid" // new status will replace "collected"
InvoiceStatePastDue = "past_due" // initial collection failed, still attempting
InvoiceStateFailed = "failed" // failed to collect
ChargeInvoiceStatePending = "pending" // previously "open"
ChargeInvoiceStateProcessing = "processing" // ACH payments only
ChargeInvoiceStatePastDue = "past_due"
ChargeInvoiceStatePaid = "paid" // previously "collected"
ChargeInvoiceStateFailed = "failed"

CreditInvoiceStateOpen = "open"
CreditInvoiceStateProcessing = "processing" // ACH/bank refund processing
CreditInvoiceStateClosed = "closed"
CreditInvoiceStateVoided = "voided"

// Deprecated
InvoiceStateOpenDeprecated = "open"
InvoiceStateCollectedDeprecated = "collected"
)

// Collection method constants.
Expand All @@ -32,6 +41,20 @@ const (
PaymentMethodOther = "other"
)

// Invoice origin constants.
const (
ChargeInvoiceOriginPurchase = "purchase"
ChargeInvoiceOriginRenewal = "renewal"
ChargeInvoiceOriginImmediateChange = "immediate_change"
ChargeInvoiceOriginTermination = "termination"

CreditInvoiceOriginGiftCard = "gift_card"
CreditInvoiceOriginRefund = "refund"
CreditInvoiceOriginCredit = "credit"
CreditInvoiceOriginWriteOff = "write_off"
CreditInvoiceOriginExternalCredit = "external_credit"
)

// Invoice is an individual invoice for an account.
// The only fields annotated with XML tags are those for posting an invoice.
// Unmarshaling an invoice is handled by the custom UnmarshalXML function.
Expand Down
8 changes: 4 additions & 4 deletions invoices_test.go
Expand Up @@ -107,7 +107,7 @@ func TestInvoices_List(t *testing.T) {
},
OriginalInvoiceNumber: 938571,
UUID: "421f7b7d414e4c6792938e7c49d552e9",
State: recurly.InvoiceStateOpen,
State: recurly.InvoiceStateOpenDeprecated,
InvoiceNumber: 1005,
SubtotalInCents: 1200,
TaxInCents: 0,
Expand Down Expand Up @@ -238,7 +238,7 @@ func TestInvoices_ListAccount(t *testing.T) {
Country: "US",
},
UUID: "421f7b7d414e4c6792938e7c49d552e9",
State: recurly.InvoiceStateOpen,
State: recurly.InvoiceStateOpenDeprecated,
InvoiceNumber: 1005,
SubtotalInCents: 1200,
TaxInCents: 0,
Expand Down Expand Up @@ -464,7 +464,7 @@ func TestInvoices_Get(t *testing.T) {
Country: "US",
},
UUID: "421f7b7d414e4c6792938e7c49d552e9",
State: recurly.InvoiceStatePaid,
State: recurly.ChargeInvoiceStatePaid,
InvoiceNumber: 5558,
SubtotalInCents: 153000,
TaxInCents: 0,
Expand Down Expand Up @@ -807,7 +807,7 @@ func TestInvoices_Create(t *testing.T) {
Country: "US",
},
UUID: "43adb97640cc05dee0b10042e596307f",
State: recurly.InvoiceStatePending,
State: recurly.ChargeInvoiceStatePending,
InvoiceNumber: 1016,
SubtotalInCents: 3000,
TaxInCents: 425,
Expand Down
3 changes: 2 additions & 1 deletion subscriptions_test.go
Expand Up @@ -7,6 +7,7 @@ import (
"net/http"
"testing"
"time"

"github.com/blacklightcms/recurly"
"github.com/google/go-cmp/cmp"
)
Expand Down Expand Up @@ -853,7 +854,7 @@ func TestSubscriptions_Preview(t *testing.T) {
XMLName: xml.Name{Local: "invoice"},
AccountCode: "1",
UUID: "43adfe52c21cbb221557a24940bcd7e5",
State: recurly.InvoiceStatePending,
State: recurly.ChargeInvoiceStatePending,
},
}); diff != "" {
t.Fatal(diff)
Expand Down
1 change: 1 addition & 0 deletions transactions.go
Expand Up @@ -167,6 +167,7 @@ func (t *Transaction) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
return nil
}

// TransactionResult is included in CVV results.
type TransactionResult struct {
NullMarshal
Code string `xml:"code,attr"`
Expand Down
27 changes: 27 additions & 0 deletions webhooks/accounts.go
@@ -0,0 +1,27 @@
package webhooks

import "encoding/xml"

// Account notifications.
// https://dev.recurly.com/page/webhooks#account-notifications
const (
BillingInfoUpdated = "billing_info_updated_notification"
)

// AccountNotification is returned for all account notifications.
type AccountNotification struct {
Type string `xml:"-"`
Account Account `xml:"account"`
}

// Account represents the account object sent in webhooks.
type Account struct {
XMLName xml.Name `xml:"account"`
Code string `xml:"account_code"`
Username string `xml:"username"`
Email string `xml:"email"`
FirstName string `xml:"first_name"`
LastName string `xml:"last_name"`
CompanyName string `xml:"company_name"`
Phone string `xml:"phone"`
}
45 changes: 45 additions & 0 deletions webhooks/charge_invoices.go
@@ -0,0 +1,45 @@
package webhooks

import (
"encoding/xml"

"github.com/blacklightcms/recurly"
)

// Charge invoice notifications.
// https://dev.recurly.com/page/webhooks#charge-invoice-notifications
const (
NewChargeInvoice = "new_charge_invoice_notification"
ProcessingChargeInvoice = "processing_charge_invoice_notification"
PastDueChargeInvoice = "past_due_charge_invoice_notification"
PaidChargeInvoice = "paid_charge_invoice_notification"
FailedChargeInvoice = "failed_charge_invoice_notification"
ReopenedChargeInvoice = "reopened_charge_invoice_notification"
)

// ChargeInvoiceNotification is returned for all charge invoice notifications.
type ChargeInvoiceNotification struct {
Type string `xml:"-"`
Account Account `xml:"account"`
Invoice ChargeInvoice `xml:"invoice"`
}

// ChargeInvoice represents the charge invoice object sent in webhooks.
type ChargeInvoice struct {
XMLName xml.Name `xml:"invoice"`
SubscriptionUUIDs []string `xml:"subscription_ids>subscription_id"`
UUID string `xml:"uuid"`
State string `xml:"state"`
Origin string `xml:"origin"`
InvoiceNumberPrefix string `xml:"invoice_number_prefix"`
InvoiceNumber int `xml:"invoice_number"`
PONumber string `xml:"po_number"`
VATNumber string `xml:"vat_number"`
BalanceInCents int `xml:"balance_in_cents"`
TotalInCents int `xml:"total_in_cents"`
Currency string `xml:"currency"`
CreatedAt recurly.NullTime `xml:"created_at"`
ClosedAt recurly.NullTime `xml:"closed_at"`
NetTerms recurly.NullInt `xml:"net_terms"`
CollectionMethod string `xml:"collection_method"`
}
41 changes: 41 additions & 0 deletions webhooks/credit_invoices.go
@@ -0,0 +1,41 @@
package webhooks

import (
"encoding/xml"

"github.com/blacklightcms/recurly"
)

// Credit invoice notifications.
// https://dev.recurly.com/page/webhooks#charge-invoice-notifications
const (
NewCreditInvoice = "new_credit_invoice_notification"
ProcessingCreditInvoice = "processing_credit_invoice_notification"
ClosedCreditInvoice = "closed_credit_invoice_notification"
VoidedCreditInvoice = "voided_credit_invoice_notification"
ReopenedCreditInvoice = "reopened_credit_invoice_notification"
OpenCreditInvoice = "open_credit_invoice_notification"
)

// CreditInvoiceNotification is returned for all credit invoice notifications.
type CreditInvoiceNotification struct {
Type string `xml:"-"`
Account Account `xml:"account"`
Invoice CreditInvoice `xml:"invoice"`
}

// CreditInvoice represents the credit invoice object sent in webhooks.
type CreditInvoice struct {
XMLName xml.Name `xml:"invoice"`
SubscriptionUUIDs []string `xml:"subscription_ids>subscription_id"`
UUID string `xml:"uuid"`
State string `xml:"state"`
Origin string `xml:"origin"`
InvoiceNumberPrefix string `xml:"invoice_number_prefix"`
InvoiceNumber int `xml:"invoice_number"`
BalanceInCents int `xml:"balance_in_cents"`
TotalInCents int `xml:"total_in_cents"`
Currency string `xml:"currency"`
CreatedAt recurly.NullTime `xml:"created_at"`
ClosedAt recurly.NullTime `xml:"closed_at"`
}
35 changes: 35 additions & 0 deletions webhooks/credit_payments.go
@@ -0,0 +1,35 @@
package webhooks

import (
"encoding/xml"

"github.com/blacklightcms/recurly"
)

// Credit payment notifications.
// https://dev.recurly.com/page/webhooks#credit-payment-notifications
const (
NewCreditPayment = "new_credit_payment_notification"
VoidedCreditPayment = "voided_credit_payment_notification"
)

// CreditPaymentNotification is returned for all credit payment notifications.
type CreditPaymentNotification struct {
Type string `xml:"-"`
Account Account `xml:"account"`
CreditPayment CreditPayment `xml:"credit_payment"`
}

// CreditPayment represents the credit payment object sent in webhooks.
type CreditPayment struct {
XMLName xml.Name `xml:"credit_payment"`
UUID string `xml:"uuid"`
Action string `xml:"action"`
AmountInCents int `xml:"amount_in_cents"`
OriginalInvoiceNumber int `xml:"original_invoice_number"`
AppliedToInvoiceNumber int `xml:"applied_to_invoice_number"`
OriginalCreditPaymentUUID string `xml:"original_credit_payment_uuid"`
RefundTransactionUUID string `xml:"refund_transaction_uuid"`
CreatedAt recurly.NullTime `xml:"created_at"`
VoidedAt recurly.NullTime `xml:"voided_at"`
}
43 changes: 43 additions & 0 deletions webhooks/invoices.go
@@ -0,0 +1,43 @@
package webhooks

import (
"encoding/xml"

"github.com/blacklightcms/recurly"
)

// Invoice notifications.
// Will be deprecated after credit invoices feature is turned on.
// https://dev.recurly.com/page/webhooks#invoice-notifications
const (
NewInvoice = "new_invoice_notification"
PastDueInvoice = "past_due_invoice_notification"
)

// InvoiceNotification is returned for all invoice notifications.
type InvoiceNotification struct {
Type string `xml:"-"`
Account Account `xml:"account"`
Invoice Invoice `xml:"invoice"`
}

// Invoice represents the invoice object sent in webhooks.
// After credit invoices have been turned on, these notifications will only be
// sent for TypeLegacy invoices (posted before the feature was turned on)
// then deprecated.
type Invoice struct {
XMLName xml.Name `xml:"invoice"`
SubscriptionUUID string `xml:"subscription_id"`
UUID string `xml:"uuid"`
State string `xml:"state"`
InvoiceNumberPrefix string `xml:"invoice_number_prefix"`
InvoiceNumber int `xml:"invoice_number"`
PONumber string `xml:"po_number"`
VATNumber string `xml:"vat_number"`
TotalInCents int `xml:"total_in_cents"`
Currency string `xml:"currency"`
CreatedAt recurly.NullTime `xml:"date"`
ClosedAt recurly.NullTime `xml:"closed_at"`
NetTerms recurly.NullInt `xml:"net_terms"`
CollectionMethod string `xml:"collection_method"`
}
48 changes: 48 additions & 0 deletions webhooks/payments.go
@@ -0,0 +1,48 @@
package webhooks

import (
"encoding/xml"

"github.com/blacklightcms/recurly"
)

// Payment notifications.
// https://dev.recurly.com/page/webhooks#payment-notifications
const (
SuccessfulPayment = "successful_payment_notification"
FailedPayment = "failed_payment_notification"
VoidPayment = "void_payment_notification"
SuccessfulRefund = "successful_refund_notification"
)

// PaymentNotification is returned for all credit payment notifications.
type PaymentNotification struct {
Type string `xml:"-"`
Account Account `xml:"account"`
Transaction Transaction `xml:"transaction"`
}

// Transaction represents the transaction object sent in webhooks.
type Transaction struct {
XMLName xml.Name `xml:"transaction"`
UUID string `xml:"id"`
InvoiceNumber int `xml:"invoice_number"`
SubscriptionUUID string `xml:"subscription_id"`
Action string `xml:"action"`
AmountInCents int `xml:"amount_in_cents"`
Status string `xml:"status"`
Message string `xml:"message"`
GatewayErrorCodes string `xml:"gateway_error_codes"`
FailureType string `xml:"failure_type"`
Reference string `xml:"reference"`
Source string `xml:"source"`
Test recurly.NullBool `xml:"test"`
Voidable recurly.NullBool `xml:"voidable"`
Refundable recurly.NullBool `xml:"refundable"`
}

// Transaction constants.
const (
TransactionFailureTypeDeclined = "declined"
TransactionFailureTypeDuplicate = "duplicate_transaction"
)
20 changes: 20 additions & 0 deletions webhooks/subscriptions.go
@@ -0,0 +1,20 @@
package webhooks

import "github.com/blacklightcms/recurly"

// Subscription notifications.
// https://dev.recurly.com/page/webhooks#subscription-notifications
const (
NewSubscription = "new_subscription_notification"
UpdatedSubscription = "updated_subscription_notification"
RenewedSubscription = "renewed_subscription_notification"
ExpiredSubscription = "expired_subscription_notification"
CanceledSubscription = "canceled_subscription_notification"
)

// SubscriptionNotification is returned for all subscription notifications.
type SubscriptionNotification struct {
Type string `xml:"-"`
Account Account `xml:"account"`
Subscription recurly.Subscription `xml:"subscription"`
}

0 comments on commit cffc983

Please sign in to comment.