recurly

package module
v2.0.0+incompatible Latest Latest
Warning

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

Go to latest
Published: Oct 14, 2021 License: MIT Imports: 20 Imported by: 0

README

Recurly Client for Go

Build Status GoDoc

Recurly is a Go (golang) API Client for the Recurly API. It is actively maintained, unit tested, and uses no external dependencies. The vast majority of the API is implemented.

Supports:

  • Recurly API v2.27
  • Accounts
  • Add Ons
  • Adjustments
  • Billing
  • Coupons
  • Credit Payments
  • Invoices
  • Plans
  • Purchases
  • Redemptions
  • Shipping Addresses
  • Shipping Methods
  • Subscriptions
  • Transactions

Installation

Install:

go get github.com/blacklightcms/recurly

Import:

import "github.com/blacklightcms/recurly"

Resources:

Note on v1 and breaking changes

If migrating from a previous version of the library, there was a large refactor with breaking changes released to address some design issues with the library. See the migration guide for steps on how to migrate to the latest version.

This is recommended for all users.

Quickstart

Construct a new Recurly client, then use the various services on the client to access different parts of the Recurly API. For example:

client := recurly.NewClient("your-subdomain", "APIKEY")

// Retrieve an account
a, err := client.Accounts.Get(context.Background(), "1")

Examples and How To

Please go through examples for detailed examples of using this package.

The examples explain important cases like:

  • Null Types
  • Error Handling
  • Get Methods
  • Pagination

Here are a few snippets to demonstrate library usage.

Create Account
account, err := client.Accounts.Create(ctx, recurly.Account{
    Code: "1",
    FirstName: "Verena",
    LastName: "Example",
    Email: "verena@example.com",
})

NOTE: An account can also be created along a subscription by embedding the account in the subscription during creation. The purchases API also supports this, and likely other endpoints. See Recurly's documentation for details.

Get Account
account, err := client.Accounts.Get(ctx, "1")
if err != nil {
    return err
} else if account == nil {
    // account not found
    // Note: this nil, nil response on 404s is unique to Get() methods
    // See GoDoc for details.
}
Create Billing Info
// Using token obtained with recurly.js
// If you want to set billing info directly, omit the token and set the
// corresponding fields on the recurly.Billing struct.
billing, err := client.Billing.Create("1", recurly.Billing{
    Token: token,
})

NOTE: See the error handling section in GoDoc for how to handle transaction errors

Creating Purchases
purchase, err := c.Client.Purchases.Create(ctx, recurly.Purchase{
    Account: recurly.Account{
	    Code: "1",
    },
    Adjustments: []recurly.Adjustment{{
	    UnitAmountInCents: recurly.NewInt(100),
	    Description:       "Purchase Description",
	    ProductCode:       "product_code",
    }},
    CollectionMethod: recurly.CollectionMethodAutomatic,
    Currency:         "USD",
})
if err != nil {
    // NOTE: See GoDoc for how to handle failed transaction errors
}

NOTE: The purchases API supports subscriptions, adjustments, shipping addresses, shipping fees, and more. This is one of many possible examples. See the underlying structs and Recurly's documentation for more info.

Creating Subscriptions
subscription, err := client.Subscriptions.Create(ctx, recurly.NewSubscription{
    PlanCode: "gold",
    Currency: "USD",
    Account: recurly.Account{
        // Note: Set the Code for an existing account
        // To create a new account, omit Code but provide other fields
    },
})
if err != nil {
    // NOTE: See GoDoc for how to handle failed transaction errors
    return err
}

NOTE: Recurly offers several other ways to create subscriptions, often embedded within other requests (such as the Purchases.Create() call). See Recurly's documentation for more details.

Webhooks

This library supports webhooks via the webhooks sub package.

The usage is to parse the webhook from a reader, then use a switch statement to determine the type of webhook received.

// import "github.com/blacklightcms/recurly/webhooks"

hook, err := webhooks.Parse(r)
if e, ok := err.(*webhooks.ErrUnknownNotification); ok {
    // e.Name() holds the name of the notification
} else if err != nil {
    // all other errors
}

// Use a switch statement to determine the type of webhook received.
switch h := hook.(type) {
case *webhooks.AccountNotification:
    // h.Account
case *webhooks.PaymentNotification:
    // h.Account
    // h.Transaction
case *webhooks.SubscriptionNotification:
    // h.Account
    // h.Subscription
default:
    // webhook not listed above
}

Testing

Once you've imported this library into your application, you will want to add tests.

Internally this library sets up a test HTTPs server and validates methods, paths, query strings, request body, and returns XML. You will not need to worry about those internals when testing your own code that uses this library.

Instead we recommend using the mock package. The mock package provides mocks for all of the different services in this library.

For examples of how to test your code using mocks, visit the GoDoc examples.

NOTE: If you need to go beyond mocks and test requests/responses, testing.go exports TestServer. This is how the library tests itself. See the GoDoc or the *_test.go files for usage examples.

Contributing

We use dep for dependency management. If you do not have it installed, see the installation instructions.

To contribute: fork and clone the repository, cd into the directory, and run:

dep ensure

That will ensure you have google/go-cmp which is used to run tests.

If you plan on submitting a patch, please write tests for it.

Documentation

Overview

Package recurly provides a client for using the Recurly API.

Usage

Construct a new Recurly client, then use the various services on the client to access different parts of the Recurly API. For example:

import "github.com/blacklightcms/recurly"

func main() {
	client := recurly.NewClient("your-subdomain", "APIKEY")

	// Retrieve an account
	a, err := client.Accounts.Get(context.Background(), "1")
}

See the examples section for more usage examples.

Null Types

Null types provide a way to differentiate between zero values and real values. For example, 0 is the zero value for ints; false for bools. Because those are valid values, null types allow us to differentiate between bool false as a valid value (we want to send to Recurly) and bool false as the zero value (we do not want to send to recurly)

There are three null types: recurly.NullInt, recurly.NullBool, and recurly.NullTime

a := recurly.Adjustment{
	UnitAmountInCents: recurly.NewInt(0),
	Taxable: recurly.NewBool(false),
	StartDate: recurly.NewTime(time.Now()),
}

// Null Int
i := a.UnitAmountInCents.Int() // 0
i, ok := a.UnitAmountInCents.Value() // 0, true
iPtr := a.UnitAmountInCents.IntPtr() // Return *int, will be nil if value is invalid

// NullBool
b := a.Taxable.Bool() // false
b, ok := a.Taxable.Value() // false, true
bPtr := a.Taxable.BoolPtr() // Return *bool, will be nil if value is invalid

// NullTime
t := a.StartDate.Time() // time.Time
t, ok := a.StartDate.Value() // time.Time, true
tPtr := a.StartDate.TimePtr() // Return *time.Time, will be nil if value is invalid

If you have a pointer value, you can use New*Ptr() to return a new null type, where the value is valid only if the pointer is non-nil:

i := recurly.NewIntPtr(v) // where v is *int
b := recurly.NewBoolPtr(b) // where b is *bool
t := recurly.NewTimePtr(t) // where t is *time.Time. If non-nil, t.IsZero() must be false to be considered valid

Error Handling

Generally, checking that err != nil is sufficient to catch errors. However there are some circumstances where you may need to know more about the specific error.

ClientError is returned for all 400-level responses with the exception of rate limit errors and failed transactions. Here is an example of working with client errors:

sub, err := client.Invoices.Create(ctx, "1", recurly.Invoice{})
if e, ok := err.(*recurly.ClientError); ok {
	// Check status code (e.g. 404)
	if e.Response.Code == http.StatusNotFound {
		return err
	}

	// Check for a specific validation symbol in one of the error messages
	if e.Is("will_not_invoice") {
		return err
	}

	// Or loop through all of the validation errors
	if len(e.ValidationErrors) > 0 {
		for _, ve := range e.ValidationErrors {
			// Access each validation error here
		}
	}
	return err
} else if err != nil {
	return err
}

TransactionFailedError is returned for any endpoint where a transaction was attempted and failed. It is highly recommended that you check for this error when using any endpoint that creates a transaction.

_, err := client.Purchases.Create(ctx, recurly.Purchase{})
if e, ok := err.(*recurly.TransactionFailedError); ok {
	// e.Transaction holds the failed transaction (if available)
	// e.TransactionError holds the specific error. See the TransactionError
	// struct for specifics on the fields.
} else if err != nil {
	// Handle all other errors
}

ServerError operates the same way as ClientError, except it's returned for 500-level responses. It only contains the *http.Response. This allows you to differentiate retriable errors (e.g. 503 Service Unavailable) from bad requests (e.g. 400 Bad Request).

RateLimitError is returned when the rate limit is exceeded. The Rate field contains information on the amount of requests and when the rate limit will reset.

For more on errors, see the examples section below.

Get Methods

When retrieving an individual item (e.g. account, invoice, subscription): if the item is not found, Recurly will return a 404 Not Found. Typically this will return a *recurly.ClientError. The only exception is for any function named 'Get': a nil item and nil error will be returned if the item is not found.

a, err := client.Accounts.Get(ctx, "1")
if err != nil {
	return err
} else if a == nil {
	// account not found
}

Pagination

All requests for resource collections support pagination. Pagination options are described in the recurly.PagerOptions struct and passed to the list methods directly.

client := recurly.NewClient("your-subdomain", "APIKEY")

// Initialize a pager with any pagination options needed.
pager := client.Accounts.List(&recurly.PagerOptions{
	State: recurly.AccountStateActive,
})

// Count the records (if desired)
count, err := pager.Count(ctx)
if err != nil {
	return err
}

// Or iterate through each of the pages
for pager.Next() {
	var accounts []recurly.Account
	if err := pager.Fetch(ctx, &accounts); err != nil {
		return err
	}
}

You can also let the library paginate for you and return all of the results at once:

pager := client.Accounts.List(nil)
var accounts []recurly.Account
if err := pager.FetchAll(ctx, &accounts); err != nil {
	return err
}

In some cases, you may want to paginate non-consecutively. For example, if you have paginated results being sent to a frontend, and the frontend is providing your app the next cursor.

In that case you can obtain the next cursor like this (although it may be empty):

cursor := pager.Cursor()

If you have a cursor, you can provide *PagerOptions with it to start paginating the next result set:

pager := client.Accounts.List(&recurly.PagerOptions{
	Cursor: cursor,
})

Index

Examples

Constants

View Source
const (
	AccountStateActive = "active"
	AccountStateClosed = "closed"
)

Account constants.

View Source
const (
	AdjustmentStatePending = "pending"
	AdjustmentStateInvoied = "invoiced"
)

Adjustment state constants.

View Source
const (
	RevenueScheduleTypeNever        = "never"
	RevenueScheduleTypeAtRangeStart = "at_range_start"
	RevenueScheduleTypeAtInvoice    = "at_invoice"
	RevenueScheduleTypeEvenly       = "evenly"       // if 'end_date' is set
	RevenueScheduleTypeAtRangeEnd   = "at_range_end" // if 'end_date' is set
)

Revenue schedule type constants.

View Source
const (
	CardTypeAmericanExpress    = "american_express"
	CardTypeDankort            = "dankort"
	CardTypeDinersClub         = "diners_club"
	CardTypeDiscover           = "discover"
	CardTypeForbrugsforeningen = "forbrugsforeningen"
	CardTypeJCB                = "jcb"
	CardTypeLaser              = "laser"
	CardTypeMaestro            = "maestro"
	CardTypeMaster             = "master"
	CardTypeVisa               = "visa"
)

Supported card type constants.

View Source
const (
	CreditPaymentActionPayment   = "payment" // applying the credit
	CreditPaymentActionGiftCard  = "gift_card"
	CreditPaymentActionRefund    = "refund"
	CreditPaymentActionReduction = "reduction" // reducing the amount of the credit without applying it
	CreditPaymentActionWriteOff  = "write_off" // used for voiding invoices
)

Credit payment action constants.

View Source
const (
	ChargeInvoiceStatePending    = "pending"
	ChargeInvoiceStateProcessing = "processing"
	ChargeInvoiceStatePastDue    = "past_due"
	ChargeInvoiceStatePaid       = "paid"
	ChargeInvoiceStateFailed     = "failed"

	CreditInvoiceStateOpen       = "open"
	CreditInvoiceStateProcessing = "processing"
	CreditInvoiceStateClosed     = "closed"
	CreditInvoiceStateVoided     = "voided"
)

Invoice state constants. https://docs.recurly.com/docs/invoices#section-statuses

View Source
const (
	CollectionMethodAutomatic = "automatic"
	CollectionMethodManual    = "manual"
)

Collection method constants.

View Source
const (
	PaymentMethodCreditCard   = "credit_card"
	PaymentMethodPayPal       = "paypal"
	PaymentMethodEFT          = "eft"
	PaymentMethodWireTransfer = "wire_transfer"
	PaymentMethodMoneyOrder   = "money_order"
	PaymentMethodCheck        = "check"
	PaymentMethodOther        = "other"
)

Payment method constants.

View Source
const (
	ChargeInvoiceOriginPurchase        = "purchase"
	ChargeInvoiceOriginRenewal         = "renewal"
	ChargeInvoiceOriginImmediateChange = "immediate_change"
	ChargeInvoiceOriginTermination     = "termination"
	CreditInvoiceOriginGiftCard        = "gift_card"
	CreditInvoiceOriginRefund          = "refund"
	CreditInvoiceOriginCredit          = "credit"
	CreditInvoiceOriginWriteOff        = "write_off"
	CreditInvoiceOriginExternalCredit  = "external_credit"
)

Invoice origin constants.

View Source
const (
	InvoiceTypeCharge = "charge"
	InvoiceTypeCredit = "credit"
	InvoiceTypeLegacy = "legacy" // all invoices prior to change have type legacy
)

Invoice type constants.

View Source
const (
	VoidRefundMethodTransactionFirst = "transaction_first"
	VoidRefundMethodCreditFirst      = "credit_first"
)

Refund constants.

View Source
const (
	ItemStateActive = "active"
	ItemStateClosed = "closed"
)

Item constants.

View Source
const (
	RedemptionStateActive   = "active"
	RedemptionStateInactive = "inactive"
)

Redemptions constants.

View Source
const (
	SubscriptionStateActive   = "active"
	SubscriptionStateCanceled = "canceled"
	SubscriptionStateExpired  = "expired"
	SubscriptionStateFuture   = "future"
	SubscriptionStateInTrial  = "in_trial"
	SubscriptionStateLive     = "live"
	SubscriptionStatePastDue  = "past_due"
	SubscriptionStatePaused   = "paused"
)

Subscription state constants. https://docs.recurly.com/docs/subscriptions

View Source
const (
	TransactionStatusSuccess = "success"
	TransactionStatusFailed  = "failed"
	TransactionStatusVoid    = "void"
)

Transaction constants. https://docs.recurly.com/docs/transactions

View Source
const DateTimeFormat = "2006-01-02T15:04:05Z07:00"

DateTimeFormat is the format Recurly uses to represent datetimes.

Variables

This section is empty.

Functions

func NewTestServer

func NewTestServer() (*Client, *TestServer)

NewTestServer returns an instance of *Client and *Server, with the client resolving to the test server.

Example
package main

import (
	"context"
	"fmt"
	"net/http"

	"github.com/blacklightcms/recurly"
)

func main() {
	client, s := recurly.NewTestServer()
	defer s.Close()

	// NOTE: This example doesn't have access to *testing.T so it passes nil
	// as the last argument to s.HandlFunc(). When setting up your tests,
	// be sure to pass *testing.T instead of nil.
	s.HandleFunc("GET", "/v2/accounts/1", func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusOK)
		w.Write([]byte(`
		<?xml version="1.0" encoding="UTF-8"?>
		<account href="https://your-subdomain.recurly.com/v2/accounts/1">
		   <email>verena@example.com</email>
		   <first_name>Verena</first_name>
		   <last_name>Example</last_name>
		</account>
		`))
	}, nil)

	a, _ := client.Accounts.Get(context.Background(), "1")
	fmt.Printf("%t\n", s.Invoked)
	fmt.Printf("%t\n", a.FirstName == "Verena")
	fmt.Printf("%t\n", a.LastName == "Example")
	fmt.Printf("%t\n", a.Email == "verena@example.com")

}
Output:

true
true
true
true

Types

type AVSResult

type AVSResult struct {
	NullMarshal
	Code    string `xml:"code,attr"`
	Message string `xml:",innerxml"`
}

AVSResult holds transaction results for address verification. http://developer.authorize.net/tools/errorgenerationguide/

type Account

type Account struct {
	XMLName                 xml.Name           `xml:"account"`
	Code                    string             `xml:"account_code,omitempty"`
	State                   string             `xml:"state,omitempty"`
	Username                string             `xml:"username,omitempty"`
	Email                   string             `xml:"email,omitempty"`
	CCEmails                []string           `xml:"cc_emails,omitempty"`
	FirstName               string             `xml:"first_name,omitempty"`
	LastName                string             `xml:"last_name,omitempty"`
	BillingInfo             *Billing           `xml:"billing_info,omitempty"`
	CompanyName             string             `xml:"company_name,omitempty"`
	VATNumber               string             `xml:"vat_number,omitempty"`
	TaxExempt               NullBool           `xml:"tax_exempt,omitempty"`
	Address                 *Address           `xml:"address,omitempty"`
	ShippingAddresses       *[]ShippingAddress `xml:"shipping_addresses>shipping_address,omitempty"`
	AcceptLanguage          string             `xml:"accept_language,omitempty"`
	HostedLoginToken        string             `xml:"hosted_login_token,omitempty"`
	CreatedAt               NullTime           `xml:"created_at,omitempty"`
	UpdatedAt               NullTime           `xml:"updated_at,omitempty"`
	ClosedAt                NullTime           `xml:"closed_at,omitempty"`
	HasLiveSubscription     NullBool           `xml:"has_live_subscription,omitempty"`
	HasActiveSubscription   NullBool           `xml:"has_active_subscription,omitempty"`
	HasFutureSubscription   NullBool           `xml:"has_future_subscription,omitempty"`
	HasCanceledSubscription NullBool           `xml:"has_canceled_subscription,omitempty"`
	HasPausedSubscription   NullBool           `xml:"has_paused_subscription,omitempty"`
	HasPastDueInvoice       NullBool           `xml:"has_past_due_invoice,omitempty"`
	PreferredLocale         string             `xml:"preferred_locale,omitempty"`
	CustomFields            *CustomFields      `xml:"custom_fields,omitempty"`
	TransactionType         string             `xml:"transaction_type,omitempty"` // Create only
}

An Account is core to managing your customers inside of Recurly. The account object stores the entire Recurly history of your customer and acts as the entry point for working with a customer's billing information, subscription data, transactions, invoices and more. https://dev.recurly.com/docs/account-object

type AccountBalance

type AccountBalance struct {
	XMLName xml.Name   `xml:"account_balance"`
	PastDue bool       `xml:"past_due"`
	Balance UnitAmount `xml:"balance_in_cents"`
}

AccountBalance is used for getting the account balance.

type AccountsService

type AccountsService interface {
	// List returns pager to paginate accounts. PagerOptions are used to optionally
	// filter the results.
	//
	// https://dev.recurly.com/docs/list-accounts
	List(opts *PagerOptions) Pager

	// Get retrieves an account. If the account does not exist,
	// a nil account and nil error is returned.
	//
	// https://dev.recurly.com/docs/get-account
	Get(ctx context.Context, accountCode string) (*Account, error)

	// Balance retrieves the balance for an account.
	//
	// https://dev.recurly.com/docs/lookup-account-balance
	Balance(ctx context.Context, accountCode string) (*AccountBalance, error)

	// Create creates a new account. You may optionally including billing information.
	//
	// https://dev.recurly.com/docs/create-an-account
	Create(ctx context.Context, a Account) (*Account, error)

	// Update updates an account. You may optionally including billing information.
	//
	// https://dev.recurly.com/docs/update-account
	Update(ctx context.Context, accountCode string, a Account) (*Account, error)

	// Close marks an account as closed and cancels any active subscriptions.
	// Paused subscriptions will be expired.
	//
	// https://dev.recurly.com/docs/close-account
	Close(ctx context.Context, accountCode string) error

	// Reopen transitions a closed account back to active.
	//
	// https://dev.recurly.com/docs/reopen-account
	Reopen(ctx context.Context, accountCode string) error

	// ListNotes returns a pager to paginate notes for an account. PagerOptions is used
	// to optionally filter the results.
	//
	// https://dev.recurly.com/docs/list-account-notes
	ListNotes(accountCode string, params *PagerOptions) Pager
}

AccountsService manages the interactions for accounts.

type AddOn

type AddOn struct {
	XMLName                     xml.Name   `xml:"add_on"`
	Code                        string     `xml:"add_on_code,omitempty"`
	Name                        string     `xml:"name,omitempty"`
	DefaultQuantity             NullInt    `xml:"default_quantity,omitempty"`
	DisplayQuantityOnHostedPage NullBool   `xml:"display_quantity_on_hosted_page,omitempty"`
	TaxCode                     string     `xml:"tax_code,omitempty"`
	UnitAmountInCents           UnitAmount `xml:"unit_amount_in_cents,omitempty"`
	AccountingCode              string     `xml:"accounting_code,omitempty"`
	ExternalSKU                 string     `xml:"external_sku,omitempty"`
	ItemState                   string     `xml:"item_state,omitempty"`
	ItemCode                    string     `xml:"item_code,omitempty"`
	TierType                    string     `xml:"tier_type,omitempty"`
	Tiers                       *[]Tier    `xml:"tiers>tier,omitempty"`

	// The following are only valid with an `Avalara for Communications` integration
	AvalaraTransactionType int `xml:"avalara_transaction_type,omitempty"`
	AvalaraServiceType     int `xml:"avalara_service_type,omitempty"`

	CreatedAt NullTime `xml:"created_at,omitempty"`
}

An AddOn is a charge billed each billing period in addition to a subscription’s base charge. Each plan may have one or more add-ons associated with it.

https://dev.recurly.com/docs/plan-add-ons-object

type AddOnsService

type AddOnsService interface {
	// List returns a pager to paginate add-ons for a plan. PagerOptions are used to
	// optionally filter the results.
	//
	// https://dev.recurly.com/docs/list-add-ons-for-a-plan
	List(planCode string, opts *PagerOptions) Pager

	// Get retrieves an add-on. If the add-on does not exist,
	// a nil add-on and nil error are returned.
	//
	// https://dev.recurly.com/docs/lookup-an-add-on
	Get(ctx context.Context, planCode string, code string) (*AddOn, error)

	// Create creates a new add-on to a plan.
	//
	// https://dev.recurly.com/docs/create-an-add-on
	Create(ctx context.Context, planCode string, a AddOn) (*AddOn, error)

	// Update updates the pricing information or description for an add-on.
	// Existing subscriptions with the add-on will not receive any pricing updates.
	//
	// https://dev.recurly.com/docs/update-an-add-on
	Update(ctx context.Context, planCode string, code string, a AddOn) (*AddOn, error)

	// Delete removes an add-on from a plan.
	//
	// https://dev.recurly.com/docs/delete-an-add-on
	Delete(ctx context.Context, planCode string, code string) error
}

AddOnsService manages the interactions for add-ons.

type Address

type Address struct {
	XMLName       xml.Name `xml:"address"`
	NameOnAccount string   `xml:"name_on_account,omitempty"`
	FirstName     string   `xml:"first_name,omitempty"`
	LastName      string   `xml:"last_name,omitempty"`
	Company       string   `xml:"company,omitempty"`
	Address       string   `xml:"address1,omitempty"`
	Address2      string   `xml:"address2,omitempty"`
	City          string   `xml:"city,omitempty"`
	State         string   `xml:"state,omitempty"`
	Zip           string   `xml:"zip,omitempty"`
	Country       string   `xml:"country,omitempty"`
	Phone         string   `xml:"phone,omitempty"`
}

Address is used for embedded addresses within other structs.

type Adjustment

type Adjustment struct {
	XMLName                xml.Name    `xml:"adjustment"`
	AccountCode            string      `xml:"-"` // Read only
	InvoiceNumber          int         `xml:"-"` // Read only
	SubscriptionUUID       string      `xml:"-"` // Read only
	UUID                   string      `xml:"uuid,omitempty"`
	State                  string      `xml:"state,omitempty"`
	Description            string      `xml:"description,omitempty"`
	AccountingCode         string      `xml:"accounting_code,omitempty"`
	RevenueScheduleType    string      `xml:"revenue_schedule_type,omitempty"`
	ProductCode            string      `xml:"product_code,omitempty"`
	Origin                 string      `xml:"origin,omitempty"`
	UnitAmountInCents      NullInt     `xml:"unit_amount_in_cents,omitempty"`
	Quantity               int         `xml:"quantity,omitempty"`
	OriginalAdjustmentUUID string      `xml:"original_adjustment_uuid,omitempty"`
	DiscountInCents        int         `xml:"discount_in_cents,omitempty"`
	TaxInCents             int         `xml:"tax_in_cents,omitempty"`
	TotalInCents           int         `xml:"total_in_cents,omitempty"`
	Currency               string      `xml:"currency"`
	TaxCode                string      `xml:"tax_code,omitempty"`
	TaxType                string      `xml:"tax_type,omitempty"`
	TaxRegion              string      `xml:"tax_region,omitempty"`
	TaxRate                float64     `xml:"tax_rate,omitempty"`
	TaxExempt              NullBool    `xml:"tax_exempt,omitempty"`
	TaxDetails             []TaxDetail `xml:"tax_details>tax_detail,omitempty"`

	// The following are only valid with an `Avalara for Communications` integration
	AvalaraTransactionType int `xml:"avalara_transaction_type,omitempty"`
	AvalaraServiceType     int `xml:"avalara_service_type,omitempty"`

	StartDate NullTime `xml:"start_date,omitempty"`
	EndDate   NullTime `xml:"end_date,omitempty"`
	CreatedAt NullTime `xml:"created_at,omitempty"`
	UpdatedAt NullTime `xml:"updated_at,omitempty"`
}

Adjustment works with charges and credits on a given account.

https://dev.recurly.com/docs/adjustment-object

func (Adjustment) MarshalXML

func (a Adjustment) MarshalXML(e *xml.Encoder, start xml.StartElement) error

MarshalXML marshals only the fields needed for creating/updating adjustments with the recurly API.

func (*Adjustment) UnmarshalXML

func (a *Adjustment) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

UnmarshalXML unmarshal an adjustment.

type AdjustmentsService

type AdjustmentsService interface {
	// List returns a pager to paginate adjustments for an account. PagerOptions are
	// used to optionally filter the results.
	//
	// https://dev.recurly.com/docs/list-an-accounts-adjustments
	ListAccount(accountCode string, opts *PagerOptions) Pager

	// Get retrieves an adjustment. If the add on does not exist,
	// a nil adjustment and nil error are returned.
	//
	// NOTE: Link below is from v2.9, the last documented version showing
	// this endpoint. The endpoint appears to still be valid in v2.19, waiting
	// to hear back from Recurly support.
	// https://dev.recurly.com/v2.9/docs/get-an-adjustment
	Get(ctx context.Context, uuid string) (*Adjustment, error)

	// Create creates a one-time charge on an account. Charges are not invoiced
	// or collected immediately. Non-invoiced charges will automatically be
	// invoiced when the account's subscription renews, or you trigger a
	// collection by posting an invoice. Charges may be removed from an account
	// if they have not been invoiced.
	//
	// For a charge, set a.UnitAmountInCents to a positive number.
	// For a credit, set a.UnitAmountInCents to a negative amount.
	//
	// https://dev.recurly.com/docs/create-a-charge
	// https://dev.recurly.com/docs/create-a-credit
	Create(ctx context.Context, accountCode string, a Adjustment) (*Adjustment, error)

	// Delete deletes an adjustment from an account. Only non-invoiced adjustments
	// can be deleted.
	//
	// https://dev.recurly.com/docs/delete-an-adjustment
	Delete(ctx context.Context, uuid string) error
}

AdjustmentsService manages the interactions for adjustments.

type AutomatedExport

type AutomatedExport struct {
	XMLName     xml.Name `xml:"export_file"`
	ExpiresAt   NullTime `xml:"expires_at,omitempty"`
	DownloadURL string   `xml:"download_url,omitempty"`
}

AutomatedExport holds export file info.

type AutomatedExportsService

type AutomatedExportsService interface {
	// Get retrieves export file.
	//
	// https://dev.recurly.com/docs/download-export-file
	Get(ctx context.Context, date time.Time, fileName string) (*AutomatedExport, error)

	// ListDates returns a list of dates with export files.
	//
	// https://dev.recurly.com/v2.8/docs/list-export-dates
	ListDates(opts *PagerOptions) Pager

	// ListFiles returns a list of files available for the date specified.
	//
	// https://dev.recurly.com/v2.8/docs/list-export-files
	ListFiles(date time.Time, opts *PagerOptions) Pager
}

AutomatedExportsService manages the interactions for automated exports.

type Billing

type Billing struct {
	XMLName          xml.Name `xml:"billing_info"`
	FirstName        string   `xml:"first_name,omitempty"`
	LastName         string   `xml:"last_name,omitempty"`
	Company          string   `xml:"company,omitempty"`
	Address          string   `xml:"address1,omitempty"`
	Address2         string   `xml:"address2,omitempty"`
	City             string   `xml:"city,omitempty"`
	State            string   `xml:"state,omitempty"`
	Zip              string   `xml:"zip,omitempty"`
	Country          string   `xml:"country,omitempty"`
	Phone            string   `xml:"phone,omitempty"`
	VATNumber        string   `xml:"vat_number,omitempty"`
	IPAddress        net.IP   `xml:"ip_address,omitempty"`
	IPAddressCountry string   `xml:"ip_address_country,omitempty"`
	PaymentType      string   `xml:"type,attr,omitempty"`

	// Credit Card Info
	FirstSix          string `xml:"first_six,omitempty"`
	LastFour          string `xml:"last_four,omitempty"`
	CardType          string `xml:"card_type,omitempty"`
	Number            int    `xml:"number,omitempty"`
	Month             int    `xml:"month,omitempty"`
	Year              int    `xml:"year,omitempty"`
	VerificationValue int    `xml:"verification_value,omitempty"` // Create/update only

	// Paypal
	PaypalAgreementID string `xml:"paypal_billing_agreement_id,omitempty"`

	// BrainTree
	BrainTreePaymentNonce string `xml:"braintree_payment_nonce,omitempty"`

	// Amazon
	AmazonAgreementID string `xml:"amazon_billing_agreement_id,omitempty"`
	AmazonRegion      string `xml:"amazon_region,omitempty"` // 'eu', 'us', or 'uk'

	// Bank Account
	NameOnAccount string `xml:"name_on_account,omitempty"`
	RoutingNumber string `xml:"routing_number,omitempty"`
	AccountNumber string `xml:"account_number,omitempty"`
	AccountType   string `xml:"account_type,omitempty"`

	ExternalHPPType                 string `xml:"external_hpp_type,omitempty"`                     // only usable with purchases API
	Currency                        string `xml:"currency,omitempty"`                              // Create/update only
	Token                           string `xml:"token_id,omitempty"`                              // Create/update only
	ThreeDSecureActionResultTokenID string `xml:"three_d_secure_action_result_token_id,omitempty"` // Create/update only
	TransactionType                 string `xml:"transaction_type,omitempty"`                      // Create only
}

Billing holds billing info for a single account.

func (Billing) Type

func (b Billing) Type() string

Type returns the billing info type. Returns either "", "bank", or an empty string.

type BillingService

type BillingService interface {
	// Get retrieves billing info for an account. If the account does not exist,
	// or the account does not have billing info, a nil billing struct and nil
	// error are returned.
	//
	// https://dev.recurly.com/docs/lookup-an-accounts-billing-info
	Get(ctx context.Context, accountCode string) (*Billing, error)

	// Create creates an account's billing info. To use the recurly.js token (recommended),
	// set b.Token and optionally b.Currency.
	// https://dev.recurly.com/docs/create-an-accounts-billing-info-token
	//
	// To create with credit card, bank info, or other, set the appropriate fields
	// on b. See the following links for specifics:
	// https://dev.recurly.com/docs/create-an-accounts-billing-info-credit-card
	// https://dev.recurly.com/docs/create-an-accounts-billing-info-bank-account
	// https://dev.recurly.com/docs/create-an-accounts-billing-info-using-external-token
	Create(ctx context.Context, accountCode string, b Billing) (*Billing, error)

	// Update updates an account's billing info. To use the recurly.js token (recommended),
	// set b.Token and optionally b.Currency.
	// https://dev.recurly.com/docs/update-an-accounts-billing-info-token
	//
	// To update with credit card, bank info, or other, set the appropriate fields
	// on b. See the following links for specifics:
	// https://dev.recurly.com/docs/update-an-accounts-billing-info-credit-card
	// https://dev.recurly.com/docs/update-an-accounts-billing-info-bank-account
	// https://dev.recurly.com/docs/update-an-accounts-billing-info-using-external-token
	Update(ctx context.Context, accountCode string, b Billing) (*Billing, error)

	// Clear removes stored billing information for an account. If the account has
	// a subscription, the renewal will go into past due unless you update the
	// billing info before the renewal occurs.
	//
	// https://dev.recurly.com/docs/clear-an-accounts-billing-info
	Clear(ctx context.Context, accountCode string) error
}

BillingService manages the interactions for billing.

type CVVResult

type CVVResult struct {
	NullMarshal
	Code    string `xml:"code,attr"`
	Message string `xml:",innerxml"`
}

CVVResult holds transaction results for CVV fields. https://www.chasepaymentech.com/card_verification_codes.html

type Client

type Client struct {

	// Client is the HTTP Client used to communicate with the API.
	// By default this uses http.DefaultClient, so there are no timeouts
	// configured. It's recommended you set your own HTTP client with
	// reasonable timeouts for your application.
	Client HTTPDoer

	// Services used for talking with different parts of the Recurly API
	Accounts          AccountsService
	Adjustments       AdjustmentsService
	AddOns            AddOnsService
	AutomatedExports  AutomatedExportsService
	Billing           BillingService
	Coupons           CouponsService
	CreditPayments    CreditPaymentsService
	Invoices          InvoicesService
	Plans             PlansService
	Purchases         PurchasesService
	Redemptions       RedemptionsService
	ShippingAddresses ShippingAddressesService
	ShippingMethods   ShippingMethodsService
	Subscriptions     SubscriptionsService
	Transactions      TransactionsService
	Items             ItemsService
	// contains filtered or unexported fields
}

Client manages communication with the Recurly API.

func NewClient

func NewClient(subdomain, apiKey string) *Client

NewClient returns a new instance of *Client. By default this uses http.DefaultClient, so there are no timeouts configured. It's recommended you set your own HTTP client with reasonable timeouts for your application.

Example
package main

import (
	"net/http"
	"time"

	"github.com/blacklightcms/recurly"
)

func main() {
	// Create a client pointing to https://your-subdomain.recurly.com
	client := recurly.NewClient("your-subdomain", "APIKEY")

	// Optionally overwrite the underlying HTTP client with your own
	client.Client = &http.Client{
		Timeout:   5 * time.Second,
		Transport: &http.Transport{},
	}
}
Output:

type ClientError

type ClientError struct {
	Response *http.Response

	// ValidationErrors holds an array of validation errors if any occurred.
	ValidationErrors []ValidationError
}

ClientError occurs when Recurly returns 400-499 status code. There are two known exceptions to this: 1) 429 Too Many Requests. See RateLimitError. 2) 422 Unprocessable Entity if a failed transaction occurred. See TransactionFailedError. All other 422 responses not related to failed transactions will return ClientError.

func (*ClientError) Error

func (e *ClientError) Error() string

func (*ClientError) Is

func (e *ClientError) Is(symbol string) bool

Is returns true if one of the validation errors has a matching symbol.

type CollectInvoice

type CollectInvoice struct {
	XMLName         xml.Name `xml:"invoice"`
	TransactionType string   `xml:"transaction_type,omitempty"` // Optional transaction type. Currently accepts "moto"
	BillingInfo     *Billing `xml:"billing_info,omitempty"`
}

CollectInvoice is used as the request body for collecting an invoice.

type Coupon

type Coupon struct {
	XMLName                  xml.Name    `xml:"coupon"`
	ID                       int64       `xml:"id,omitempty"`
	Code                     string      `xml:"coupon_code"`
	Type                     string      `xml:"coupon_type,omitempty"`
	Name                     string      `xml:"name"`
	RedemptionResource       string      `xml:"redemption_resource,omitempty"`
	State                    string      `xml:"state,omitempty"`
	AppliesToAllPlans        bool        `xml:"applies_to_all_plans,omitempty"`
	Duration                 string      `xml:"duration,omitempty"`
	DiscountType             string      `xml:"discount_type"`
	AppliesToNonPlanCharges  bool        `xml:"applies_to_non_plan_charges,omitempty"`
	Description              string      `xml:"description,omitempty"`
	InvoiceDescription       string      `xml:"invoice_description,omitempty"`
	DiscountPercent          NullInt     `xml:"discount_percent,omitempty"`
	DiscountInCents          *UnitAmount `xml:"discount_in_cents,omitempty"`
	RedeemByDate             NullTime    `xml:"redeem_by_date,omitempty"`
	MaxRedemptions           NullInt     `xml:"max_redemptions,omitempty"`
	CreatedAt                NullTime    `xml:"created_at,omitempty"`
	UpdatedAt                NullTime    `xml:"updated_at,omitempty"`
	DeletedAt                NullTime    `xml:"deleted_at,omitempty"`
	TemporalUnit             string      `xml:"temporal_unit,omitempty"`
	TemporalAmount           NullInt     `xml:"temporal_amount,omitempty"`
	MaxRedemptionsPerAccount NullInt     `xml:"max_redemptions_per_account,omitempty"`
	UniqueCodeTemplate       string      `xml:"unique_code_template,omitempty"`
	UniqueCouponCodeCount    NullInt     `xml:"unique_coupon_codes_count,omitempty"`
	PlanCodes                []string    `xml:"plan_codes>plan_code,omitempty"`
}

Coupon represents an individual coupon on your site.

type CouponRedemption

type CouponRedemption struct {
	XMLName          xml.Name `xml:"redemption"`
	AccountCode      string   `xml:"account_code"`                // required
	Currency         string   `xml:"currency"`                    // required
	SubscriptionUUID string   `xml:"subscription_uuid,omitempty"` // optional, redeem to subscription
}

CouponRedemption is used to redeem coupons.

type CouponsService

type CouponsService interface {
	// List returns a pager to paginate coupons. PagerOptions are used to optionally
	// filter the results.
	//
	// https://dev.recurly.com/docs/list-active-coupons
	List(opts *PagerOptions) Pager

	// Get retrieves a coupon. If the coupon does not exist,
	// a nil coupon and nil error are returned.
	//
	// https://dev.recurly.com/docs/lookup-a-coupon
	Get(ctx context.Context, code string) (*Coupon, error)

	// Create creates a new coupon. Please note: coupons cannot be updated
	// after being created.
	//
	// https://dev.recurly.com/docs/create-coupon
	Create(ctx context.Context, c Coupon) (*Coupon, error)

	// Update edits a redeemable coupon to extend redemption rules.
	// Only redeemable coupons can be edited an only certain fields can
	// be sent. See documentation for the list of valid fields.
	// Any fields provided outside of valid fields will be automatically
	// excluded before sending to Recurly.
	//
	// https://dev.recurly.com/docs/edit-coupon
	Update(ctx context.Context, code string, c Coupon) (*Coupon, error)

	// Restore restores an expired coupon so it can be redeemed again.
	// You can change editable fields in this call. See documentation for the
	// list of valid fields. Any fields provided outside of valid fields
	// will be automatically excluded before sending to Recurly.
	//
	// https://dev.recurly.com/docs/restore-coupon
	Restore(ctx context.Context, code string, c Coupon) (*Coupon, error)

	// Delete expires a coupon so customers can no longer redeem it.
	//
	// https://dev.recurly.com/docs/deactivate-coupon
	Delete(ctx context.Context, code string) error

	// Generate creates unique codes for a bulk coupon. A bulk coupon can
	// have up to 100,000 unique codes total. The generate endpoint allows
	// up to 200 unique codes at a time. The endpoint can be called
	// multiple times to create the number of coupon codes you need.
	//
	// The response will return a Pager to view the unique codes.
	// https://dev.recurly.com/docs/generate-unique-codes
	Generate(ctx context.Context, code string, n int) (Pager, error)
}

CouponsService manages the interactions for coupons.

type CreditPayment

type CreditPayment struct {
	XMLName                   xml.Name `xml:"credit_payment"`
	AccountCode               string   `xml:"-"`
	UUID                      string   `xml:"uuid"`
	Action                    string   `xml:"action"`
	Currency                  string   `xml:"currency"`
	AmountInCents             int      `xml:"amount_in_cents"`
	OriginalInvoiceNumber     int      `xml:"-"`
	AppliedToInvoice          int      `xml:"-"`
	OriginalCreditPaymentUUID string   `xml:"-"`
	RefundTransactionUUID     string   `xml:"-"`
	CreatedAt                 NullTime `xml:"created_at"`
	UpdatedAt                 NullTime `xml:"updated_at,omitempty"`
	VoidedAt                  NullTime `xml:"voided_at,omitempty"`
}

CreditPayment is a credit that has been applied to an invoice. This is a read-only object.

https://dev.recurly.com/docs/creditpayment-object

func (*CreditPayment) UnmarshalXML

func (c *CreditPayment) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

UnmarshalXML unmarshals invoices and handles intermediary state during unmarshaling for types like href.

type CreditPaymentsService

type CreditPaymentsService interface {
	// List returns a pager to paginate credit payments. PagerOptions are used to optionally
	// filter the results.
	//
	// https://dev.recurly.com/docs/list-credit-payments
	List(opts *PagerOptions) Pager

	// ListAccount returns a pager to paginate credit payments for an account.
	// PagerOptions are used to optionally filter the results.
	//
	// https://dev.recurly.com/docs/list-credit-payments
	ListAccount(accountCode string, opts *PagerOptions) Pager

	// Get retrieves a credit payment. If the credit payment does not exist,
	// a nil credit payment and nil error are returned.
	//
	// https://dev.recurly.com/docs/lookup-credit-payment
	Get(ctx context.Context, uuid string) (*CreditPayment, error)
}

CreditPaymentsService manages the interactions for credit payments.

type CustomFields

type CustomFields map[string]string

CustomFields represents custom key value pairs. Note that custom fields must be enabled on your Recurly site and must be added in the dashboard before they can be used.

func (CustomFields) MarshalXML

func (c CustomFields) MarshalXML(e *xml.Encoder, start xml.StartElement) error

MarshalXML marshals custom_fields.

func (*CustomFields) UnmarshalXML

func (c *CustomFields) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

UnmarshalXML unmarshals custom_fields.

type ExportDate

type ExportDate struct {
	XMLName xml.Name `xml:"export_date"`
	Date    string   `xml:"date,omitempty"`
}

ExportDate holds export date info.

type ExportFile

type ExportFile struct {
	XMLName xml.Name `xml:"export_file"`
	Name    string   `xml:"name,omitempty"`
}

ExportFile holds export file info.

type HTTPDoer

type HTTPDoer interface {
	Do(req *http.Request) (*http.Response, error)
}

HTTPDoer is used for making HTTP requests. This implementation is generally a *http.Client.

type Invoice

type Invoice struct {
	XMLName                 xml.Name        `xml:"invoice,omitempty"`
	AccountCode             string          `xml:"-"`
	Address                 Address         `xml:"-"`
	OriginalInvoiceNumber   int             `xml:"-"`
	UUID                    string          `xml:"-"`
	State                   string          `xml:"-"`
	InvoiceNumberPrefix     string          `xml:"-"`
	InvoiceNumber           int             `xml:"-"`
	PONumber                string          `xml:"po_number,omitempty"` // PostInvoice param
	VATNumber               string          `xml:"-"`
	DiscountInCents         int             `xml:"-"`
	SubtotalInCents         int             `xml:"-"`
	TaxInCents              int             `xml:"-"`
	TotalInCents            int             `xml:"-"`
	BalanceInCents          int             `xml:"-"`
	Currency                string          `xml:"-"`
	DueOn                   NullTime        `xml:"-"`
	CreatedAt               NullTime        `xml:"-"`
	UpdatedAt               NullTime        `xml:"-"`
	AttemptNextCollectionAt NullTime        `xml:"-"`
	ClosedAt                NullTime        `xml:"-"`
	Type                    string          `xml:"-"`
	Origin                  string          `xml:"-"`
	TaxType                 string          `xml:"-"`
	TaxRegion               string          `xml:"-"`
	TaxRate                 float64         `xml:"-"`
	NetTerms                NullInt         `xml:"net_terms,omitempty"`                // PostInvoice param
	CollectionMethod        string          `xml:"collection_method,omitempty"`        // PostInvoice param
	TermsAndConditions      string          `xml:"terms_and_conditions,omitempty"`     // PostInvoice param
	CustomerNotes           string          `xml:"customer_notes,omitempty"`           // PostInvoice param
	VatReverseChargeNotes   string          `xml:"vat_reverse_charge_notes,omitempty"` // PostInvoice param
	LineItems               []Adjustment    `xml:"-"`
	Transactions            []Transaction   `xml:"-"`
	CreditPayments          []CreditPayment `xml:"-"`

	// TaxDetails is only available if the site has the  `Avalara for Communications` integration
	TaxDetails *[]TaxDetail `xml:"tax_details>tax_detail,omitempty"`
}

Invoice is an individual invoice for an account. Transactions are guaranteed to be sorted from oldest to newest by date. The only fields annotated with XML tags are those for posting an invoice. Unmarshaling an invoice is handled by the custom UnmarshalXML function.

func (*Invoice) UnmarshalXML

func (i *Invoice) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

UnmarshalXML unmarshals invoices and handles intermediary state during unmarshaling for types like href.

type InvoiceCollection

type InvoiceCollection struct {
	XMLName        xml.Name  `xml:"invoice_collection"`
	ChargeInvoice  *Invoice  `xml:"-"`
	CreditInvoices []Invoice `xml:"-"`
}

InvoiceCollection is the data type returned from Preview, Post, MarkFailed, and inside PreviewSubscription, and PreviewSubscriptionChange.

func (*InvoiceCollection) UnmarshalXML

func (i *InvoiceCollection) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

UnmarshalXML unmarshals invoices and handles intermediary state during unmarshaling for types like href.

type InvoiceLineItemsRefund

type InvoiceLineItemsRefund struct {
	XMLName   xml.Name       `xml:"invoice"`
	LineItems []VoidLineItem `xml:"line_items>adjustment"`
	InvoiceRefund
}

InvoiceLineItemsRefund is used to refund one or more line items on an invoice.

type InvoiceRefund

type InvoiceRefund struct {
	XMLName             xml.Name `xml:"invoice"`
	AmountInCents       NullInt  `xml:"amount_in_cents,omitempty"` // If left empty the remaining refundable amount will be refunded
	RefundMethod        string   `xml:"refund_method,omitempty"`
	ExternalRefund      NullBool `xml:"external_refund,omitempty"`
	CreditCustomerNotes string   `xml:"credit_customer_notes,omitempty"`
	PaymentMethod       string   `xml:"payment_method,omitempty"`
	Description         string   `xml:"description,omitempty"`
	RefundedAt          NullTime `xml:"refunded_at,omitempty"`
}

InvoiceRefund is used to refund invoices.

type InvoicesService

type InvoicesService interface {
	// List returns a pager to paginate invoices. PagerOptions are used to optionally
	// filter the results.
	//
	// https://dev.recurly.com/docs/list-invoices
	List(opts *PagerOptions) Pager

	// ListAccount returns a pager to paginate invoices for an account. Params
	// are used to optionally filter the results.
	//
	// https://dev.recurly.com/docs/list-an-accounts-invoices
	ListAccount(accountCode string, opts *PagerOptions) Pager

	// Get retrieves an invoice. If the invoice does not exist,
	// a nil invoice and nil error are returned.
	//
	// https://dev.recurly.com/docs/lookup-invoice-details
	Get(ctx context.Context, invoiceNumber int) (*Invoice, error)

	// GetPDF retrieves an invoice as a PDF. If the invoice does not exist,
	// a nil bytes.Buffer and nil error are returned. If language is not provided
	// or not valid, English will be used.
	//
	// https://dev.recurly.com/docs/retrieve-a-pdf-invoice
	GetPDF(ctx context.Context, invoiceNumber int, language string) (*bytes.Buffer, error)

	// Preview allows you to display the invoice details, including estimated
	// tax, before you post it.
	//
	// https://dev.recurly.com/docs/preview-an-invoice
	Preview(ctx context.Context, accountCode string) (*Invoice, error)

	// Create posts an invoice with pending adjustments to the account.
	// See Recurly's documentation for details.
	//
	// https://dev.recurly.com/docs/post-an-invoice-invoice-pending-charges-on-an-acco
	Create(ctx context.Context, accountCode string, invoice Invoice) (*Invoice, error)

	// Collect allows collecting a past-due or pending invoice. This API
	// is rate limited. See Recurly's documentation for details.
	//
	// https://dev.recurly.com/docs/collect-an-invoice
	Collect(ctx context.Context, invoiceNumber int, collectInvoice CollectInvoice) (*Invoice, error)

	// MarkPaid marks an invoice as paid successfully.
	//
	// https://dev.recurly.com/docs/mark-an-invoice-as-paid-successfully
	MarkPaid(ctx context.Context, invoiceNumber int) (*Invoice, error)

	// MarkFailed marks an invoice as failed collection.
	//
	// https://dev.recurly.com/docs/mark-an-invoice-as-failed-collection
	MarkFailed(ctx context.Context, invoiceNumber int) (*Invoice, error)

	// RefundVoidLineItems allows specific invoice line items and/or quantities to
	// be refunded and generates a refund invoice. Full amount line item refunds
	//of invoices with an unsettled transaction will voide the transaction and
	// generate a void invoice. See Recurly's documentation for details.
	//
	// https://dev.recurly.com/docs/line-item-refunds
	RefundVoidLineItems(ctx context.Context, invoiceNumber int, refund InvoiceLineItemsRefund) (*Invoice, error)

	// RefundVoidOpenAmount allows custom invoice amounts to be refunded and
	// generates a refund invoice. Full open amount refunds of invoices with
	// an unsettled transaction will void the transaction and generate a
	// void invoice. See Recurly's documentation for details.
	//
	// https://dev.recurly.com/docs/open-amount-refunds
	RefundVoidOpenAmount(ctx context.Context, invoiceNumber int, refund InvoiceRefund) (*Invoice, error)

	// VoidCreditInvoice voids an open credit invoice.
	//
	// https://dev.recurly.com/docs/void-credit-invoice
	VoidCreditInvoice(ctx context.Context, invoiceNumber int) (*Invoice, error)

	// RecordPayment records an offline payment for a manual invoice, such as a check
	// or money order.
	//
	// https://dev.recurly.com/docs/enter-an-offline-payment-for-a-manual-invoice
	RecordPayment(ctx context.Context, offlinePayment OfflinePayment) (*Transaction, error)
}

InvoicesService manages the interactions for invoices.

type Item

type Item struct {
	XMLName        xml.Name      `xml:"item"`
	Code           string        `xml:"item_code,omitempty"`
	Name           string        `xml:"name,omitempty"`
	Description    string        `xml:"description,omitempty"`
	ExternalSKU    string        `xml:"external_sku,omitempty"`
	AccountingCode string        `xml:"accounting_code,omitempty"`
	TaxExempt      NullBool      `xml:"tax_exempt,omitempty"`
	State          string        `xml:"state,omitempty"`
	CustomFields   *CustomFields `xml:"custom_fields,omitempty"`

	// The following are only valid with an `Avalara for Communications` integration
	AvalaraTransactionType int `xml:"avalara_transaction_type,omitempty"`
	AvalaraServiceType     int `xml:"avalara_service_type,omitempty"`

	CreatedAt NullTime `xml:"created_at,omitempty"`
	UpdatedAt NullTime `xml:"updated_at,omitempty"`
	DeletedAt NullTime `xml:"deleted_at,omitempty"`
}

If you sell standard offerings or combinations of offerings to many customers, organizing those in a Recurly catalog provides many benefits. You'll experience faster charge creation, easier management of offerings, and analytics about your offerings across all sales channels. Because your offerings may be physical, digital, or service-oriented, Recurly collectively calls these "Items".

type ItemsService

type ItemsService interface {
	// List returns pager to paginate items. PagerOptions are used to optionally
	// filter the results.
	//
	// https://dev.recurly.com/docs/list-items
	List(opts *PagerOptions) Pager

	// Get retrieves an item. If the item does not exist,
	// a nil item and nil error is returned.
	//
	// https://dev.recurly.com/docs/lookup-item
	Get(ctx context.Context, itemCode string) (*Item, error)

	// Create creates a new item.
	//
	// https://dev.recurly.com/docs/create-item
	Create(ctx context.Context, a Item) (*Item, error)

	// Update updates an item.
	//
	// https://dev.recurly.com/docs/update-item
	Update(ctx context.Context, itemCode string, a Item) (*Item, error)

	// Deactivates an item.
	//
	// https://dev.recurly.com/docs/delete-item
	Deactivate(ctx context.Context, itemCode string) error
}

ItemsService manages the interactions for items.

type NestedPlan

type NestedPlan struct {
	Code string `xml:"plan_code,omitempty"`
	Name string `xml:"name,omitempty"`
}

type NewSubscription

type NewSubscription struct {
	XMLName                 xml.Name             `xml:"subscription"`
	PlanCode                string               `xml:"plan_code"`
	Account                 Account              `xml:"account"`
	SubscriptionAddOns      *[]SubscriptionAddOn `xml:"subscription_add_ons>subscription_add_on,omitempty"`
	CouponCode              string               `xml:"coupon_code,omitempty"`
	UnitAmountInCents       NullInt              `xml:"unit_amount_in_cents,omitempty"`
	Currency                string               `xml:"currency"`
	Quantity                int                  `xml:"quantity,omitempty"`
	TrialEndsAt             NullTime             `xml:"trial_ends_at,omitempty"`
	StartsAt                NullTime             `xml:"starts_at,omitempty"`
	TotalBillingCycles      int                  `xml:"total_billing_cycles,omitempty"`
	RenewalBillingCycles    NullInt              `xml:"renewal_billing_cycles"`
	NextBillDate            NullTime             `xml:"next_bill_date,omitempty"`
	CollectionMethod        string               `xml:"collection_method,omitempty"`
	AutoRenew               bool                 `xml:"auto_renew,omitempty"`
	NetTerms                NullInt              `xml:"net_terms,omitempty"`
	PONumber                string               `xml:"po_number,omitempty"`
	Bulk                    bool                 `xml:"bulk,omitempty"`
	TermsAndConditions      string               `xml:"terms_and_conditions,omitempty"`
	CustomerNotes           string               `xml:"customer_notes,omitempty"`
	VATReverseChargeNotes   string               `xml:"vat_reverse_charge_notes,omitempty"`
	BankAccountAuthorizedAt NullTime             `xml:"bank_account_authorized_at,omitempty"`
	RevenueScheduleType     string               `xml:"revenue_schedule_type,omitempty"`
	ShippingAddress         *ShippingAddress     `xml:"shipping_address,omitempty"`
	ShippingAddressID       int64                `xml:"shipping_address_id,omitempty"`
	ImportedTrial           NullBool             `xml:"imported_trial,omitempty"`
	GatewayCode             string               `xml:"gateway_code,omitempty"`
	ShippingMethodCode      string               `xml:"shipping_method_code,omitempty"`
	ShippingAmountInCents   NullInt              `xml:"shipping_amount_in_cents,omitempty"`
	CustomFields            *CustomFields        `xml:"custom_fields,omitempty"`
	TransactionType         string               `xml:"transaction_type,omitempty"` // Optional transaction type. Currently accepts "moto"
}

NewSubscription is used to create new subscriptions.

type Note

type Note struct {
	XMLName   xml.Name  `xml:"note"`
	Message   string    `xml:"message,omitempty"`
	CreatedAt time.Time `xml:"created_at,omitempty"`
}

Note holds account notes.

type NullBool

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

NullBool is able to marshal or unmarshal bools to XML in order to differentiate between false as a value and false as a zero-value.

Example
package main

import (
	"fmt"

	"github.com/blacklightcms/recurly"
)

func main() {
	b := recurly.NewBool(true)
	fmt.Println(b.Bool())

	value, ok := b.Value()
	fmt.Println(value, ok)

}
Output:

true
true true
Example (Invalid)
package main

import (
	"fmt"

	"github.com/blacklightcms/recurly"
)

func main() {
	var b recurly.NullBool
	fmt.Println(b.Bool())

	value, ok := b.Value()
	fmt.Println(value, ok)

}
Output:

false
false false

func NewBool

func NewBool(b bool) NullBool

NewBool returns NullBool with a valid value of b.

func NewBoolPtr

func NewBoolPtr(b *bool) NullBool

NewBoolPtr returns a new bool from a pointer.

func (NullBool) Bool

func (n NullBool) Bool() bool

Bool returns the bool value, regardless of validity. Use Value() if you need to know whether the value is valid.

func (NullBool) BoolPtr

func (n NullBool) BoolPtr() *bool

BoolPtr returns a pointer to the bool value, or nil if the value is not valid.

func (NullBool) Equal

func (n NullBool) Equal(v NullBool) bool

Equal compares the equality of two NullBools.

func (NullBool) MarshalJSON

func (n NullBool) MarshalJSON() ([]byte, error)

MarshalJSON marshals a bool based on whether valid is true.

func (NullBool) MarshalXML

func (n NullBool) MarshalXML(e *xml.Encoder, start xml.StartElement) error

MarshalXML marshals NullBools to XML. Otherwise nothing is marshaled.

func (*NullBool) UnmarshalXML

func (n *NullBool) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

UnmarshalXML unmarshals an bool properly, as well as marshaling an empty string to nil.

func (NullBool) Value

func (n NullBool) Value() (value bool, ok bool)

Value returns the value of NullBool. The value should only be considered valid if ok returns true.

type NullInt

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

NullInt is used for properly handling int types that could be null.

Example
package main

import (
	"fmt"

	"github.com/blacklightcms/recurly"
)

func main() {
	i := recurly.NewInt(100)
	fmt.Println(i.Int())

	value, ok := i.Value()
	fmt.Println(value, ok)

}
Output:

100
100 true
Example (Invalid)
package main

import (
	"fmt"

	"github.com/blacklightcms/recurly"
)

func main() {
	var i recurly.NullInt
	fmt.Println(i.Int())

	value, ok := i.Value()
	fmt.Println(value, ok)

}
Output:

0
0 false

func NewInt

func NewInt(i int) NullInt

NewInt returns NullInt with a valid value of i.

func NewIntPtr

func NewIntPtr(i *int) NullInt

NewIntPtr returns a new bool from a pointer.

func (NullInt) Equal

func (n NullInt) Equal(v NullInt) bool

Equal compares the equality of two NullInt.

func (NullInt) Int

func (n NullInt) Int() int

Int returns the int value, regardless of validity. Use Value() if you need to know whether the value is valid.

func (NullInt) IntPtr

func (n NullInt) IntPtr() *int

IntPtr returns a pointer to the int value, or nil if the value is not valid.

func (NullInt) MarshalJSON

func (n NullInt) MarshalJSON() ([]byte, error)

MarshalJSON marshals an int based on whether valid is true.

func (NullInt) MarshalXML

func (n NullInt) MarshalXML(e *xml.Encoder, start xml.StartElement) error

MarshalXML marshals NullInts greater than zero to XML. Otherwise nothing is marshaled.

func (*NullInt) UnmarshalXML

func (n *NullInt) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

UnmarshalXML unmarshals an int properly, as well as marshaling an empty string to nil.

func (NullInt) Value

func (n NullInt) Value() (value int, ok bool)

Value returns the value of NullInt. The value should only be considered valid if ok returns true.

type NullMarshal

type NullMarshal struct{}

NullMarshal can be embedded in structs that are read-only or just should never be marshaled

func (NullMarshal) MarshalXML

func (nm NullMarshal) MarshalXML(e *xml.Encoder, start xml.StartElement) error

MarshalXML ensures that nullMarshal doesn't marshal any xml.

type NullTime

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

NullTime is used for properly handling time.Time types that could be null.

Example
package main

import (
	"fmt"
	"time"

	"github.com/blacklightcms/recurly"
)

func main() {
	t := recurly.NewTime(time.Date(2018, 5, 13, 0, 0, 0, 0, time.UTC))
	fmt.Println(t.Time())

	value, ok := t.Value()
	fmt.Println(value, ok)

}
Output:

2018-05-13 00:00:00 +0000 UTC
2018-05-13 00:00:00 +0000 UTC true
Example (Invalid)
package main

import (
	"fmt"

	"github.com/blacklightcms/recurly"
)

func main() {
	var t recurly.NullTime
	fmt.Println(t.Time())

	value, ok := t.Value()
	fmt.Println(value, ok)

}
Output:

0001-01-01 00:00:00 +0000 UTC
0001-01-01 00:00:00 +0000 UTC false

func NewTime

func NewTime(t time.Time) NullTime

NewTime returns NullTime with a valid value of t. The NullTime value will be considered invalid if t.IsZero() returns true.

func NewTimePtr

func NewTimePtr(t *time.Time) NullTime

NewTimePtr returns NullTime from a pointer.

func (NullTime) Equal

func (n NullTime) Equal(v NullTime) bool

Equal compares the equality of two NullTime.

func (NullTime) MarshalJSON

func (n NullTime) MarshalJSON() ([]byte, error)

MarshalJSON method has to be added here due to embeded interface json marshal issue in Go with panic on nil time field

func (NullTime) MarshalXML

func (n NullTime) MarshalXML(e *xml.Encoder, start xml.StartElement) error

MarshalXML marshals times into their proper format. Otherwise nothing is marshaled. All times are sent in UTC.

func (NullTime) String

func (n NullTime) String() string

String returns a string representation of the time in UTC using the DateTimeFormat constant as the format.

func (NullTime) Time

func (n NullTime) Time() time.Time

Time returns the time value, regardless of validity. Use Value() if you need to know whether the value is valid.

func (NullTime) TimePtr

func (n NullTime) TimePtr() *time.Time

TimePtr returns a pointer to the time.Time value, or nil if the value is not valid.

func (*NullTime) UnmarshalXML

func (n *NullTime) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

UnmarshalXML unmarshals an int properly, as well as marshaling an empty string to nil.

func (NullTime) Value

func (n NullTime) Value() (value time.Time, ok bool)

Value returns the value of NullTime. The value should only be considered valid if ok returns true.

type OfflinePayment

type OfflinePayment struct {
	XMLName       xml.Name `xml:"transaction"`
	InvoiceNumber int      `xml:"-"`
	PaymentMethod string   `xml:"payment_method"`
	CollectedAt   NullTime `xml:"collected_at,omitempty"`
	Amount        int      `xml:"amount_in_cents,omitempty"`
	Description   string   `xml:"description,omitempty"`
}

OfflinePayment is a payment received outside of Recurly (e.g. ACH/Wire).

type Pager

type Pager interface {
	// Count returns a total count of the request. Calling this function
	// more than once will return the value from the first call.
	Count(ctx context.Context) (int, error)

	// Next returns true if there is a next result expected, or false if
	// there is no next result.
	Next() bool

	// Cursor returns the next cursor (if available).
	Cursor() string

	// Fetch fetches results of a single page and populates dst with the results.
	// For use in a for loop with Next().
	Fetch(ctx context.Context, dst interface{}) error

	// FetchAll fetches all of the pages recurly has available for the result
	// set and populates dst with the results.
	FetchAll(ctx context.Context, dst interface{}) error
}

Pager paginates records.

type PagerOptions

type PagerOptions struct {
	// Results per page. If not provided, Recurly defaults to 50.
	PerPage int

	// The field to sort by (e.g. created_at). See Recurly's documentation.
	Sort string

	// asc or desc
	Order string

	// Returns records greater than or equal to BeginTime.
	BeginTime NullTime

	// Returns records less than or equal to EndTime.
	EndTime NullTime

	State string // supported by some endpoints. Check Recurly's documenation.
	Type  string // supported by some endpoints. Check Recurly's documentation.

	// Cursor is set internally by the library. If you are paginating
	// records non-consecutively and obtained the next cursor, you can set it
	// as the starting cursor here to continue where you left off.
	//
	// Use Pager.Cursor() to obtain the next cursor.
	Cursor string
	// contains filtered or unexported fields
}

PagerOptions are used to send pagination parameters with paginated requests.

type PendingSubscription

type PendingSubscription struct {
	XMLName            xml.Name            `xml:"pending_subscription"`
	Plan               NestedPlan          `xml:"plan,omitempty"`
	UnitAmountInCents  int                 `xml:"unit_amount_in_cents,omitempty"`
	Quantity           int                 `xml:"quantity,omitempty"` // Quantity of subscriptions
	SubscriptionAddOns []SubscriptionAddOn `xml:"subscription_add_ons>subscription_add_on,omitempty"`
}

PendingSubscription are updates to the subscription or subscription add ons that will be made on the next renewal.

type Plan

type Plan struct {
	XMLName                    xml.Name   `xml:"plan"`
	Code                       string     `xml:"plan_code,omitempty"`
	Name                       string     `xml:"name"`
	Description                string     `xml:"description,omitempty"`
	SuccessURL                 string     `xml:"success_url,omitempty"`
	CancelURL                  string     `xml:"cancel_url,omitempty"`
	DisplayDonationAmounts     NullBool   `xml:"display_donation_amounts,omitempty"`
	DisplayQuantity            NullBool   `xml:"display_quantity,omitempty"`
	DisplayPhoneNumber         NullBool   `xml:"display_phone_number,omitempty"`
	BypassHostedConfirmation   NullBool   `xml:"bypass_hosted_confirmation,omitempty"`
	UnitName                   string     `xml:"unit_name,omitempty"`
	PaymentPageTOSLink         string     `xml:"payment_page_tos_link,omitempty"`
	IntervalUnit               string     `xml:"plan_interval_unit,omitempty"`
	IntervalLength             int        `xml:"plan_interval_length,omitempty"`
	TrialIntervalUnit          string     `xml:"trial_interval_unit,omitempty"`
	TrialIntervalLength        int        `xml:"trial_interval_length,omitempty"`
	TotalBillingCycles         NullInt    `xml:"total_billing_cycles,omitempty"`
	AccountingCode             string     `xml:"accounting_code,omitempty"`
	CreatedAt                  NullTime   `xml:"created_at,omitempty"`
	TaxExempt                  NullBool   `xml:"tax_exempt,omitempty"`
	TaxCode                    string     `xml:"tax_code,omitempty"`
	AutoRenew                  bool       `xml:"auto_renew,omitempty"`
	UnitAmountInCents          UnitAmount `xml:"unit_amount_in_cents"`
	SetupFeeInCents            UnitAmount `xml:"setup_fee_in_cents,omitempty"`
	AllowAnyItemOnSubscription NullBool   `xml:"allow_any_item_on_subscription,omitempty"`

	// The following are only valid with an `Avalara for Communications` integration
	AvalaraTransactionType int `xml:"avalara_transaction_type,omitempty"`
	AvalaraServiceType     int `xml:"avalara_service_type,omitempty"`
}

Plan tells Recurly how often and how much to charge your customers.

type PlansService

type PlansService interface {
	// List returns a pager to paginate plans. PagerOptions are used to optionally
	// filter the results.
	//
	// https://dev.recurly.com/docs/list-plans
	List(opts *PagerOptions) Pager

	// Get retrieves a plan. If the plan does not exist,
	// a nil plan and nil error are returned.
	//
	// https://dev.recurly.com/docs/lookup-plan-details
	Get(ctx context.Context, code string) (*Plan, error)

	// Create a new subscription plan.
	//
	// https://dev.recurly.com/docs/create-plan
	Create(ctx context.Context, p Plan) (*Plan, error)

	// Update the pricing or details for a plan. Existing subscriptions will
	// remain at the previous renewal amounts.
	//
	// https://dev.recurly.com/docs/update-plan
	Update(ctx context.Context, code string, p Plan) (*Plan, error)

	// Delete makes a plan inactive. New subscriptions cannot be created
	// from inactive plans.
	//
	// https://dev.recurly.com/docs/delete-plan
	Delete(ctx context.Context, code string) error
}

PlansService manages the interactions for plans.

type Purchase

type Purchase struct {
	XMLName               xml.Name               `xml:"purchase"`
	Account               Account                `xml:"account,omitempty"`
	Adjustments           []Adjustment           `xml:"adjustments>adjustment,omitempty"`
	CollectionMethod      string                 `xml:"collection_method,omitempty"`
	Currency              string                 `xml:"currency"`
	PONumber              string                 `xml:"po_number,omitempty"`
	NetTerms              NullInt                `xml:"net_terms,omitempty"`
	GiftCard              string                 `xml:"gift_card>redemption_code,omitempty"`
	CouponCodes           []string               `xml:"coupon_codes>coupon_code,omitempty"`
	Subscriptions         []PurchaseSubscription `xml:"subscriptions>subscription,omitempty"`
	CustomerNotes         string                 `xml:"customer_notes,omitempty"`
	TermsAndConditions    string                 `xml:"terms_and_conditions,omitempty"`
	VATReverseChargeNotes string                 `xml:"vat_reverse_charge_notes,omitempty"`
	ShippingAddressID     int64                  `xml:"shipping_address_id,omitempty"`
	GatewayCode           string                 `xml:"gateway_code,omitempty"`
	ShippingFees          *[]ShippingFee         `xml:"shipping_fees>shipping_fee,omitempty"`
	TransactionType       string                 `xml:"transaction_type,omitempty"` // Create only
}

Purchase represents an individual checkout holding at least one subscription OR one adjustment. NOTE: Adjustments cannot contain a Currency field. Use Purchase.Currency instead.

type PurchaseSubscription

type PurchaseSubscription struct {
	XMLName               xml.Name             `xml:"subscription"`
	PlanCode              string               `xml:"plan_code"`
	SubscriptionAddOns    *[]SubscriptionAddOn `xml:"subscription_add_ons>subscription_add_on,omitempty"`
	UnitAmountInCents     NullInt              `xml:"unit_amount_in_cents,omitempty"`
	Quantity              int                  `xml:"quantity,omitempty"`
	TrialEndsAt           NullTime             `xml:"trial_ends_at,omitempty"`
	StartsAt              NullTime             `xml:"starts_at,omitempty"`
	TotalBillingCycles    int                  `xml:"total_billing_cycles,omitempty"`
	RenewalBillingCycles  NullInt              `xml:"renewal_billing_cycles,omitempty"`
	NextBillDate          NullTime             `xml:"next_bill_date,omitempty"`
	AutoRenew             bool                 `xml:"auto_renew,omitempty"`
	CustomFields          *CustomFields        `xml:"custom_fields,omitempty"`
	ShippingAddress       *ShippingAddress     `xml:"shipping_address,omitempty"`
	ShippingAddressID     int64                `xml:"shipping_address_id,omitempty"`
	ShippingMethodCode    string               `xml:"shipping_method_code,omitempty"`
	ShippingAmountInCents NullInt              `xml:"shipping_amount_in_cents,omitempty"`
}

PurchaseSubscription represents a subscription to purchase some new subscription. This is different from the Subscription struct in that only fields allowed to be used with the purchases API are available.

type PurchasesService

type PurchasesService interface {
	// Create a purchase. See Recurly's documentation for more details.
	//
	// https://dev.recurly.com/docs/create-purchase
	Create(ctx context.Context, p Purchase) (*InvoiceCollection, error)

	// Preview a purchase. See Recurly's documentation for more details.
	//
	// https://dev.recurly.com/docs/preview-purchase
	Preview(ctx context.Context, p Purchase) (*InvoiceCollection, error)

	// Authorize creates a pending purchase that can be activated at a later
	// time once payment has been completed on an external source (e.g. Adyen's
	// Hosted Payment Pages).
	//
	// p.Account.Email and p.Account.Billing.ExternalHPPType appear to be required.
	//
	// https://dev.recurly.com/docs/authorize-purchase
	Authorize(ctx context.Context, p Purchase) (*Purchase, error)

	// Pending is used for Adyen HPP transaction requests. This runs the validations
	// but not the transactions. See Recurly's documentation for more info.
	//
	// https://dev.recurly.com/docs/pending-purchase
	Pending(ctx context.Context, p Purchase) (*Purchase, error)

	// Capture an open Authorization request. See Recurly's documentation
	// for details.
	//
	// https://dev.recurly.com/docs/capture-purchase
	Capture(ctx context.Context, transactionUUID string) (*InvoiceCollection, error)

	// Cancel an open Authorization request. See Recurly's documentation
	// for details.
	//
	// https://dev.recurly.com/docs/cancel-purchase
	Cancel(ctx context.Context, transactionUUID string) (*InvoiceCollection, error)
}

PurchasesService manages the interactions for a purchase involving at least one adjustment or one subscription.

type Rate

type Rate struct {
	// The total request limit during the 5 minute window (e.g. requests/min * 5 min)
	Limit int

	// The number of requests remaining until your requests will be denied.
	Remaining int

	// The time when the current window will completely reset assuming no further API requests are made.
	Reset time.Time
}

Rate represents the rate limit for the current client.

type RateLimitError

type RateLimitError struct {
	Response *http.Response

	Rate Rate // Rate specifies the last known rate limit for the client
}

RateLimitError occurs when Recurly returns a 429 Too Many Requests error.

func (*RateLimitError) Error

func (e *RateLimitError) Error() string

type Redemption

type Redemption struct {
	UUID                   string
	SubscriptionUUID       string // Only available if redeemed on a subscription
	AccountCode            string
	CouponCode             string
	SingleUse              bool
	TotalDiscountedInCents int
	Currency               string
	State                  string
	CreatedAt              NullTime
	UpdatedAt              NullTime
}

Redemption holds redeemed coupons for an account or invoice.

https://dev.recurly.com/docs/coupon-redemption-object

func (*Redemption) UnmarshalXML

func (r *Redemption) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

UnmarshalXML unmarshal a coupon redemption object. Minaly converts href links for coupons and accounts to CouponCode and AccountCodes.

type RedemptionsService

type RedemptionsService interface {
	// ListAccount returns a pager to paginate redemptions for an account.
	// PagerOptions are used to optionally filter the results.
	//
	// https://dev.recurly.com/docs/coupon-redemption-object
	ListAccount(accountCode string, opts *PagerOptions) Pager

	// ListInvoice returns a pager to paginate redemptions for an invoice.
	// PagerOptions are used to optionally filter the results.
	//
	// https://dev.recurly.com/docs/lookup-a-coupon-redemption-on-an-invoice
	ListInvoice(invoiceNumber int, opts *PagerOptions) Pager

	// ListInvoice returns a pager to paginate redemptions for an invoice.
	// PagerOptions are used to optionally filter the results.
	//
	// https://dev.recurly.com/docs/lookup-a-coupon-redemption-on-a-subscription
	ListSubscription(uuid string, opts *PagerOptions) Pager

	// Redeem redeems a coupon on an existing customer's account to apply to
	// their next invoice. r.AccountCode and r.Currency are required fields.
	// Set r.SubscriptionUUID to redeem the coupon to a subscription.
	//
	// NOTE: If you want the coupon redemption to be rejected if a subscription
	// signup fails, you must redeem the coupon within the Subscriptions.Create()
	// call.
	//
	// https://dev.recurly.com/docs/redeem-a-coupon-before-or-after-a-subscription
	// https://dev.recurly.com/docs/redeem-a-coupon-before-or-after-a-subscription
	Redeem(ctx context.Context, code string, r CouponRedemption) (*Redemption, error)

	// Delete manually expires a coupon redemption on an account. Please note:
	// the coupon redemption will still count towards the "maximum redemption total"
	// of the coupon. See Recurly's documentation for details.
	//
	// https://dev.recurly.com/docs/remove-a-coupon-from-an-account
	Delete(ctx context.Context, accountCode, redemptionUUID string) error
}

RedemptionsService manages the interactions for coupon redemptions.

type ServerError

type ServerError struct {
	Response *http.Response
}

ServerError occurs when Recurly returns 500-599 status code.

func (*ServerError) Error

func (e *ServerError) Error() string

type ShippingAddress

type ShippingAddress struct {
	XMLName   xml.Name `xml:"shipping_address"`
	ID        int64    `xml:"id,omitempty"`
	FirstName string   `xml:"first_name"`
	LastName  string   `xml:"last_name"`
	Nickname  string   `xml:"nickname,omitempty"`
	Address   string   `xml:"address1"`
	Address2  string   `xml:"address2,omitempty"`
	Company   string   `xml:"company,omitempty"`
	City      string   `xml:"city"`
	State     string   `xml:"state"`
	Zip       string   `xml:"zip"`
	Country   string   `xml:"country"`
	Phone     string   `xml:"phone,omitempty"`
	Email     string   `xml:"email,omitempty"`
	VATNumber string   `xml:"vat_number,omitempty"`
	CreatedAt NullTime `xml:"created_at,omitempty"`
	UpdatedAt NullTime `xml:"updated_at,omitempty"`
}

ShippingAddress represents a shipping address

type ShippingAddressesService

type ShippingAddressesService interface {
	// ListAccount returns a pager to paginate shipping addresses for an account.
	// PagerOptions are used to optionally filter the results.
	//
	// https://dev.recurly.com/docs/list-accounts-shipping-address
	ListAccount(accountCode string, opts *PagerOptions) Pager

	// Create creates a new shipping address on an existing account.
	// Note: A shipping address can also be created via Accounts.Create()
	// as well as Subscriptions.Create(). See Recurly's documentation for details.
	//
	// https://dev.recurly.com/docs/create-shipping-address-on-an-account
	Create(ctx context.Context, accountCode string, address ShippingAddress) (*ShippingAddress, error)

	// Update updates the shipping address on an account.
	//
	// https://dev.recurly.com/docs/edit-shipping-address-on-an-existing-account
	Update(ctx context.Context, accountCode string, shippingAddressID int, address ShippingAddress) (*ShippingAddress, error)

	// Delete removes an existing shipping address from ane existing account.
	//
	// https://dev.recurly.com/docs/delete-shipping-address-on-an-existing-account
	Delete(ctx context.Context, accountCode string, shippingAddressID int) error
}

ShippingAddressesService manages the interactions for shipping addresses.

type ShippingFee

type ShippingFee struct {
	XMLName               xml.Name `xml:"shipping_fee"`
	ShippingMethodCode    string   `xml:"shipping_method_code,omitempty"`
	ShippingAmountInCents NullInt  `xml:"shipping_amount_in_cents,omitempty"`
}

ShippingFee holds shipping fees for a purchase.

type ShippingMethod

type ShippingMethod struct {
	XMLName        xml.Name `xml:"shipping_method"`
	Code           string   `xml:"code"`
	Name           string   `xml:"name"`
	AccountingCode string   `xml:"accounting_code"`
	TaxCode        string   `xml:"tax_code"`
	CreatedAt      NullTime `xml:"created_at"`
	UpdatedAt      NullTime `xml:"updated_at"`
}

ShippingMethod holds a shipping method.

type ShippingMethodsService

type ShippingMethodsService interface {
	// ListAccount returns a pager to paginate available shipping methods.
	// PagerOptions are used to optionally filter the results.
	//
	// https://dev.recurly.com/docs/list-shipping-methods
	List(opts *PagerOptions) Pager

	// Get retrieves a shipping method. If the shipping method does not exist,
	// a nil shipping method and nil error are returned.
	//
	// https://dev.recurly.com/docs/lookup-shipping-method
	Get(ctx context.Context, code string) (*ShippingMethod, error)
}

ShippingMethodsService manages the interactions for shipping methods.

type Subscription

type Subscription struct {
	XMLName                xml.Name             `xml:"subscription"`
	Plan                   NestedPlan           `xml:"plan,omitempty"`
	AccountCode            string               `xml:"-"`
	InvoiceNumber          int                  `xml:"-"`
	UUID                   string               `xml:"uuid,omitempty"`
	State                  string               `xml:"state,omitempty"`
	UnitAmountInCents      int                  `xml:"unit_amount_in_cents,omitempty"`
	Currency               string               `xml:"currency,omitempty"`
	Quantity               int                  `xml:"quantity,omitempty"`
	TotalAmountInCents     int                  `xml:"total_amount_in_cents,omitempty"`
	ActivatedAt            NullTime             `xml:"activated_at,omitempty"`
	CanceledAt             NullTime             `xml:"canceled_at,omitempty"`
	ExpiresAt              NullTime             `xml:"expires_at,omitempty"`
	CurrentPeriodStartedAt NullTime             `xml:"current_period_started_at,omitempty"`
	CurrentPeriodEndsAt    NullTime             `xml:"current_period_ends_at,omitempty"`
	TrialStartedAt         NullTime             `xml:"trial_started_at,omitempty"`
	TrialEndsAt            NullTime             `xml:"trial_ends_at,omitempty"`
	PausedAt               NullTime             `xml:"paused_at,omitempty"`
	ResumeAt               NullTime             `xml:"resume_at,omitempty"`
	TaxInCents             int                  `xml:"tax_in_cents,omitempty"`
	TaxType                string               `xml:"tax_type,omitempty"`
	TaxRegion              string               `xml:"tax_region,omitempty"`
	TaxRate                float64              `xml:"tax_rate,omitempty"`
	PONumber               string               `xml:"po_number,omitempty"`
	NetTerms               NullInt              `xml:"net_terms,omitempty"`
	SubscriptionAddOns     []SubscriptionAddOn  `xml:"subscription_add_ons>subscription_add_on,omitempty"`
	CurrentTermStartedAt   NullTime             `xml:"current_term_started_at,omitempty"`
	CurrentTermEndsAt      NullTime             `xml:"current_term_ends_at,omitempty"`
	PendingSubscription    *PendingSubscription `xml:"pending_subscription,omitempty"`
	InvoiceCollection      *InvoiceCollection   `xml:"invoice_collection,omitempty"`
	RemainingPauseCycles   int                  `xml:"remaining_pause_cycles,omitempty"`
	CollectionMethod       string               `xml:"collection_method"`
	CustomerNotes          string               `xml:"customer_notes,omitempty"`
	AutoRenew              bool                 `xml:"auto_renew,omitempty"`
	RenewalBillingCycles   NullInt              `xml:"renewal_billing_cycles,omitempty"`
	RemainingBillingCycles NullInt              `xml:"remaining_billing_cycles,omitempty"`
	GatewayCode            string               `xml:"gateway_code,omitempty"`
	CustomFields           *CustomFields        `xml:"custom_fields,omitempty"`
}

Subscription represents an individual subscription.

func (*Subscription) UnmarshalXML

func (s *Subscription) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

UnmarshalXML unmarshals transactions and handles intermediary state during unmarshaling for types like href.

type SubscriptionAddOn

type SubscriptionAddOn struct {
	XMLName           xml.Name `xml:"subscription_add_on"`
	Type              string   `xml:"add_on_type,omitempty"`
	Code              string   `xml:"add_on_code"`
	UnitAmountInCents NullInt  `xml:"unit_amount_in_cents,omitempty"`
	Quantity          int      `xml:"quantity,omitempty"`
	AddOnSource       string   `xml:"add_on_source,omitempty"`
}

SubscriptionAddOn are add ons to subscriptions. https://docs.com/api/subscriptions/subscription-add-ons

type SubscriptionNotes

type SubscriptionNotes struct {
	XMLName               xml.Name      `xml:"subscription"`
	TermsAndConditions    string        `xml:"terms_and_conditions,omitempty"`
	CustomerNotes         string        `xml:"customer_notes,omitempty"`
	VATReverseChargeNotes string        `xml:"vat_reverse_charge_notes,omitempty"`
	GatewayCode           string        `xml:"gateway_code"`
	CustomFields          *CustomFields `xml:"custom_fields,omitempty"`
}

SubscriptionNotes is used to update a subscription's notes.

type SubscriptionsService

type SubscriptionsService interface {
	// List returns a pager to paginate subscription. PagerOptions are used to
	// optionally filter the results.
	//
	// https://dev.recurly.com/docs/list-subscriptions
	List(opts *PagerOptions) Pager

	// ListAccount returns a pager to paginate subscriptions for an account.
	// PagerOptions are used to optionally filter the results.
	//
	// https://dev.recurly.com/docs/list-accounts-subscriptions
	ListAccount(accountCode string, opts *PagerOptions) Pager

	// Get retrieves a subscription. If the subscription does not exist,
	// a nil subscription and nil error are returned.
	//
	// https://dev.recurly.com/docs/lookup-subscription-details
	Get(ctx context.Context, uuid string) (*Subscription, error)

	// Create creates a subscription. You can optionally include subscription
	// add ons. See Recurly's documentation for specfics.
	//
	// https://dev.recurly.com/docs/create-subscription
	// https://dev.recurly.com/docs/subscription-add-ons
	Create(ctx context.Context, sub NewSubscription) (*Subscription, error)

	// Preview returns a preview for a new subscription applied to an account.
	//
	// https://dev.recurly.com/docs/preview-subscription
	Preview(ctx context.Context, sub NewSubscription) (*Subscription, error)

	// Update updates a subscription that takes place immediately or at renewal
	// based on sub.Timeframe. You can optionally send subscription add ons.
	// If the subscription has add ons and you omit, the subscription will
	// be updated and all add ons will be removed.
	//
	// https://dev.recurly.com/docs/update-subscription
	// https://dev.recurly.com/docs/update-subscription-with-add-ons
	Update(ctx context.Context, uuid string, sub UpdateSubscription) (*Subscription, error)

	// UpdateNotes updates a subscription's invoice notes before the next renewal.
	// Updating notes will not trigger the renewal.
	//
	// https://dev.recurly.com/docs/update-subscription-notes
	UpdateNotes(ctx context.Context, uuid string, n SubscriptionNotes) (*Subscription, error)

	// PreviewChange previews a subscription change applied to an account without
	// committing a subscription change or posting an invoice.
	//
	// https://dev.recurly.com/docs/preview-subscription-change
	PreviewChange(ctx context.Context, uuid string, sub UpdateSubscription) (*Subscription, error)

	// Cancel cancels a subscription so it remains active and then expires at
	// the end of the current bill cycle.
	//
	// https://dev.recurly.com/docs/cancel-subscription
	Cancel(ctx context.Context, uuid string) (*Subscription, error)

	// Reactive reactivates a canceled subscription so it renews at the end
	// of the current bill cycle.
	//
	// https://dev.recurly.com/docs/reactivate-canceled-subscription
	Reactivate(ctx context.Context, uuid string) (*Subscription, error)

	// Terminate terminates a subscription and refunds according to refundType.
	// Valid values for refundType: 'partial', 'full', or 'none'.
	// See Recurly's documentation for more details.
	//
	// https://dev.recurly.com/docs/terminate-subscription
	Terminate(ctx context.Context, uuid string, refundType string) (*Subscription, error)

	// Pause schedules a pause or updates remaining pause cycles for a subscription.
	//
	// https://dev.recurly.com/docs/pause-subscription
	Pause(ctx context.Context, uuid string, cycles int) (*Subscription, error)

	// Postpone changes the next bill date (for an active subscription) or
	// changes when the trial expires (for subscriptions in trial period).
	// See Recurly's documentation for details.
	//
	// https://dev.recurly.com/docs/postpone-subscription
	Postpone(ctx context.Context, uuid string, dt time.Time, bulk bool) (*Subscription, error)

	// Resume reactivates a paused subscription, starting a new billing cycle.
	//
	// https://dev.recurly.com/docs/resume-subscription
	Resume(ctx context.Context, uuid string) (*Subscription, error)

	// Immediately converts a trial subscription to paid
	//
	// https://dev.recurly.com/docs/convert-trial
	ConvertTrial(ctx context.Context, uuid string) (*Subscription, error)
}

SubscriptionsService manages the interactions for subscriptions.

type TaxDetail

type TaxDetail struct {
	XMLName    xml.Name `xml:"tax_detail"`
	Name       string   `xml:"name,omitempty"`
	Type       string   `xml:"type,omitempty"`
	TaxRate    float64  `xml:"tax_rate,omitempty"`
	TaxInCents int      `xml:"tax_in_cents,omitempty"`
	Level      string   `xml:"level,omitempty"`
	Billable   NullBool `xml:"billable,omitempty"`
}

TaxDetail holds tax information and is embedded in an Adjustment. TaxDetails are a read only field, so they shouldn't marshal.

type TestServer

type TestServer struct {
	Invoked bool
	// contains filtered or unexported fields
}

TestServer is a server used for testing when mocks are not sufficient. This enables pointing a recurly client to this test server and simulating requests/responses directly.

func (*TestServer) Close

func (s *TestServer) Close()

Close closes the server.

func (*TestServer) HandleFunc

func (s *TestServer) HandleFunc(method string, pattern string, fn http.HandlerFunc, t *testing.T)

HandleFunc sets up an HTTP handler where the HTTP method is asserted. fn is the handler, and all invocation will set s.Invoked to true.

type Tier

type Tier struct {
	XMLName           xml.Name   `xml:"tier"`
	UnitAmountInCents UnitAmount `xml:"unit_amount_in_cents,omitempty"`
	EndingQuantity    int        `xml:"ending_quantity,omitempty"`
}

Tier is used for Quantity Based Pricing models https://docs.recurly.com/docs/billing-models#section-quantity-based

type Transaction

type Transaction struct {
	InvoiceNumber           int               // Read only
	OriginalTransactionUUID string            // Read only
	UUID                    string            `xml:"uuid,omitempty"` // Read only
	Action                  string            `xml:"action,omitempty"`
	AmountInCents           int               `xml:"amount_in_cents"`
	TaxInCents              int               `xml:"tax_in_cents,omitempty"`
	Currency                string            `xml:"currency"`
	Status                  string            `xml:"status,omitempty"`
	Description             string            `xml:"description,omitempty"`
	ProductCode             string            `xml:"-"` // Write only field, saved on the invoice line item but not the transaction
	PaymentMethod           string            `xml:"payment_method,omitempty"`
	Reference               string            `xml:"reference,omitempty"`
	Source                  string            `xml:"source,omitempty"`
	Recurring               NullBool          `xml:"recurring,omitempty"`
	Test                    bool              `xml:"test,omitempty"`
	Voidable                NullBool          `xml:"voidable,omitempty"`
	Refundable              NullBool          `xml:"refundable,omitempty"`
	IPAddress               net.IP            `xml:"ip_address,omitempty"`
	TransactionError        *TransactionError `xml:"transaction_error,omitempty"` // Read only
	CVVResult               CVVResult         `xml:"cvv_result,omitempty"`        // Read only
	AVSResult               AVSResult         `xml:"avs_result,omitempty"`        // Read only
	AVSResultStreet         string            `xml:"avs_result_street,omitempty"` // Read only
	AVSResultPostal         string            `xml:"avs_result_postal,omitempty"` // Read only
	CreatedAt               NullTime          `xml:"created_at,omitempty"`        // Read only
	Account                 Account           `xml:"details>account"`             // Read only
	GatewayType             string            `xml:"gateway_type,omitempty"`      // Read only
	Origin                  string            `xml:"origin,omitempty"`            // Read only
	Message                 string            `xml:"message,omitempty"`           // Read only
	ApprovalCode            string            `xml:"approval_code,omitempty"`     // Read only

}

Transaction is an individual transaction.

func (*Transaction) UnmarshalXML

func (t *Transaction) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

UnmarshalXML unmarshals transactions and handles intermediary state during unmarshaling for types like href.

type TransactionError

type TransactionError struct {
	XMLName                   xml.Name `xml:"transaction_error"`
	ErrorCode                 string   `xml:"error_code,omitempty"`
	ErrorCategory             string   `xml:"error_category,omitempty"`
	MerchantMessage           string   `xml:"merchant_message,omitempty"`
	CustomerMessage           string   `xml:"customer_message,omitempty"`
	GatewayErrorCode          string   `xml:"gateway_error_code,omitempty"`
	ThreeDSecureActionTokenID string   `xml:"three_d_secure_action_token_id,omitempty"`
}

TransactionError is an error encounted from your payment gateway that recurly has standardized.

https://dev.recurly.com/page/transaction-errors

type TransactionFailedError

type TransactionFailedError struct {
	Response *http.Response

	// Transaction holds the failed transaction (if any).
	Transaction *Transaction

	// TransactionError holds the transaction error. This will always be
	// available.
	TransactionError TransactionError
}

TransactionFailedError is returned when a transaction fails.

func (*TransactionFailedError) Error

func (e *TransactionFailedError) Error() string

type Transactions

type Transactions []Transaction

Transactions is a sortable slice of Transaction.

func (Transactions) Sort

func (t Transactions) Sort()

Sort sorts transactions in ascending order.

type TransactionsService

type TransactionsService interface {
	// List returns a pager to paginate transactions. PagerOptions are used to
	// optionally filter the results.
	//
	// https://dev.recurly.com/docs/list-transactions
	List(opts *PagerOptions) Pager

	// ListAccount returns a pager to paginate transactions for an account.
	// PagerOptions are used to optionally filter the results.
	//
	// https://dev.recurly.com/docs/list-accounts-transactions
	ListAccount(accountCode string, opts *PagerOptions) Pager

	// Get retrieves a transaction. If the transaction does not exist,
	// a nil transaction and nil error are returned.
	//
	// https://dev.recurly.com/docs/lookup-transaction
	Get(ctx context.Context, uuid string) (*Transaction, error)
}

TransactionsService manages the interactions for transactions.

type UnitAmount

type UnitAmount struct {
	USD int `xml:"USD,omitempty"`
	EUR int `xml:"EUR,omitempty"`
	GBP int `xml:"GBP,omitempty"`
	CAD int `xml:"CAD,omitempty"`
	AUD int `xml:"AUD,omitempty"`
}

UnitAmount can read or write amounts in various currencies.

func (UnitAmount) MarshalXML

func (u UnitAmount) MarshalXML(e *xml.Encoder, start xml.StartElement) error

MarshalXML ensures UnitAmount is not marshaled unless one or more currencies has a value greater than zero.

type UpdateSubscription

type UpdateSubscription struct {
	XMLName                xml.Name             `xml:"subscription"`
	Timeframe              string               `xml:"timeframe,omitempty"`
	PlanCode               string               `xml:"plan_code,omitempty"`
	Quantity               int                  `xml:"quantity,omitempty"`
	UnitAmountInCents      NullInt              `xml:"unit_amount_in_cents,omitempty"`
	CollectionMethod       string               `xml:"collection_method,omitempty"`
	NetTerms               NullInt              `xml:"net_terms,omitempty"`
	PONumber               string               `xml:"po_number,omitempty"`
	SubscriptionAddOns     *[]SubscriptionAddOn `xml:"subscription_add_ons>subscription_add_on,omitempty"`
	CouponCode             string               `xml:"coupon_code,omitempty"`
	RevenueScheduleType    string               `xml:"revenue_schedule_type,omitempty"`
	RemainingBillingCycles NullInt              `xml:"remaining_billing_cycles,omitempty"`
	ImportedTrial          NullBool             `xml:"imported_trial,omitempty"`
	RenewalBillingCycles   NullInt              `xml:"renewal_billing_cycles,omitempty"`
	AutoRenew              NullBool             `xml:"auto_renew,omitempty"`
	CustomFields           *CustomFields        `xml:"custom_fields,omitempty"`
	BillingInfo            *Billing             `xml:"billing_info,omitempty"`
	TransactionType        string               `xml:"transaction_type,omitempty"` // Optional transaction type. Currently accepts "moto"
}

UpdateSubscription is used to update subscriptions

type ValidationError

type ValidationError struct {
	Description string
	Field       string
	Symbol      string
}

ValidationError is an individual validation error.

func (*ValidationError) Error

func (e *ValidationError) Error() string

type VoidLineItem

type VoidLineItem struct {
	XMLName  xml.Name `xml:"adjustment"`
	UUID     string   `xml:"uuid"` // Adjustment UUID
	Quantity int      `xml:"quantity"`
	Prorate  NullBool `xml:"prorate,omitempty"`
}

VoidLineItem is an individual line item to refund.

Directories

Path Synopsis
Package mock provides mocks attached to the Recurly client for testing code using the Recurly API client.
Package mock provides mocks attached to the Recurly client for testing code using the Recurly API client.

Jump to

Keyboard shortcuts

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