From d32b0559fba98a1581cd67e4ec10c9b451728b9c Mon Sep 17 00:00:00 2001 From: ProcessOut Fountain Date: Tue, 13 Jan 2026 16:38:36 +0100 Subject: [PATCH] BREAKING CHANGE: Add riskified as supported external fraud tool; removes unused endpoints. --- activity.go | 291 ------ addon.go | 631 ------------- card.go | 6 + card_create_request.go | 77 +- card_update_request.go | 11 +- coupon.go | 586 ------------ customer.go | 119 +-- device.go | 6 + discount.go | 500 ----------- invoice.go | 155 +++- invoice_device.go | 3 + invoice_external_fraud_tools.go | 3 + plan.go | 599 ------------- processout.go | 132 +-- project.go | 214 ----- refund.go | 4 + subscription.go | 1486 ------------------------------- token.go | 3 + transaction.go | 12 +- transaction_operation.go | 3 + unsupported_feature_bypass.go | 3 + 21 files changed, 254 insertions(+), 4590 deletions(-) delete mode 100755 activity.go delete mode 100755 addon.go delete mode 100755 coupon.go delete mode 100755 discount.go delete mode 100755 plan.go delete mode 100755 subscription.go diff --git a/activity.go b/activity.go deleted file mode 100755 index cca6ff7..0000000 --- a/activity.go +++ /dev/null @@ -1,291 +0,0 @@ -package processout - -import ( - "bytes" - "context" - "encoding/json" - "io" - "net/http" - "net/url" - "strings" - "time" - - "gopkg.in/processout.v5/errors" -) - -// Activity represents the Activity API object -type Activity struct { - // ID is the iD of the activity - ID *string `json:"id,omitempty"` - // Project is the project to which the activity belongs - Project *Project `json:"project,omitempty"` - // ProjectID is the iD of the project to which the activity belongs - ProjectID *string `json:"project_id,omitempty"` - // Title is the title of the activity - Title *string `json:"title,omitempty"` - // Content is the content of the activity - Content *string `json:"content,omitempty"` - // Level is the level of the activity - Level *int `json:"level,omitempty"` - // CreatedAt is the date at which the transaction was created - CreatedAt *time.Time `json:"created_at,omitempty"` - - client *ProcessOut -} - -// GetID implements the Identiable interface -func (s *Activity) GetID() string { - if s.ID == nil { - return "" - } - - return *s.ID -} - -// SetClient sets the client for the Activity object and its -// children -func (s *Activity) SetClient(c *ProcessOut) *Activity { - if s == nil { - return s - } - s.client = c - if s.Project != nil { - s.Project.SetClient(c) - } - - return s -} - -// Prefil prefills the object with data provided in the parameter -func (s *Activity) Prefill(c *Activity) *Activity { - if c == nil { - return s - } - - s.ID = c.ID - s.Project = c.Project - s.ProjectID = c.ProjectID - s.Title = c.Title - s.Content = c.Content - s.Level = c.Level - s.CreatedAt = c.CreatedAt - - return s -} - -// ActivityAllParameters is the structure representing the -// additional parameters used to call Activity.All -type ActivityAllParameters struct { - *Options - *Activity -} - -// All allows you to get all the project activities. -func (s Activity) All(options ...ActivityAllParameters) (*Iterator, error) { - return s.AllWithContext(context.Background(), options...) -} - -// All allows you to get all the project activities., passes the provided context to the request -func (s Activity) AllWithContext(ctx context.Context, options ...ActivityAllParameters) (*Iterator, error) { - if s.client == nil { - panic("Please use the client.NewActivity() method to create a new Activity object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := ActivityAllParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Activity) - - type Response struct { - Activities []*Activity `json:"activities"` - - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - }{ - Options: opt.Options, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/activities" - - req, err := http.NewRequestWithContext( - ctx, - "GET", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - activitiesList := []Identifiable{} - for _, o := range payload.Activities { - activitiesList = append(activitiesList, o.SetClient(s.client)) - } - activitiesIterator := &Iterator{ - pos: -1, - path: path, - data: activitiesList, - options: opt.Options, - decoder: func(b io.Reader, i interface{}) (bool, error) { - r := struct { - Data json.RawMessage `json:"activities"` - HasMore bool `json:"has_more"` - }{} - if err := json.NewDecoder(b).Decode(&r); err != nil { - return false, err - } - if err := json.Unmarshal(r.Data, i); err != nil { - return false, err - } - return r.HasMore, nil - }, - client: s.client, - hasMoreNext: payload.HasMore, - hasMorePrev: false, - } - return activitiesIterator, nil -} - -// ActivityFindParameters is the structure representing the -// additional parameters used to call Activity.Find -type ActivityFindParameters struct { - *Options - *Activity -} - -// Find allows you to find a specific activity and fetch its data. -func (s Activity) Find(activityID string, options ...ActivityFindParameters) (*Activity, error) { - return s.FindWithContext(context.Background(), activityID, options...) -} - -// Find allows you to find a specific activity and fetch its data., passes the provided context to the request -func (s Activity) FindWithContext(ctx context.Context, activityID string, options ...ActivityFindParameters) (*Activity, error) { - if s.client == nil { - panic("Please use the client.NewActivity() method to create a new Activity object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := ActivityFindParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Activity) - - type Response struct { - Activity *Activity `json:"activity"` - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - }{ - Options: opt.Options, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/activities/" + url.QueryEscape(activityID) + "" - - req, err := http.NewRequestWithContext( - ctx, - "GET", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - payload.Activity.SetClient(s.client) - return payload.Activity, nil -} - -// dummyActivity is a dummy function that's only -// here because some files need specific packages and some don't. -// It's easier to include it for every file. In case you couldn't -// tell, everything is generated. -func dummyActivity() { - type dummy struct { - a bytes.Buffer - b json.RawMessage - c http.File - d strings.Reader - e time.Time - f url.URL - g io.Reader - } - errors.New(nil, "", "") -} diff --git a/addon.go b/addon.go deleted file mode 100755 index 6332269..0000000 --- a/addon.go +++ /dev/null @@ -1,631 +0,0 @@ -package processout - -import ( - "bytes" - "context" - "encoding/json" - "io" - "net/http" - "net/url" - "strings" - "time" - - "gopkg.in/processout.v5/errors" -) - -// Addon represents the Addon API object -type Addon struct { - // ID is the iD of the addon - ID *string `json:"id,omitempty"` - // Project is the project to which the addon belongs - Project *Project `json:"project,omitempty"` - // ProjectID is the iD of the project to which the addon belongs - ProjectID *string `json:"project_id,omitempty"` - // Subscription is the subscription to which the addon belongs - Subscription *Subscription `json:"subscription,omitempty"` - // SubscriptionID is the iD of the subscription to which the addon belongs - SubscriptionID *string `json:"subscription_id,omitempty"` - // Plan is the plan used to create the addon, if any - Plan *Plan `json:"plan,omitempty"` - // PlanID is the iD of the plan used to create the addon, if any - PlanID *string `json:"plan_id,omitempty"` - // Type is the type of the addon. Can be either metered or recurring - Type *string `json:"type,omitempty"` - // Name is the name of the addon - Name *string `json:"name,omitempty"` - // Amount is the amount of the addon - Amount *string `json:"amount,omitempty"` - // Quantity is the quantity of the addon - Quantity *int `json:"quantity,omitempty"` - // Metadata is the metadata related to the addon, in the form of a dictionary (key-value pair) - Metadata *map[string]string `json:"metadata,omitempty"` - // Sandbox is the define whether or not the addon is in sandbox environment - Sandbox *bool `json:"sandbox,omitempty"` - // CreatedAt is the date at which the addon was created - CreatedAt *time.Time `json:"created_at,omitempty"` - - client *ProcessOut -} - -// GetID implements the Identiable interface -func (s *Addon) GetID() string { - if s.ID == nil { - return "" - } - - return *s.ID -} - -// SetClient sets the client for the Addon object and its -// children -func (s *Addon) SetClient(c *ProcessOut) *Addon { - if s == nil { - return s - } - s.client = c - if s.Project != nil { - s.Project.SetClient(c) - } - if s.Subscription != nil { - s.Subscription.SetClient(c) - } - if s.Plan != nil { - s.Plan.SetClient(c) - } - - return s -} - -// Prefil prefills the object with data provided in the parameter -func (s *Addon) Prefill(c *Addon) *Addon { - if c == nil { - return s - } - - s.ID = c.ID - s.Project = c.Project - s.ProjectID = c.ProjectID - s.Subscription = c.Subscription - s.SubscriptionID = c.SubscriptionID - s.Plan = c.Plan - s.PlanID = c.PlanID - s.Type = c.Type - s.Name = c.Name - s.Amount = c.Amount - s.Quantity = c.Quantity - s.Metadata = c.Metadata - s.Sandbox = c.Sandbox - s.CreatedAt = c.CreatedAt - - return s -} - -// AddonFetchSubscriptionAddonsParameters is the structure representing the -// additional parameters used to call Addon.FetchSubscriptionAddons -type AddonFetchSubscriptionAddonsParameters struct { - *Options - *Addon -} - -// FetchSubscriptionAddons allows you to get the addons applied to the subscription. -func (s Addon) FetchSubscriptionAddons(subscriptionID string, options ...AddonFetchSubscriptionAddonsParameters) (*Iterator, error) { - return s.FetchSubscriptionAddonsWithContext(context.Background(), subscriptionID, options...) -} - -// FetchSubscriptionAddons allows you to get the addons applied to the subscription., passes the provided context to the request -func (s Addon) FetchSubscriptionAddonsWithContext(ctx context.Context, subscriptionID string, options ...AddonFetchSubscriptionAddonsParameters) (*Iterator, error) { - if s.client == nil { - panic("Please use the client.NewAddon() method to create a new Addon object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := AddonFetchSubscriptionAddonsParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Addon) - - type Response struct { - Addons []*Addon `json:"addons"` - - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - }{ - Options: opt.Options, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/subscriptions/" + url.QueryEscape(subscriptionID) + "/addons" - - req, err := http.NewRequestWithContext( - ctx, - "GET", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - addonsList := []Identifiable{} - for _, o := range payload.Addons { - addonsList = append(addonsList, o.SetClient(s.client)) - } - addonsIterator := &Iterator{ - pos: -1, - path: path, - data: addonsList, - options: opt.Options, - decoder: func(b io.Reader, i interface{}) (bool, error) { - r := struct { - Data json.RawMessage `json:"addons"` - HasMore bool `json:"has_more"` - }{} - if err := json.NewDecoder(b).Decode(&r); err != nil { - return false, err - } - if err := json.Unmarshal(r.Data, i); err != nil { - return false, err - } - return r.HasMore, nil - }, - client: s.client, - hasMoreNext: payload.HasMore, - hasMorePrev: false, - } - return addonsIterator, nil -} - -// AddonCreateParameters is the structure representing the -// additional parameters used to call Addon.Create -type AddonCreateParameters struct { - *Options - *Addon - Prorate interface{} `json:"prorate"` - ProrationDate interface{} `json:"proration_date"` - Preview interface{} `json:"preview"` -} - -// Create allows you to create a new addon to the given subscription ID. -func (s Addon) Create(options ...AddonCreateParameters) (*Addon, error) { - return s.CreateWithContext(context.Background(), options...) -} - -// Create allows you to create a new addon to the given subscription ID., passes the provided context to the request -func (s Addon) CreateWithContext(ctx context.Context, options ...AddonCreateParameters) (*Addon, error) { - if s.client == nil { - panic("Please use the client.NewAddon() method to create a new Addon object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := AddonCreateParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Addon) - - type Response struct { - Addon *Addon `json:"addon"` - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - PlanID interface{} `json:"plan_id"` - Type interface{} `json:"type"` - Name interface{} `json:"name"` - Amount interface{} `json:"amount"` - Quantity interface{} `json:"quantity"` - Metadata interface{} `json:"metadata"` - Prorate interface{} `json:"prorate"` - ProrationDate interface{} `json:"proration_date"` - Preview interface{} `json:"preview"` - }{ - Options: opt.Options, - PlanID: s.PlanID, - Type: s.Type, - Name: s.Name, - Amount: s.Amount, - Quantity: s.Quantity, - Metadata: s.Metadata, - Prorate: opt.Prorate, - ProrationDate: opt.ProrationDate, - Preview: opt.Preview, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/subscriptions/" + url.QueryEscape(*s.SubscriptionID) + "/addons" - - req, err := http.NewRequestWithContext( - ctx, - "POST", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - payload.Addon.SetClient(s.client) - return payload.Addon, nil -} - -// AddonFindParameters is the structure representing the -// additional parameters used to call Addon.Find -type AddonFindParameters struct { - *Options - *Addon -} - -// Find allows you to find a subscription's addon by its ID. -func (s Addon) Find(subscriptionID, addonID string, options ...AddonFindParameters) (*Addon, error) { - return s.FindWithContext(context.Background(), subscriptionID, addonID, options...) -} - -// Find allows you to find a subscription's addon by its ID., passes the provided context to the request -func (s Addon) FindWithContext(ctx context.Context, subscriptionID, addonID string, options ...AddonFindParameters) (*Addon, error) { - if s.client == nil { - panic("Please use the client.NewAddon() method to create a new Addon object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := AddonFindParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Addon) - - type Response struct { - Addon *Addon `json:"addon"` - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - }{ - Options: opt.Options, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/subscriptions/" + url.QueryEscape(subscriptionID) + "/addons/" + url.QueryEscape(addonID) + "" - - req, err := http.NewRequestWithContext( - ctx, - "GET", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - payload.Addon.SetClient(s.client) - return payload.Addon, nil -} - -// AddonSaveParameters is the structure representing the -// additional parameters used to call Addon.Save -type AddonSaveParameters struct { - *Options - *Addon - Prorate interface{} `json:"prorate"` - ProrationDate interface{} `json:"proration_date"` - Preview interface{} `json:"preview"` - IncrementQuantityBy interface{} `json:"increment_quantity_by"` -} - -// Save allows you to save the updated addon attributes. -func (s Addon) Save(options ...AddonSaveParameters) (*Addon, error) { - return s.SaveWithContext(context.Background(), options...) -} - -// Save allows you to save the updated addon attributes., passes the provided context to the request -func (s Addon) SaveWithContext(ctx context.Context, options ...AddonSaveParameters) (*Addon, error) { - if s.client == nil { - panic("Please use the client.NewAddon() method to create a new Addon object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := AddonSaveParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Addon) - - type Response struct { - Addon *Addon `json:"addon"` - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - PlanID interface{} `json:"plan_id"` - Type interface{} `json:"type"` - Name interface{} `json:"name"` - Amount interface{} `json:"amount"` - Quantity interface{} `json:"quantity"` - Metadata interface{} `json:"metadata"` - Prorate interface{} `json:"prorate"` - ProrationDate interface{} `json:"proration_date"` - Preview interface{} `json:"preview"` - IncrementQuantityBy interface{} `json:"increment_quantity_by"` - }{ - Options: opt.Options, - PlanID: s.PlanID, - Type: s.Type, - Name: s.Name, - Amount: s.Amount, - Quantity: s.Quantity, - Metadata: s.Metadata, - Prorate: opt.Prorate, - ProrationDate: opt.ProrationDate, - Preview: opt.Preview, - IncrementQuantityBy: opt.IncrementQuantityBy, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/subscriptions/" + url.QueryEscape(*s.SubscriptionID) + "/addons/" + url.QueryEscape(*s.ID) + "" - - req, err := http.NewRequestWithContext( - ctx, - "PUT", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - payload.Addon.SetClient(s.client) - return payload.Addon, nil -} - -// AddonDeleteParameters is the structure representing the -// additional parameters used to call Addon.Delete -type AddonDeleteParameters struct { - *Options - *Addon - Prorate interface{} `json:"prorate"` - ProrationDate interface{} `json:"proration_date"` - Preview interface{} `json:"preview"` -} - -// Delete allows you to delete an addon applied to a subscription. -func (s Addon) Delete(options ...AddonDeleteParameters) error { - return s.DeleteWithContext(context.Background(), options...) -} - -// Delete allows you to delete an addon applied to a subscription., passes the provided context to the request -func (s Addon) DeleteWithContext(ctx context.Context, options ...AddonDeleteParameters) error { - if s.client == nil { - panic("Please use the client.NewAddon() method to create a new Addon object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := AddonDeleteParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Addon) - - type Response struct { - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - Prorate interface{} `json:"prorate"` - ProrationDate interface{} `json:"proration_date"` - Preview interface{} `json:"preview"` - }{ - Options: opt.Options, - Prorate: opt.Prorate, - ProrationDate: opt.ProrationDate, - Preview: opt.Preview, - } - - body, err := json.Marshal(data) - if err != nil { - return errors.New(err, "", "") - } - - path := "/subscriptions/" + url.QueryEscape(*s.SubscriptionID) + "/addons/" + url.QueryEscape(*s.ID) + "" - - req, err := http.NewRequestWithContext( - ctx, - "DELETE", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return erri - } - - return nil -} - -// dummyAddon is a dummy function that's only -// here because some files need specific packages and some don't. -// It's easier to include it for every file. In case you couldn't -// tell, everything is generated. -func dummyAddon() { - type dummy struct { - a bytes.Buffer - b json.RawMessage - c http.File - d strings.Reader - e time.Time - f url.URL - g io.Reader - } - errors.New(nil, "", "") -} diff --git a/card.go b/card.go index c533088..0dd0f29 100755 --- a/card.go +++ b/card.go @@ -81,6 +81,10 @@ type Card struct { Sandbox *bool `json:"sandbox,omitempty"` // CreatedAt is the date at which the card was created CreatedAt *time.Time `json:"created_at,omitempty"` + // PreferredCardType is the preferred card type for combo cards, such as credit or debit + PreferredCardType *string `json:"preferred_card_type,omitempty"` + // VaultID is the iD of the Vault that the card resides in + VaultID *string `json:"vault_id,omitempty"` client *ProcessOut } @@ -150,6 +154,8 @@ func (s *Card) Prefill(c *Card) *Card { s.ExpiresSoon = c.ExpiresSoon s.Sandbox = c.Sandbox s.CreatedAt = c.CreatedAt + s.PreferredCardType = c.PreferredCardType + s.VaultID = c.VaultID return s } diff --git a/card_create_request.go b/card_create_request.go index 86e0092..be86471 100755 --- a/card_create_request.go +++ b/card_create_request.go @@ -31,6 +31,8 @@ type CardCreateRequest struct { Cvc2 *string `json:"cvc2,omitempty"` // PreferredScheme is the preferred card scheme PreferredScheme *string `json:"preferred_scheme,omitempty"` + // PreferredCardType is the preferred card type for combo cards + PreferredCardType *string `json:"preferred_card_type,omitempty"` // Metadata is the metadata related to the card, in the form of a dictionary (key-value pair) Metadata *map[string]string `json:"metadata,omitempty"` // TokenType is the this field defines if the card was tokenized with a 3rd party tokenization method: applepay, googlepay @@ -87,6 +89,7 @@ func (s *CardCreateRequest) Prefill(c *CardCreateRequest) *CardCreateRequest { s.ExpYear = c.ExpYear s.Cvc2 = c.Cvc2 s.PreferredScheme = c.PreferredScheme + s.PreferredCardType = c.PreferredCardType s.Metadata = c.Metadata s.TokenType = c.TokenType s.Eci = c.Eci @@ -140,42 +143,46 @@ func (s CardCreateRequest) CreateWithContext(ctx context.Context, options ...Car data := struct { *Options - Device interface{} `json:"device"` - Name interface{} `json:"name"` - Number interface{} `json:"number"` - ExpDay interface{} `json:"exp_day"` - ExpMonth interface{} `json:"exp_month"` - ExpYear interface{} `json:"exp_year"` - Cvc2 interface{} `json:"cvc2"` - PreferredScheme interface{} `json:"preferred_scheme"` - Metadata interface{} `json:"metadata"` - TokenType interface{} `json:"token_type"` - Eci interface{} `json:"eci"` - Cryptogram interface{} `json:"cryptogram"` - ApplepayResponse interface{} `json:"applepay_response"` - ApplepayMid interface{} `json:"applepay_mid"` - PaymentToken interface{} `json:"payment_token"` - Contact interface{} `json:"contact"` - Shipping interface{} `json:"shipping"` + Device interface{} `json:"device"` + Name interface{} `json:"name"` + Number interface{} `json:"number"` + ExpDay interface{} `json:"exp_day"` + ExpMonth interface{} `json:"exp_month"` + ExpYear interface{} `json:"exp_year"` + Cvc2 interface{} `json:"cvc2"` + PreferredScheme interface{} `json:"preferred_scheme"` + PreferredCardType interface{} `json:"preferred_card_type"` + Metadata interface{} `json:"metadata"` + TokenType interface{} `json:"token_type"` + Eci interface{} `json:"eci"` + Cryptogram interface{} `json:"cryptogram"` + ApplepayResponse interface{} `json:"applepay_response"` + ApplepayMid interface{} `json:"applepay_mid"` + PaymentToken interface{} `json:"payment_token"` + Contact interface{} `json:"contact"` + Shipping interface{} `json:"shipping"` + SchemeTransaction interface{} `json:"scheme_transaction"` }{ - Options: opt.Options, - Device: s.Device, - Name: s.Name, - Number: s.Number, - ExpDay: s.ExpDay, - ExpMonth: s.ExpMonth, - ExpYear: s.ExpYear, - Cvc2: s.Cvc2, - PreferredScheme: s.PreferredScheme, - Metadata: s.Metadata, - TokenType: s.TokenType, - Eci: s.Eci, - Cryptogram: s.Cryptogram, - ApplepayResponse: s.ApplepayResponse, - ApplepayMid: s.ApplepayMid, - PaymentToken: s.PaymentToken, - Contact: s.Contact, - Shipping: s.Shipping, + Options: opt.Options, + Device: s.Device, + Name: s.Name, + Number: s.Number, + ExpDay: s.ExpDay, + ExpMonth: s.ExpMonth, + ExpYear: s.ExpYear, + Cvc2: s.Cvc2, + PreferredScheme: s.PreferredScheme, + PreferredCardType: s.PreferredCardType, + Metadata: s.Metadata, + TokenType: s.TokenType, + Eci: s.Eci, + Cryptogram: s.Cryptogram, + ApplepayResponse: s.ApplepayResponse, + ApplepayMid: s.ApplepayMid, + PaymentToken: s.PaymentToken, + Contact: s.Contact, + Shipping: s.Shipping, + SchemeTransaction: s.SchemeTransaction, } body, err := json.Marshal(data) diff --git a/card_update_request.go b/card_update_request.go index 1717b40..9038629 100755 --- a/card_update_request.go +++ b/card_update_request.go @@ -17,6 +17,8 @@ import ( type CardUpdateRequest struct { // PreferredScheme is the customer preferred scheme, such as carte bancaire vs visa. Can be set to none to clear the previous value PreferredScheme *string `json:"preferred_scheme,omitempty"` + // PreferredCardType is the preferred card type for combo cards, such as credit or debit. + PreferredCardType *string `json:"preferred_card_type,omitempty"` client *ProcessOut } @@ -39,6 +41,7 @@ func (s *CardUpdateRequest) Prefill(c *CardUpdateRequest) *CardUpdateRequest { } s.PreferredScheme = c.PreferredScheme + s.PreferredCardType = c.PreferredCardType return s } @@ -83,10 +86,12 @@ func (s CardUpdateRequest) UpdateWithContext(ctx context.Context, cardID string, data := struct { *Options - PreferredScheme interface{} `json:"preferred_scheme"` + PreferredScheme interface{} `json:"preferred_scheme"` + SchemeTransaction interface{} `json:"scheme_transaction"` }{ - Options: opt.Options, - PreferredScheme: s.PreferredScheme, + Options: opt.Options, + PreferredScheme: s.PreferredScheme, + SchemeTransaction: s.SchemeTransaction, } body, err := json.Marshal(data) diff --git a/coupon.go b/coupon.go deleted file mode 100755 index 89c686d..0000000 --- a/coupon.go +++ /dev/null @@ -1,586 +0,0 @@ -package processout - -import ( - "bytes" - "context" - "encoding/json" - "io" - "net/http" - "net/url" - "strings" - "time" - - "gopkg.in/processout.v5/errors" -) - -// Coupon represents the Coupon API object -type Coupon struct { - // ID is the iD of the coupon - ID *string `json:"id,omitempty"` - // Project is the project to which the coupon belongs - Project *Project `json:"project,omitempty"` - // ProjectID is the iD of the project to which the coupon belongs - ProjectID *string `json:"project_id,omitempty"` - // AmountOff is the amount to be removed from the subscription price - AmountOff *string `json:"amount_off,omitempty"` - // PercentOff is the percent of the subscription amount to be removed (integer between 0 and 100) - PercentOff *int `json:"percent_off,omitempty"` - // Currency is the currency of the coupon amount_off - Currency *string `json:"currency,omitempty"` - // IterationCount is the number billing cycles the coupon will last when applied to a subscription. If 0, will last forever - IterationCount *int `json:"iteration_count,omitempty"` - // MaxRedemptions is the number of time the coupon can be redeemed. If 0, there's no limit - MaxRedemptions *int `json:"max_redemptions,omitempty"` - // ExpiresAt is the date at which the coupon will expire - ExpiresAt *time.Time `json:"expires_at,omitempty"` - // Metadata is the metadata related to the coupon, in the form of a dictionary (key-value pair) - Metadata *map[string]string `json:"metadata,omitempty"` - // RedeemedNumber is the number of times the coupon was already redeemed - RedeemedNumber *int `json:"redeemed_number,omitempty"` - // Sandbox is the true if the coupon was created in the sandbox environment, false otherwise - Sandbox *bool `json:"sandbox,omitempty"` - // CreatedAt is the date at which the coupon was created - CreatedAt *time.Time `json:"created_at,omitempty"` - - client *ProcessOut -} - -// GetID implements the Identiable interface -func (s *Coupon) GetID() string { - if s.ID == nil { - return "" - } - - return *s.ID -} - -// SetClient sets the client for the Coupon object and its -// children -func (s *Coupon) SetClient(c *ProcessOut) *Coupon { - if s == nil { - return s - } - s.client = c - if s.Project != nil { - s.Project.SetClient(c) - } - - return s -} - -// Prefil prefills the object with data provided in the parameter -func (s *Coupon) Prefill(c *Coupon) *Coupon { - if c == nil { - return s - } - - s.ID = c.ID - s.Project = c.Project - s.ProjectID = c.ProjectID - s.AmountOff = c.AmountOff - s.PercentOff = c.PercentOff - s.Currency = c.Currency - s.IterationCount = c.IterationCount - s.MaxRedemptions = c.MaxRedemptions - s.ExpiresAt = c.ExpiresAt - s.Metadata = c.Metadata - s.RedeemedNumber = c.RedeemedNumber - s.Sandbox = c.Sandbox - s.CreatedAt = c.CreatedAt - - return s -} - -// CouponAllParameters is the structure representing the -// additional parameters used to call Coupon.All -type CouponAllParameters struct { - *Options - *Coupon -} - -// All allows you to get all the coupons. -func (s Coupon) All(options ...CouponAllParameters) (*Iterator, error) { - return s.AllWithContext(context.Background(), options...) -} - -// All allows you to get all the coupons., passes the provided context to the request -func (s Coupon) AllWithContext(ctx context.Context, options ...CouponAllParameters) (*Iterator, error) { - if s.client == nil { - panic("Please use the client.NewCoupon() method to create a new Coupon object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := CouponAllParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Coupon) - - type Response struct { - Coupons []*Coupon `json:"coupons"` - - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - }{ - Options: opt.Options, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/coupons" - - req, err := http.NewRequestWithContext( - ctx, - "GET", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - couponsList := []Identifiable{} - for _, o := range payload.Coupons { - couponsList = append(couponsList, o.SetClient(s.client)) - } - couponsIterator := &Iterator{ - pos: -1, - path: path, - data: couponsList, - options: opt.Options, - decoder: func(b io.Reader, i interface{}) (bool, error) { - r := struct { - Data json.RawMessage `json:"coupons"` - HasMore bool `json:"has_more"` - }{} - if err := json.NewDecoder(b).Decode(&r); err != nil { - return false, err - } - if err := json.Unmarshal(r.Data, i); err != nil { - return false, err - } - return r.HasMore, nil - }, - client: s.client, - hasMoreNext: payload.HasMore, - hasMorePrev: false, - } - return couponsIterator, nil -} - -// CouponCreateParameters is the structure representing the -// additional parameters used to call Coupon.Create -type CouponCreateParameters struct { - *Options - *Coupon -} - -// Create allows you to create a new coupon. -func (s Coupon) Create(options ...CouponCreateParameters) (*Coupon, error) { - return s.CreateWithContext(context.Background(), options...) -} - -// Create allows you to create a new coupon., passes the provided context to the request -func (s Coupon) CreateWithContext(ctx context.Context, options ...CouponCreateParameters) (*Coupon, error) { - if s.client == nil { - panic("Please use the client.NewCoupon() method to create a new Coupon object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := CouponCreateParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Coupon) - - type Response struct { - Coupon *Coupon `json:"coupon"` - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - ID interface{} `json:"id"` - AmountOff interface{} `json:"amount_off"` - PercentOff interface{} `json:"percent_off"` - Currency interface{} `json:"currency"` - IterationCount interface{} `json:"iteration_count"` - MaxRedemptions interface{} `json:"max_redemptions"` - ExpiresAt interface{} `json:"expires_at"` - Metadata interface{} `json:"metadata"` - }{ - Options: opt.Options, - ID: s.ID, - AmountOff: s.AmountOff, - PercentOff: s.PercentOff, - Currency: s.Currency, - IterationCount: s.IterationCount, - MaxRedemptions: s.MaxRedemptions, - ExpiresAt: s.ExpiresAt, - Metadata: s.Metadata, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/coupons" - - req, err := http.NewRequestWithContext( - ctx, - "POST", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - payload.Coupon.SetClient(s.client) - return payload.Coupon, nil -} - -// CouponFindParameters is the structure representing the -// additional parameters used to call Coupon.Find -type CouponFindParameters struct { - *Options - *Coupon -} - -// Find allows you to find a coupon by its ID. -func (s Coupon) Find(couponID string, options ...CouponFindParameters) (*Coupon, error) { - return s.FindWithContext(context.Background(), couponID, options...) -} - -// Find allows you to find a coupon by its ID., passes the provided context to the request -func (s Coupon) FindWithContext(ctx context.Context, couponID string, options ...CouponFindParameters) (*Coupon, error) { - if s.client == nil { - panic("Please use the client.NewCoupon() method to create a new Coupon object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := CouponFindParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Coupon) - - type Response struct { - Coupon *Coupon `json:"coupon"` - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - }{ - Options: opt.Options, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/coupons/" + url.QueryEscape(couponID) + "" - - req, err := http.NewRequestWithContext( - ctx, - "GET", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - payload.Coupon.SetClient(s.client) - return payload.Coupon, nil -} - -// CouponSaveParameters is the structure representing the -// additional parameters used to call Coupon.Save -type CouponSaveParameters struct { - *Options - *Coupon -} - -// Save allows you to save the updated coupon attributes. -func (s Coupon) Save(options ...CouponSaveParameters) (*Coupon, error) { - return s.SaveWithContext(context.Background(), options...) -} - -// Save allows you to save the updated coupon attributes., passes the provided context to the request -func (s Coupon) SaveWithContext(ctx context.Context, options ...CouponSaveParameters) (*Coupon, error) { - if s.client == nil { - panic("Please use the client.NewCoupon() method to create a new Coupon object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := CouponSaveParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Coupon) - - type Response struct { - Coupon *Coupon `json:"coupon"` - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - Metadata interface{} `json:"metadata"` - }{ - Options: opt.Options, - Metadata: s.Metadata, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/coupons/" + url.QueryEscape(*s.ID) + "" - - req, err := http.NewRequestWithContext( - ctx, - "PUT", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - payload.Coupon.SetClient(s.client) - return payload.Coupon, nil -} - -// CouponDeleteParameters is the structure representing the -// additional parameters used to call Coupon.Delete -type CouponDeleteParameters struct { - *Options - *Coupon -} - -// Delete allows you to delete the coupon. -func (s Coupon) Delete(options ...CouponDeleteParameters) error { - return s.DeleteWithContext(context.Background(), options...) -} - -// Delete allows you to delete the coupon., passes the provided context to the request -func (s Coupon) DeleteWithContext(ctx context.Context, options ...CouponDeleteParameters) error { - if s.client == nil { - panic("Please use the client.NewCoupon() method to create a new Coupon object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := CouponDeleteParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Coupon) - - type Response struct { - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - }{ - Options: opt.Options, - } - - body, err := json.Marshal(data) - if err != nil { - return errors.New(err, "", "") - } - - path := "/coupons/" + url.QueryEscape(*s.ID) + "" - - req, err := http.NewRequestWithContext( - ctx, - "DELETE", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return erri - } - - return nil -} - -// dummyCoupon is a dummy function that's only -// here because some files need specific packages and some don't. -// It's easier to include it for every file. In case you couldn't -// tell, everything is generated. -func dummyCoupon() { - type dummy struct { - a bytes.Buffer - b json.RawMessage - c http.File - d strings.Reader - e time.Time - f url.URL - g io.Reader - } - errors.New(nil, "", "") -} diff --git a/customer.go b/customer.go index 3f55e77..6651e9d 100755 --- a/customer.go +++ b/customer.go @@ -27,8 +27,6 @@ type Customer struct { DefaultTokenID *string `json:"default_token_id,omitempty"` // Tokens is the list of the customer tokens Tokens *[]*Token `json:"tokens,omitempty"` - // Subscriptions is the list of the customer subscriptions - Subscriptions *[]*Subscription `json:"subscriptions,omitempty"` // Transactions is the list of the customer transactions Transactions *[]*Transaction `json:"transactions,omitempty"` // Balance is the customer balance. Can be positive or negative @@ -79,6 +77,8 @@ type Customer struct { DateOfBirth *time.Time `json:"date_of_birth,omitempty"` // ReferenceID is the merchant reference ID, custom ID for this Customer provided by the API caller. At most 80 characters. Allowed only 1-byte ASCII characters from range 33 (inclusive) to 126 (inclusive) - non-whitespace, non-DEL characters. ReferenceID *string `json:"reference_id,omitempty"` + // VaultID is the iD of the Vault that customer resides in + VaultID *string `json:"vault_id,omitempty"` client *ProcessOut } @@ -124,7 +124,6 @@ func (s *Customer) Prefill(c *Customer) *Customer { s.DefaultToken = c.DefaultToken s.DefaultTokenID = c.DefaultTokenID s.Tokens = c.Tokens - s.Subscriptions = c.Subscriptions s.Transactions = c.Transactions s.Balance = c.Balance s.Currency = c.Currency @@ -150,123 +149,11 @@ func (s *Customer) Prefill(c *Customer) *Customer { s.RegisteredAt = c.RegisteredAt s.DateOfBirth = c.DateOfBirth s.ReferenceID = c.ReferenceID + s.VaultID = c.VaultID return s } -// CustomerFetchSubscriptionsParameters is the structure representing the -// additional parameters used to call Customer.FetchSubscriptions -type CustomerFetchSubscriptionsParameters struct { - *Options - *Customer -} - -// FetchSubscriptions allows you to get the subscriptions belonging to the customer. -func (s Customer) FetchSubscriptions(options ...CustomerFetchSubscriptionsParameters) (*Iterator, error) { - return s.FetchSubscriptionsWithContext(context.Background(), options...) -} - -// FetchSubscriptions allows you to get the subscriptions belonging to the customer., passes the provided context to the request -func (s Customer) FetchSubscriptionsWithContext(ctx context.Context, options ...CustomerFetchSubscriptionsParameters) (*Iterator, error) { - if s.client == nil { - panic("Please use the client.NewCustomer() method to create a new Customer object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := CustomerFetchSubscriptionsParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Customer) - - type Response struct { - Subscriptions []*Subscription `json:"subscriptions"` - - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - }{ - Options: opt.Options, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/customers/" + url.QueryEscape(*s.ID) + "/subscriptions" - - req, err := http.NewRequestWithContext( - ctx, - "GET", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - subscriptionsList := []Identifiable{} - for _, o := range payload.Subscriptions { - subscriptionsList = append(subscriptionsList, o.SetClient(s.client)) - } - subscriptionsIterator := &Iterator{ - pos: -1, - path: path, - data: subscriptionsList, - options: opt.Options, - decoder: func(b io.Reader, i interface{}) (bool, error) { - r := struct { - Data json.RawMessage `json:"subscriptions"` - HasMore bool `json:"has_more"` - }{} - if err := json.NewDecoder(b).Decode(&r); err != nil { - return false, err - } - if err := json.Unmarshal(r.Data, i); err != nil { - return false, err - } - return r.HasMore, nil - }, - client: s.client, - hasMoreNext: payload.HasMore, - hasMorePrev: false, - } - return subscriptionsIterator, nil -} - // CustomerFetchTokensParameters is the structure representing the // additional parameters used to call Customer.FetchTokens type CustomerFetchTokensParameters struct { diff --git a/device.go b/device.go index fecb140..df15b79 100755 --- a/device.go +++ b/device.go @@ -20,6 +20,10 @@ type Device struct { ID *string `json:"id,omitempty"` // Channel is the device channel. Possible values: "web", "ios", "android", "other" Channel *string `json:"channel,omitempty"` + // ThreedsSdk is the preferred 3DS SDK type for authentication. Possible values: "web", "ios", "android", "other". This is the recommended field to use instead of channel for 3DS SDK selection + ThreedsSdk *string `json:"threeds_sdk,omitempty"` + // Platform is the platform of the device for analytics and metadata. Possible values: "web", "ios", "android", "other" + Platform *string `json:"platform,omitempty"` // IpAddress is the device IP address. Use if request origin is "backend" IpAddress *string `json:"ip_address,omitempty"` // UserAgent is the device user agent. Use if request origin is "backend" @@ -73,6 +77,8 @@ func (s *Device) Prefill(c *Device) *Device { s.RequestOrigin = c.RequestOrigin s.ID = c.ID s.Channel = c.Channel + s.ThreedsSdk = c.ThreedsSdk + s.Platform = c.Platform s.IpAddress = c.IpAddress s.UserAgent = c.UserAgent s.HeaderAccept = c.HeaderAccept diff --git a/discount.go b/discount.go deleted file mode 100755 index 68d1f50..0000000 --- a/discount.go +++ /dev/null @@ -1,500 +0,0 @@ -package processout - -import ( - "bytes" - "context" - "encoding/json" - "io" - "net/http" - "net/url" - "strings" - "time" - - "gopkg.in/processout.v5/errors" -) - -// Discount represents the Discount API object -type Discount struct { - // ID is the iD of the discount - ID *string `json:"id,omitempty"` - // Project is the project to which the discount belongs - Project *Project `json:"project,omitempty"` - // ProjectID is the iD of the project to which the discount belongs - ProjectID *string `json:"project_id,omitempty"` - // Subscription is the subscription to which the discount belongs - Subscription *Subscription `json:"subscription,omitempty"` - // SubscriptionID is the iD of the subscription to which the addon belongs - SubscriptionID *string `json:"subscription_id,omitempty"` - // Coupon is the coupon used to create the discount, if any - Coupon *Coupon `json:"coupon,omitempty"` - // CouponID is the iD of the coupon used to create the discount, if any - CouponID *string `json:"coupon_id,omitempty"` - // Name is the name of the discount - Name *string `json:"name,omitempty"` - // Amount is the amount discounted - Amount *string `json:"amount,omitempty"` - // Percent is the percentage discounted - Percent *int `json:"percent,omitempty"` - // ExpiresAt is the date at which the discount will expire - ExpiresAt *time.Time `json:"expires_at,omitempty"` - // Metadata is the metadata related to the discount, in the form of a dictionary (key-value pair) - Metadata *map[string]string `json:"metadata,omitempty"` - // Sandbox is the define whether or not the discount is in sandbox environment - Sandbox *bool `json:"sandbox,omitempty"` - // CreatedAt is the date at which the discount was created - CreatedAt *time.Time `json:"created_at,omitempty"` - - client *ProcessOut -} - -// GetID implements the Identiable interface -func (s *Discount) GetID() string { - if s.ID == nil { - return "" - } - - return *s.ID -} - -// SetClient sets the client for the Discount object and its -// children -func (s *Discount) SetClient(c *ProcessOut) *Discount { - if s == nil { - return s - } - s.client = c - if s.Project != nil { - s.Project.SetClient(c) - } - if s.Subscription != nil { - s.Subscription.SetClient(c) - } - if s.Coupon != nil { - s.Coupon.SetClient(c) - } - - return s -} - -// Prefil prefills the object with data provided in the parameter -func (s *Discount) Prefill(c *Discount) *Discount { - if c == nil { - return s - } - - s.ID = c.ID - s.Project = c.Project - s.ProjectID = c.ProjectID - s.Subscription = c.Subscription - s.SubscriptionID = c.SubscriptionID - s.Coupon = c.Coupon - s.CouponID = c.CouponID - s.Name = c.Name - s.Amount = c.Amount - s.Percent = c.Percent - s.ExpiresAt = c.ExpiresAt - s.Metadata = c.Metadata - s.Sandbox = c.Sandbox - s.CreatedAt = c.CreatedAt - - return s -} - -// DiscountFetchSubscriptionDiscountsParameters is the structure representing the -// additional parameters used to call Discount.FetchSubscriptionDiscounts -type DiscountFetchSubscriptionDiscountsParameters struct { - *Options - *Discount -} - -// FetchSubscriptionDiscounts allows you to get the discounts applied to the subscription. -func (s Discount) FetchSubscriptionDiscounts(subscriptionID string, options ...DiscountFetchSubscriptionDiscountsParameters) (*Iterator, error) { - return s.FetchSubscriptionDiscountsWithContext(context.Background(), subscriptionID, options...) -} - -// FetchSubscriptionDiscounts allows you to get the discounts applied to the subscription., passes the provided context to the request -func (s Discount) FetchSubscriptionDiscountsWithContext(ctx context.Context, subscriptionID string, options ...DiscountFetchSubscriptionDiscountsParameters) (*Iterator, error) { - if s.client == nil { - panic("Please use the client.NewDiscount() method to create a new Discount object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := DiscountFetchSubscriptionDiscountsParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Discount) - - type Response struct { - Discounts []*Discount `json:"discounts"` - - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - }{ - Options: opt.Options, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/subscriptions/" + url.QueryEscape(subscriptionID) + "/discounts" - - req, err := http.NewRequestWithContext( - ctx, - "GET", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - discountsList := []Identifiable{} - for _, o := range payload.Discounts { - discountsList = append(discountsList, o.SetClient(s.client)) - } - discountsIterator := &Iterator{ - pos: -1, - path: path, - data: discountsList, - options: opt.Options, - decoder: func(b io.Reader, i interface{}) (bool, error) { - r := struct { - Data json.RawMessage `json:"discounts"` - HasMore bool `json:"has_more"` - }{} - if err := json.NewDecoder(b).Decode(&r); err != nil { - return false, err - } - if err := json.Unmarshal(r.Data, i); err != nil { - return false, err - } - return r.HasMore, nil - }, - client: s.client, - hasMoreNext: payload.HasMore, - hasMorePrev: false, - } - return discountsIterator, nil -} - -// DiscountCreateParameters is the structure representing the -// additional parameters used to call Discount.Create -type DiscountCreateParameters struct { - *Options - *Discount -} - -// Create allows you to create a new discount for the given subscription ID. -func (s Discount) Create(options ...DiscountCreateParameters) (*Discount, error) { - return s.CreateWithContext(context.Background(), options...) -} - -// Create allows you to create a new discount for the given subscription ID., passes the provided context to the request -func (s Discount) CreateWithContext(ctx context.Context, options ...DiscountCreateParameters) (*Discount, error) { - if s.client == nil { - panic("Please use the client.NewDiscount() method to create a new Discount object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := DiscountCreateParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Discount) - - type Response struct { - Discount *Discount `json:"discount"` - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - CouponID interface{} `json:"coupon_id"` - Name interface{} `json:"name"` - Amount interface{} `json:"amount"` - ExpiresAt interface{} `json:"expires_at"` - Metadata interface{} `json:"metadata"` - }{ - Options: opt.Options, - CouponID: s.CouponID, - Name: s.Name, - Amount: s.Amount, - ExpiresAt: s.ExpiresAt, - Metadata: s.Metadata, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/subscriptions/" + url.QueryEscape(*s.SubscriptionID) + "/discounts" - - req, err := http.NewRequestWithContext( - ctx, - "POST", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - payload.Discount.SetClient(s.client) - return payload.Discount, nil -} - -// DiscountFindParameters is the structure representing the -// additional parameters used to call Discount.Find -type DiscountFindParameters struct { - *Options - *Discount -} - -// Find allows you to find a subscription's discount by its ID. -func (s Discount) Find(subscriptionID, discountID string, options ...DiscountFindParameters) (*Discount, error) { - return s.FindWithContext(context.Background(), subscriptionID, discountID, options...) -} - -// Find allows you to find a subscription's discount by its ID., passes the provided context to the request -func (s Discount) FindWithContext(ctx context.Context, subscriptionID, discountID string, options ...DiscountFindParameters) (*Discount, error) { - if s.client == nil { - panic("Please use the client.NewDiscount() method to create a new Discount object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := DiscountFindParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Discount) - - type Response struct { - Discount *Discount `json:"discount"` - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - }{ - Options: opt.Options, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/subscriptions/" + url.QueryEscape(subscriptionID) + "/discounts/" + url.QueryEscape(discountID) + "" - - req, err := http.NewRequestWithContext( - ctx, - "GET", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - payload.Discount.SetClient(s.client) - return payload.Discount, nil -} - -// DiscountDeleteParameters is the structure representing the -// additional parameters used to call Discount.Delete -type DiscountDeleteParameters struct { - *Options - *Discount -} - -// Delete allows you to delete a discount applied to a subscription. -func (s Discount) Delete(options ...DiscountDeleteParameters) error { - return s.DeleteWithContext(context.Background(), options...) -} - -// Delete allows you to delete a discount applied to a subscription., passes the provided context to the request -func (s Discount) DeleteWithContext(ctx context.Context, options ...DiscountDeleteParameters) error { - if s.client == nil { - panic("Please use the client.NewDiscount() method to create a new Discount object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := DiscountDeleteParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Discount) - - type Response struct { - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - }{ - Options: opt.Options, - } - - body, err := json.Marshal(data) - if err != nil { - return errors.New(err, "", "") - } - - path := "/subscriptions/" + url.QueryEscape(*s.SubscriptionID) + "/discounts/" + url.QueryEscape(*s.ID) + "" - - req, err := http.NewRequestWithContext( - ctx, - "DELETE", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return erri - } - - return nil -} - -// dummyDiscount is a dummy function that's only -// here because some files need specific packages and some don't. -// It's easier to include it for every file. In case you couldn't -// tell, everything is generated. -func dummyDiscount() { - type dummy struct { - a bytes.Buffer - b json.RawMessage - c http.File - d strings.Reader - e time.Time - f url.URL - g io.Reader - } - errors.New(nil, "", "") -} diff --git a/invoice.go b/invoice.go index 6613091..215fdbd 100755 --- a/invoice.go +++ b/invoice.go @@ -29,10 +29,6 @@ type Invoice struct { Customer *Customer `json:"customer,omitempty"` // CustomerID is the iD of the customer linked to the invoice, if any CustomerID *string `json:"customer_id,omitempty"` - // Subscription is the subscription to which the invoice is linked to, if any - Subscription *Subscription `json:"subscription,omitempty"` - // SubscriptionID is the iD of the subscription to which the invoice is linked to, if any - SubscriptionID *string `json:"subscription_id,omitempty"` // Token is the token used to pay the invoice, if any Token *Token `json:"token,omitempty"` // TokenID is the iD of the token used to pay the invoice, if any @@ -148,9 +144,6 @@ func (s *Invoice) SetClient(c *ProcessOut) *Invoice { if s.Customer != nil { s.Customer.SetClient(c) } - if s.Subscription != nil { - s.Subscription.SetClient(c) - } if s.Token != nil { s.Token.SetClient(c) } @@ -198,8 +191,6 @@ func (s *Invoice) Prefill(c *Invoice) *Invoice { s.TransactionID = c.TransactionID s.Customer = c.Customer s.CustomerID = c.CustomerID - s.Subscription = c.Subscription - s.SubscriptionID = c.SubscriptionID s.Token = c.Token s.TokenID = c.TokenID s.Details = c.Details @@ -247,6 +238,137 @@ func (s *Invoice) Prefill(c *Invoice) *Invoice { return s } +// InvoiceAuthenticateParameters is the structure representing the +// additional parameters used to call Invoice.Authenticate +type InvoiceAuthenticateParameters struct { + *Options + *Invoice + Synchronous interface{} `json:"synchronous"` + RetryDropLiabilityShift interface{} `json:"retry_drop_liability_shift"` + CaptureAmount interface{} `json:"capture_amount"` + EnableThreeDS2 interface{} `json:"enable_three_d_s_2"` + AllowFallbackToSale interface{} `json:"allow_fallback_to_sale"` + AutoCaptureAt interface{} `json:"auto_capture_at"` + Metadata interface{} `json:"metadata"` + OverrideMacBlocking interface{} `json:"override_mac_blocking"` + ExternalThreeDS interface{} `json:"external_three_d_s"` + SaveSource interface{} `json:"save_source"` +} + +// Authenticate allows you to autheticate the invoice using the given source (customer or token) +func (s Invoice) Authenticate(source string, options ...InvoiceAuthenticateParameters) (*Transaction, *CustomerAction, error) { + return s.AuthenticateWithContext(context.Background(), source, options...) +} + +// Authenticate allows you to autheticate the invoice using the given source (customer or token), passes the provided context to the request +func (s Invoice) AuthenticateWithContext(ctx context.Context, source string, options ...InvoiceAuthenticateParameters) (*Transaction, *CustomerAction, error) { + if s.client == nil { + panic("Please use the client.NewInvoice() method to create a new Invoice object") + } + if len(options) > 1 { + panic("The options parameter should only be provided once.") + } + + opt := InvoiceAuthenticateParameters{} + if len(options) == 1 { + opt = options[0] + } + if opt.Options == nil { + opt.Options = &Options{} + } + s.Prefill(opt.Invoice) + + type Response struct { + Transaction *Transaction `json:"transaction"` + CustomerAction *CustomerAction `json:"customer_action"` + HasMore bool `json:"has_more"` + Success bool `json:"success"` + Message string `json:"message"` + Code string `json:"error_type"` + } + + data := struct { + *Options + Device interface{} `json:"device"` + Incremental interface{} `json:"incremental"` + CaptureType interface{} `json:"capture_type"` + SplitAllocations interface{} `json:"split_allocations"` + InstallmentPlanID interface{} `json:"installment_plan_id"` + Synchronous interface{} `json:"synchronous"` + RetryDropLiabilityShift interface{} `json:"retry_drop_liability_shift"` + CaptureAmount interface{} `json:"capture_amount"` + EnableThreeDS2 interface{} `json:"enable_three_d_s_2"` + AllowFallbackToSale interface{} `json:"allow_fallback_to_sale"` + AutoCaptureAt interface{} `json:"auto_capture_at"` + Metadata interface{} `json:"metadata"` + OverrideMacBlocking interface{} `json:"override_mac_blocking"` + ExternalThreeDS interface{} `json:"external_three_d_s"` + SaveSource interface{} `json:"save_source"` + Source interface{} `json:"source"` + }{ + Options: opt.Options, + Device: s.Device, + Incremental: s.Incremental, + CaptureType: s.CaptureType, + SplitAllocations: s.SplitAllocations, + InstallmentPlanID: s.InstallmentPlanID, + Synchronous: opt.Synchronous, + RetryDropLiabilityShift: opt.RetryDropLiabilityShift, + CaptureAmount: opt.CaptureAmount, + EnableThreeDS2: opt.EnableThreeDS2, + AllowFallbackToSale: opt.AllowFallbackToSale, + AutoCaptureAt: opt.AutoCaptureAt, + Metadata: opt.Metadata, + OverrideMacBlocking: opt.OverrideMacBlocking, + ExternalThreeDS: opt.ExternalThreeDS, + SaveSource: opt.SaveSource, + Source: source, + } + + body, err := json.Marshal(data) + if err != nil { + return nil, nil, errors.New(err, "", "") + } + + path := "/invoices/:invoice_id/authenticate" + + req, err := http.NewRequestWithContext( + ctx, + "POST", + Host+path, + bytes.NewReader(body), + ) + if err != nil { + return nil, nil, errors.NewNetworkError(err) + } + setupRequest(s.client, opt.Options, req) + + res, err := s.client.HTTPClient.Do(req) + if err != nil { + return nil, nil, errors.NewNetworkError(err) + } + payload := &Response{} + defer res.Body.Close() + if res.StatusCode >= 500 { + return nil, nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") + } + err = json.NewDecoder(res.Body).Decode(payload) + if err != nil { + return nil, nil, errors.New(err, "", "") + } + + if !payload.Success { + erri := errors.NewFromResponse(res.StatusCode, payload.Code, + payload.Message) + + return nil, nil, erri + } + + payload.Transaction.SetClient(s.client) + payload.CustomerAction.SetClient(s.client) + return payload.Transaction, payload.CustomerAction, nil +} + // InvoiceIncrementAuthorizationParameters is the structure representing the // additional parameters used to call Invoice.IncrementAuthorization type InvoiceIncrementAuthorizationParameters struct { @@ -392,6 +514,9 @@ func (s Invoice) AuthorizeWithContext(ctx context.Context, source string, option *Options Device interface{} `json:"device"` Incremental interface{} `json:"incremental"` + CaptureType interface{} `json:"capture_type"` + SplitAllocations interface{} `json:"split_allocations"` + InstallmentPlanID interface{} `json:"installment_plan_id"` Synchronous interface{} `json:"synchronous"` RetryDropLiabilityShift interface{} `json:"retry_drop_liability_shift"` CaptureAmount interface{} `json:"capture_amount"` @@ -407,6 +532,9 @@ func (s Invoice) AuthorizeWithContext(ctx context.Context, source string, option Options: opt.Options, Device: s.Device, Incremental: s.Incremental, + CaptureType: s.CaptureType, + SplitAllocations: s.SplitAllocations, + InstallmentPlanID: s.InstallmentPlanID, Synchronous: opt.Synchronous, RetryDropLiabilityShift: opt.RetryDropLiabilityShift, CaptureAmount: opt.CaptureAmount, @@ -517,7 +645,9 @@ func (s Invoice) CaptureWithContext(ctx context.Context, source string, options data := struct { *Options Device interface{} `json:"device"` + AuthenticateOnly interface{} `json:"authenticate_only"` Incremental interface{} `json:"incremental"` + InstallmentPlanID interface{} `json:"installment_plan_id"` AuthorizeOnly interface{} `json:"authorize_only"` Synchronous interface{} `json:"synchronous"` RetryDropLiabilityShift interface{} `json:"retry_drop_liability_shift"` @@ -533,7 +663,9 @@ func (s Invoice) CaptureWithContext(ctx context.Context, source string, options }{ Options: opt.Options, Device: s.Device, + AuthenticateOnly: s.AuthenticateOnly, Incremental: s.Incremental, + InstallmentPlanID: s.InstallmentPlanID, AuthorizeOnly: opt.AuthorizeOnly, Synchronous: opt.Synchronous, RetryDropLiabilityShift: opt.RetryDropLiabilityShift, @@ -774,6 +906,7 @@ type InvoicePayoutParameters struct { *Options *Invoice ForceGatewayConfigurationID interface{} `json:"force_gateway_configuration_id"` + Metadata interface{} `json:"metadata"` } // Payout allows you to process the payout invoice using the given source (customer or token) @@ -810,11 +943,13 @@ func (s Invoice) PayoutWithContext(ctx context.Context, gatewayConfigurationID, data := struct { *Options ForceGatewayConfigurationID interface{} `json:"force_gateway_configuration_id"` + Metadata interface{} `json:"metadata"` GatewayConfigurationID interface{} `json:"gateway_configuration_id"` Source interface{} `json:"source"` }{ Options: opt.Options, ForceGatewayConfigurationID: opt.ForceGatewayConfigurationID, + Metadata: opt.Metadata, GatewayConfigurationID: gatewayConfigurationID, Source: source, } @@ -1505,6 +1640,7 @@ func (s Invoice) CreateWithContext(ctx context.Context, options ...InvoiceCreate Verification interface{} `json:"verification"` AutoCaptureAt interface{} `json:"auto_capture_at"` ExpiresAt interface{} `json:"expires_at"` + SplitAllocations interface{} `json:"split_allocations"` }{ Options: opt.Options, CustomerID: s.CustomerID, @@ -1543,6 +1679,7 @@ func (s Invoice) CreateWithContext(ctx context.Context, options ...InvoiceCreate Verification: s.Verification, AutoCaptureAt: s.AutoCaptureAt, ExpiresAt: s.ExpiresAt, + SplitAllocations: s.SplitAllocations, } body, err := json.Marshal(data) diff --git a/invoice_device.go b/invoice_device.go index ba7ab3c..22b0969 100755 --- a/invoice_device.go +++ b/invoice_device.go @@ -16,6 +16,8 @@ import ( type InvoiceDevice struct { // Channel is the channel of the device Channel *string `json:"channel,omitempty"` + // Platform is the platform of the device for analytics and metadata. Possible values: "web", "ios", "android", "other" + Platform *string `json:"platform,omitempty"` // IpAddress is the iP address of the device IpAddress *string `json:"ip_address,omitempty"` // ID is the iD of the device @@ -51,6 +53,7 @@ func (s *InvoiceDevice) Prefill(c *InvoiceDevice) *InvoiceDevice { } s.Channel = c.Channel + s.Platform = c.Platform s.IpAddress = c.IpAddress s.ID = c.ID diff --git a/invoice_external_fraud_tools.go b/invoice_external_fraud_tools.go index a0033f4..dd74c67 100755 --- a/invoice_external_fraud_tools.go +++ b/invoice_external_fraud_tools.go @@ -20,6 +20,8 @@ type InvoiceExternalFraudTools struct { Ravelin interface{} `json:"ravelin,omitempty"` // Signifyd is the signifyd Signifyd interface{} `json:"signifyd,omitempty"` + // Riskified is the riskified + Riskified interface{} `json:"riskified,omitempty"` client *ProcessOut } @@ -44,6 +46,7 @@ func (s *InvoiceExternalFraudTools) Prefill(c *InvoiceExternalFraudTools) *Invoi s.Forter = c.Forter s.Ravelin = c.Ravelin s.Signifyd = c.Signifyd + s.Riskified = c.Riskified return s } diff --git a/plan.go b/plan.go deleted file mode 100755 index 6f5d7b4..0000000 --- a/plan.go +++ /dev/null @@ -1,599 +0,0 @@ -package processout - -import ( - "bytes" - "context" - "encoding/json" - "io" - "net/http" - "net/url" - "strings" - "time" - - "gopkg.in/processout.v5/errors" -) - -// Plan represents the Plan API object -type Plan struct { - // ID is the iD of the plan - ID *string `json:"id,omitempty"` - // Project is the project to which the plan belongs - Project *Project `json:"project,omitempty"` - // ProjectID is the iD of the project to which the plan belongs - ProjectID *string `json:"project_id,omitempty"` - // URL is the uRL to which you may redirect your customer to activate the subscription plan - URL *string `json:"url,omitempty"` - // Name is the name of the plan - Name *string `json:"name,omitempty"` - // Amount is the amount of the plan - Amount *string `json:"amount,omitempty"` - // Currency is the currency of the plan - Currency *string `json:"currency,omitempty"` - // Metadata is the metadata related to the plan, in the form of a dictionary (key-value pair) - Metadata *map[string]string `json:"metadata,omitempty"` - // Interval is the the plan interval, formatted in the format "1d2w3m4y" (day, week, month, year) - Interval *string `json:"interval,omitempty"` - // TrialPeriod is the the trial period. The customer will not be charged during this time span. Formatted in the format "1d2w3m4y" (day, week, month, year) - TrialPeriod *string `json:"trial_period,omitempty"` - // ReturnURL is the uRL where the customer will be redirected when activating the subscription created using this plan - ReturnURL *string `json:"return_url,omitempty"` - // CancelURL is the uRL where the customer will be redirected when cancelling the subscription created using this plan - CancelURL *string `json:"cancel_url,omitempty"` - // Sandbox is the define whether or not the plan is in sandbox environment - Sandbox *bool `json:"sandbox,omitempty"` - // CreatedAt is the date at which the plan was created - CreatedAt *time.Time `json:"created_at,omitempty"` - - client *ProcessOut -} - -// GetID implements the Identiable interface -func (s *Plan) GetID() string { - if s.ID == nil { - return "" - } - - return *s.ID -} - -// SetClient sets the client for the Plan object and its -// children -func (s *Plan) SetClient(c *ProcessOut) *Plan { - if s == nil { - return s - } - s.client = c - if s.Project != nil { - s.Project.SetClient(c) - } - - return s -} - -// Prefil prefills the object with data provided in the parameter -func (s *Plan) Prefill(c *Plan) *Plan { - if c == nil { - return s - } - - s.ID = c.ID - s.Project = c.Project - s.ProjectID = c.ProjectID - s.URL = c.URL - s.Name = c.Name - s.Amount = c.Amount - s.Currency = c.Currency - s.Metadata = c.Metadata - s.Interval = c.Interval - s.TrialPeriod = c.TrialPeriod - s.ReturnURL = c.ReturnURL - s.CancelURL = c.CancelURL - s.Sandbox = c.Sandbox - s.CreatedAt = c.CreatedAt - - return s -} - -// PlanAllParameters is the structure representing the -// additional parameters used to call Plan.All -type PlanAllParameters struct { - *Options - *Plan -} - -// All allows you to get all the plans. -func (s Plan) All(options ...PlanAllParameters) (*Iterator, error) { - return s.AllWithContext(context.Background(), options...) -} - -// All allows you to get all the plans., passes the provided context to the request -func (s Plan) AllWithContext(ctx context.Context, options ...PlanAllParameters) (*Iterator, error) { - if s.client == nil { - panic("Please use the client.NewPlan() method to create a new Plan object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := PlanAllParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Plan) - - type Response struct { - Plans []*Plan `json:"plans"` - - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - }{ - Options: opt.Options, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/plans" - - req, err := http.NewRequestWithContext( - ctx, - "GET", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - plansList := []Identifiable{} - for _, o := range payload.Plans { - plansList = append(plansList, o.SetClient(s.client)) - } - plansIterator := &Iterator{ - pos: -1, - path: path, - data: plansList, - options: opt.Options, - decoder: func(b io.Reader, i interface{}) (bool, error) { - r := struct { - Data json.RawMessage `json:"plans"` - HasMore bool `json:"has_more"` - }{} - if err := json.NewDecoder(b).Decode(&r); err != nil { - return false, err - } - if err := json.Unmarshal(r.Data, i); err != nil { - return false, err - } - return r.HasMore, nil - }, - client: s.client, - hasMoreNext: payload.HasMore, - hasMorePrev: false, - } - return plansIterator, nil -} - -// PlanCreateParameters is the structure representing the -// additional parameters used to call Plan.Create -type PlanCreateParameters struct { - *Options - *Plan -} - -// Create allows you to create a new plan. -func (s Plan) Create(options ...PlanCreateParameters) (*Plan, error) { - return s.CreateWithContext(context.Background(), options...) -} - -// Create allows you to create a new plan., passes the provided context to the request -func (s Plan) CreateWithContext(ctx context.Context, options ...PlanCreateParameters) (*Plan, error) { - if s.client == nil { - panic("Please use the client.NewPlan() method to create a new Plan object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := PlanCreateParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Plan) - - type Response struct { - Plan *Plan `json:"plan"` - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - ID interface{} `json:"id"` - Name interface{} `json:"name"` - Amount interface{} `json:"amount"` - Currency interface{} `json:"currency"` - Interval interface{} `json:"interval"` - TrialPeriod interface{} `json:"trial_period"` - Metadata interface{} `json:"metadata"` - ReturnURL interface{} `json:"return_url"` - CancelURL interface{} `json:"cancel_url"` - }{ - Options: opt.Options, - ID: s.ID, - Name: s.Name, - Amount: s.Amount, - Currency: s.Currency, - Interval: s.Interval, - TrialPeriod: s.TrialPeriod, - Metadata: s.Metadata, - ReturnURL: s.ReturnURL, - CancelURL: s.CancelURL, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/plans" - - req, err := http.NewRequestWithContext( - ctx, - "POST", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - payload.Plan.SetClient(s.client) - return payload.Plan, nil -} - -// PlanFindParameters is the structure representing the -// additional parameters used to call Plan.Find -type PlanFindParameters struct { - *Options - *Plan -} - -// Find allows you to find a plan by its ID. -func (s Plan) Find(planID string, options ...PlanFindParameters) (*Plan, error) { - return s.FindWithContext(context.Background(), planID, options...) -} - -// Find allows you to find a plan by its ID., passes the provided context to the request -func (s Plan) FindWithContext(ctx context.Context, planID string, options ...PlanFindParameters) (*Plan, error) { - if s.client == nil { - panic("Please use the client.NewPlan() method to create a new Plan object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := PlanFindParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Plan) - - type Response struct { - Plan *Plan `json:"plan"` - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - }{ - Options: opt.Options, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/plans/" + url.QueryEscape(planID) + "" - - req, err := http.NewRequestWithContext( - ctx, - "GET", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - payload.Plan.SetClient(s.client) - return payload.Plan, nil -} - -// PlanSaveParameters is the structure representing the -// additional parameters used to call Plan.Save -type PlanSaveParameters struct { - *Options - *Plan -} - -// Save allows you to save the updated plan attributes. This action won't affect subscriptions already linked to this plan. -func (s Plan) Save(options ...PlanSaveParameters) (*Plan, error) { - return s.SaveWithContext(context.Background(), options...) -} - -// Save allows you to save the updated plan attributes. This action won't affect subscriptions already linked to this plan., passes the provided context to the request -func (s Plan) SaveWithContext(ctx context.Context, options ...PlanSaveParameters) (*Plan, error) { - if s.client == nil { - panic("Please use the client.NewPlan() method to create a new Plan object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := PlanSaveParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Plan) - - type Response struct { - Plan *Plan `json:"plan"` - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - Name interface{} `json:"name"` - TrialPeriod interface{} `json:"trial_period"` - Metadata interface{} `json:"metadata"` - ReturnURL interface{} `json:"return_url"` - CancelURL interface{} `json:"cancel_url"` - }{ - Options: opt.Options, - Name: s.Name, - TrialPeriod: s.TrialPeriod, - Metadata: s.Metadata, - ReturnURL: s.ReturnURL, - CancelURL: s.CancelURL, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/plans/" + url.QueryEscape(*s.ID) + "" - - req, err := http.NewRequestWithContext( - ctx, - "PUT", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - payload.Plan.SetClient(s.client) - return payload.Plan, nil -} - -// PlanEndParameters is the structure representing the -// additional parameters used to call Plan.End -type PlanEndParameters struct { - *Options - *Plan -} - -// End allows you to delete a plan. Subscriptions linked to this plan won't be affected. -func (s Plan) End(options ...PlanEndParameters) error { - return s.EndWithContext(context.Background(), options...) -} - -// End allows you to delete a plan. Subscriptions linked to this plan won't be affected., passes the provided context to the request -func (s Plan) EndWithContext(ctx context.Context, options ...PlanEndParameters) error { - if s.client == nil { - panic("Please use the client.NewPlan() method to create a new Plan object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := PlanEndParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Plan) - - type Response struct { - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - }{ - Options: opt.Options, - } - - body, err := json.Marshal(data) - if err != nil { - return errors.New(err, "", "") - } - - path := "/plans/" + url.QueryEscape(*s.ID) + "" - - req, err := http.NewRequestWithContext( - ctx, - "DELETE", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return erri - } - - return nil -} - -// dummyPlan is a dummy function that's only -// here because some files need specific packages and some don't. -// It's easier to include it for every file. In case you couldn't -// tell, everything is generated. -func dummyPlan() { - type dummy struct { - a bytes.Buffer - b json.RawMessage - c http.File - d strings.Reader - e time.Time - f url.URL - g io.Reader - } - errors.New(nil, "", "") -} diff --git a/processout.go b/processout.go index eb24abd..b440e0e 100755 --- a/processout.go +++ b/processout.go @@ -63,7 +63,7 @@ func New(projectID, projectSecret string) *ProcessOut { func setupRequest(client *ProcessOut, opt *Options, req *http.Request) { req.Header.Set("Content-Type", "application/json") req.Header.Set("API-Version", client.APIVersion) - req.Header.Set("User-Agent", "ProcessOut Go-Bindings/v5.6.0") + req.Header.Set("User-Agent", "ProcessOut Go-Bindings/v6.0.0") req.Header.Set("Accept", "application/json") if client.UserAgent != "" { req.Header.Set("User-Agent", client.UserAgent) @@ -87,36 +87,6 @@ func setupRequest(client *ProcessOut, opt *Options, req *http.Request) { req.URL.RawQuery = v.Encode() } -// NewActivity creates a new Activity object -func (c *ProcessOut) NewActivity(prefill ...*Activity) *Activity { - if len(prefill) > 1 { - panic("You may only provide one structure used to prefill the Activity, or none.") - } - if len(prefill) == 0 { - return &Activity{ - client: c, - } - } - - prefill[0].client = c - return prefill[0] -} - -// NewAddon creates a new Addon object -func (c *ProcessOut) NewAddon(prefill ...*Addon) *Addon { - if len(prefill) > 1 { - panic("You may only provide one structure used to prefill the Addon, or none.") - } - if len(prefill) == 0 { - return &Addon{ - client: c, - } - } - - prefill[0].client = c - return prefill[0] -} - // NewAPIVersion creates a new APIVersion object func (c *ProcessOut) NewAPIVersion(prefill ...*APIVersion) *APIVersion { if len(prefill) > 1 { @@ -252,21 +222,6 @@ func (c *ProcessOut) NewPhone(prefill ...*Phone) *Phone { return prefill[0] } -// NewCoupon creates a new Coupon object -func (c *ProcessOut) NewCoupon(prefill ...*Coupon) *Coupon { - if len(prefill) > 1 { - panic("You may only provide one structure used to prefill the Coupon, or none.") - } - if len(prefill) == 0 { - return &Coupon{ - client: c, - } - } - - prefill[0].client = c - return prefill[0] -} - // NewCustomer creates a new Customer object func (c *ProcessOut) NewCustomer(prefill ...*Customer) *Customer { if len(prefill) > 1 { @@ -312,21 +267,6 @@ func (c *ProcessOut) NewToken(prefill ...*Token) *Token { return prefill[0] } -// NewDiscount creates a new Discount object -func (c *ProcessOut) NewDiscount(prefill ...*Discount) *Discount { - if len(prefill) > 1 { - panic("You may only provide one structure used to prefill the Discount, or none.") - } - if len(prefill) == 0 { - return &Discount{ - client: c, - } - } - - prefill[0].client = c - return prefill[0] -} - // NewEvent creates a new Event object func (c *ProcessOut) NewEvent(prefill ...*Event) *Event { if len(prefill) > 1 { @@ -792,21 +732,6 @@ func (c *ProcessOut) NewPayoutItemAmountBreakdowns(prefill ...*PayoutItemAmountB return prefill[0] } -// NewPlan creates a new Plan object -func (c *ProcessOut) NewPlan(prefill ...*Plan) *Plan { - if len(prefill) > 1 { - panic("You may only provide one structure used to prefill the Plan, or none.") - } - if len(prefill) == 0 { - return &Plan{ - client: c, - } - } - - prefill[0].client = c - return prefill[0] -} - // NewProduct creates a new Product object func (c *ProcessOut) NewProduct(prefill ...*Product) *Product { if len(prefill) > 1 { @@ -882,21 +807,6 @@ func (c *ProcessOut) NewRefund(prefill ...*Refund) *Refund { return prefill[0] } -// NewSubscription creates a new Subscription object -func (c *ProcessOut) NewSubscription(prefill ...*Subscription) *Subscription { - if len(prefill) > 1 { - panic("You may only provide one structure used to prefill the Subscription, or none.") - } - if len(prefill) == 0 { - return &Subscription{ - client: c, - } - } - - prefill[0].client = c - return prefill[0] -} - // NewTransaction creates a new Transaction object func (c *ProcessOut) NewTransaction(prefill ...*Transaction) *Transaction { if len(prefill) > 1 { @@ -1062,13 +972,13 @@ func (c *ProcessOut) NewWebhookEndpoint(prefill ...*WebhookEndpoint) *WebhookEnd return prefill[0] } -// NewDevice creates a new Device object -func (c *ProcessOut) NewDevice(prefill ...*Device) *Device { +// NewCardUpdateRequest creates a new CardUpdateRequest object +func (c *ProcessOut) NewCardUpdateRequest(prefill ...*CardUpdateRequest) *CardUpdateRequest { if len(prefill) > 1 { - panic("You may only provide one structure used to prefill the Device, or none.") + panic("You may only provide one structure used to prefill the CardUpdateRequest, or none.") } if len(prefill) == 0 { - return &Device{ + return &CardUpdateRequest{ client: c, } } @@ -1077,13 +987,13 @@ func (c *ProcessOut) NewDevice(prefill ...*Device) *Device { return prefill[0] } -// NewCardContact creates a new CardContact object -func (c *ProcessOut) NewCardContact(prefill ...*CardContact) *CardContact { +// NewCardCreateRequest creates a new CardCreateRequest object +func (c *ProcessOut) NewCardCreateRequest(prefill ...*CardCreateRequest) *CardCreateRequest { if len(prefill) > 1 { - panic("You may only provide one structure used to prefill the CardContact, or none.") + panic("You may only provide one structure used to prefill the CardCreateRequest, or none.") } if len(prefill) == 0 { - return &CardContact{ + return &CardCreateRequest{ client: c, } } @@ -1092,13 +1002,13 @@ func (c *ProcessOut) NewCardContact(prefill ...*CardContact) *CardContact { return prefill[0] } -// NewCardShipping creates a new CardShipping object -func (c *ProcessOut) NewCardShipping(prefill ...*CardShipping) *CardShipping { +// NewDevice creates a new Device object +func (c *ProcessOut) NewDevice(prefill ...*Device) *Device { if len(prefill) > 1 { - panic("You may only provide one structure used to prefill the CardShipping, or none.") + panic("You may only provide one structure used to prefill the Device, or none.") } if len(prefill) == 0 { - return &CardShipping{ + return &Device{ client: c, } } @@ -1107,13 +1017,13 @@ func (c *ProcessOut) NewCardShipping(prefill ...*CardShipping) *CardShipping { return prefill[0] } -// NewCardUpdateRequest creates a new CardUpdateRequest object -func (c *ProcessOut) NewCardUpdateRequest(prefill ...*CardUpdateRequest) *CardUpdateRequest { +// NewCardContact creates a new CardContact object +func (c *ProcessOut) NewCardContact(prefill ...*CardContact) *CardContact { if len(prefill) > 1 { - panic("You may only provide one structure used to prefill the CardUpdateRequest, or none.") + panic("You may only provide one structure used to prefill the CardContact, or none.") } if len(prefill) == 0 { - return &CardUpdateRequest{ + return &CardContact{ client: c, } } @@ -1122,13 +1032,13 @@ func (c *ProcessOut) NewCardUpdateRequest(prefill ...*CardUpdateRequest) *CardUp return prefill[0] } -// NewCardCreateRequest creates a new CardCreateRequest object -func (c *ProcessOut) NewCardCreateRequest(prefill ...*CardCreateRequest) *CardCreateRequest { +// NewCardShipping creates a new CardShipping object +func (c *ProcessOut) NewCardShipping(prefill ...*CardShipping) *CardShipping { if len(prefill) > 1 { - panic("You may only provide one structure used to prefill the CardCreateRequest, or none.") + panic("You may only provide one structure used to prefill the CardShipping, or none.") } if len(prefill) == 0 { - return &CardCreateRequest{ + return &CardShipping{ client: c, } } diff --git a/project.go b/project.go index 848988d..5f9c283 100755 --- a/project.go +++ b/project.go @@ -347,220 +347,6 @@ func (s Project) DeleteWithContext(ctx context.Context, options ...ProjectDelete return nil } -// ProjectFetchSupervisedParameters is the structure representing the -// additional parameters used to call Project.FetchSupervised -type ProjectFetchSupervisedParameters struct { - *Options - *Project -} - -// FetchSupervised allows you to get all the supervised projects. -func (s Project) FetchSupervised(options ...ProjectFetchSupervisedParameters) (*Iterator, error) { - return s.FetchSupervisedWithContext(context.Background(), options...) -} - -// FetchSupervised allows you to get all the supervised projects., passes the provided context to the request -func (s Project) FetchSupervisedWithContext(ctx context.Context, options ...ProjectFetchSupervisedParameters) (*Iterator, error) { - if s.client == nil { - panic("Please use the client.NewProject() method to create a new Project object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := ProjectFetchSupervisedParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Project) - - type Response struct { - Projects []*Project `json:"projects"` - - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - }{ - Options: opt.Options, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/supervised-projects" - - req, err := http.NewRequestWithContext( - ctx, - "GET", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - projectsList := []Identifiable{} - for _, o := range payload.Projects { - projectsList = append(projectsList, o.SetClient(s.client)) - } - projectsIterator := &Iterator{ - pos: -1, - path: path, - data: projectsList, - options: opt.Options, - decoder: func(b io.Reader, i interface{}) (bool, error) { - r := struct { - Data json.RawMessage `json:"projects"` - HasMore bool `json:"has_more"` - }{} - if err := json.NewDecoder(b).Decode(&r); err != nil { - return false, err - } - if err := json.Unmarshal(r.Data, i); err != nil { - return false, err - } - return r.HasMore, nil - }, - client: s.client, - hasMoreNext: payload.HasMore, - hasMorePrev: false, - } - return projectsIterator, nil -} - -// ProjectCreateSupervisedParameters is the structure representing the -// additional parameters used to call Project.CreateSupervised -type ProjectCreateSupervisedParameters struct { - *Options - *Project - ApplepaySettings interface{} `json:"applepay_settings"` - PublicMetadata interface{} `json:"public_metadata"` -} - -// CreateSupervised allows you to create a new supervised project. -func (s Project) CreateSupervised(options ...ProjectCreateSupervisedParameters) (*Project, error) { - return s.CreateSupervisedWithContext(context.Background(), options...) -} - -// CreateSupervised allows you to create a new supervised project., passes the provided context to the request -func (s Project) CreateSupervisedWithContext(ctx context.Context, options ...ProjectCreateSupervisedParameters) (*Project, error) { - if s.client == nil { - panic("Please use the client.NewProject() method to create a new Project object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := ProjectCreateSupervisedParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Project) - - type Response struct { - Project *Project `json:"project"` - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - ID interface{} `json:"id"` - Name interface{} `json:"name"` - DefaultCurrency interface{} `json:"default_currency"` - DunningConfiguration interface{} `json:"dunning_configuration"` - ApplepaySettings interface{} `json:"applepay_settings"` - PublicMetadata interface{} `json:"public_metadata"` - }{ - Options: opt.Options, - ID: s.ID, - Name: s.Name, - DefaultCurrency: s.DefaultCurrency, - DunningConfiguration: s.DunningConfiguration, - ApplepaySettings: opt.ApplepaySettings, - PublicMetadata: opt.PublicMetadata, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/supervised-projects" - - req, err := http.NewRequestWithContext( - ctx, - "POST", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - payload.Project.SetClient(s.client) - return payload.Project, nil -} - // dummyProject is a dummy function that's only // here because some files need specific packages and some don't. // It's easier to include it for every file. In case you couldn't diff --git a/refund.go b/refund.go index d4d7219..450cc6e 100755 --- a/refund.go +++ b/refund.go @@ -129,6 +129,7 @@ func (s Refund) CreateForInvoiceWithContext(ctx context.Context, invoiceID strin Reason interface{} `json:"reason"` Information interface{} `json:"information"` InvoiceDetailIds interface{} `json:"invoice_detail_ids"` + SplitAllocations interface{} `json:"split_allocations"` Metadata interface{} `json:"metadata"` }{ Options: opt.Options, @@ -136,6 +137,7 @@ func (s Refund) CreateForInvoiceWithContext(ctx context.Context, invoiceID strin Reason: s.Reason, Information: s.Information, InvoiceDetailIds: s.InvoiceDetailIds, + SplitAllocations: s.SplitAllocations, Metadata: opt.Metadata, } @@ -425,6 +427,7 @@ func (s Refund) CreateWithContext(ctx context.Context, options ...RefundCreatePa Reason interface{} `json:"reason"` Information interface{} `json:"information"` InvoiceDetailIds interface{} `json:"invoice_detail_ids"` + SplitAllocations interface{} `json:"split_allocations"` Metadata interface{} `json:"metadata"` }{ Options: opt.Options, @@ -432,6 +435,7 @@ func (s Refund) CreateWithContext(ctx context.Context, options ...RefundCreatePa Reason: s.Reason, Information: s.Information, InvoiceDetailIds: s.InvoiceDetailIds, + SplitAllocations: s.SplitAllocations, Metadata: opt.Metadata, } diff --git a/subscription.go b/subscription.go deleted file mode 100755 index 318b7ce..0000000 --- a/subscription.go +++ /dev/null @@ -1,1486 +0,0 @@ -package processout - -import ( - "bytes" - "context" - "encoding/json" - "io" - "net/http" - "net/url" - "strings" - "time" - - "gopkg.in/processout.v5/errors" -) - -// Subscription represents the Subscription API object -type Subscription struct { - // ID is the iD of the subscription - ID *string `json:"id,omitempty"` - // Project is the project to which the subscription belongs - Project *Project `json:"project,omitempty"` - // ProjectID is the iD of the project to which the subscription belongs - ProjectID *string `json:"project_id,omitempty"` - // Plan is the plan linked to this subscription, if any - Plan *Plan `json:"plan,omitempty"` - // PlanID is the iD of the plan linked to this subscription, if any - PlanID *string `json:"plan_id,omitempty"` - // Discounts is the list of the subscription discounts - Discounts *[]*Discount `json:"discounts,omitempty"` - // Addons is the list of the subscription addons - Addons *[]*Addon `json:"addons,omitempty"` - // Transactions is the list of the subscription transactions - Transactions *[]*Transaction `json:"transactions,omitempty"` - // Customer is the customer linked to the subscription - Customer *Customer `json:"customer,omitempty"` - // CustomerID is the iD of the customer linked to the subscription - CustomerID *string `json:"customer_id,omitempty"` - // Token is the token used to capture payments on this subscription - Token *Token `json:"token,omitempty"` - // TokenID is the iD of the token used to capture payments on this subscription - TokenID *string `json:"token_id,omitempty"` - // URL is the uRL to which you may redirect your customer to activate the subscription - URL *string `json:"url,omitempty"` - // Name is the name of the subscription - Name *string `json:"name,omitempty"` - // Amount is the base amount of the subscription - Amount *string `json:"amount,omitempty"` - // BillableAmount is the amount to be paid at each billing cycle of the subscription - BillableAmount *string `json:"billable_amount,omitempty"` - // DiscountedAmount is the amount discounted by discounts applied to the subscription - DiscountedAmount *string `json:"discounted_amount,omitempty"` - // AddonsAmount is the amount applied on top of the subscription base price with addons - AddonsAmount *string `json:"addons_amount,omitempty"` - // Currency is the currency of the subscription - Currency *string `json:"currency,omitempty"` - // Metadata is the metadata related to the subscription, in the form of a dictionary (key-value pair) - Metadata *map[string]string `json:"metadata,omitempty"` - // Interval is the the subscription interval, formatted in the format "1d2w3m4y" (day, week, month, year) - Interval *string `json:"interval,omitempty"` - // TrialEndAt is the date at which the subscription trial should end. Can be null to set no trial - TrialEndAt *time.Time `json:"trial_end_at,omitempty"` - // Activated is the whether or not the subscription was activated. This field does not take into account whether or not the subscription was canceled. Use the active field to know if the subscription is currently active - Activated *bool `json:"activated,omitempty"` - // Active is the whether or not the subscription is currently active (ie activated and not cancelled) - Active *bool `json:"active,omitempty"` - // CancelAt is the date at which the subscription will automatically be canceled. Can be null - CancelAt *time.Time `json:"cancel_at,omitempty"` - // Canceled is the whether or not the subscription was canceled. The cancellation reason can be found in the cancellation_reason field - Canceled *bool `json:"canceled,omitempty"` - // CancellationReason is the reason as to why the subscription was cancelled - CancellationReason *string `json:"cancellation_reason,omitempty"` - // PendingCancellation is the whether or not the subscription is pending cancellation (meaning a cancel_at date was set) - PendingCancellation *bool `json:"pending_cancellation,omitempty"` - // ReturnURL is the uRL where the customer will be redirected upon activation of the subscription - ReturnURL *string `json:"return_url,omitempty"` - // CancelURL is the uRL where the customer will be redirected if the subscription activation was canceled - CancelURL *string `json:"cancel_url,omitempty"` - // UnpaidState is the when the subscription has unpaid invoices, defines the dunning logic of the subscription (as specified in the project settings) - UnpaidState *string `json:"unpaid_state,omitempty"` - // Sandbox is the define whether or not the subscription is in sandbox environment - Sandbox *bool `json:"sandbox,omitempty"` - // CreatedAt is the date at which the subscription was created - CreatedAt *time.Time `json:"created_at,omitempty"` - // ActivatedAt is the date at which the subscription was activated. Null if the subscription hasn't been activated yet - ActivatedAt *time.Time `json:"activated_at,omitempty"` - // IterateAt is the next iteration date, corresponding to the next billing cycle start date - IterateAt *time.Time `json:"iterate_at,omitempty"` - - client *ProcessOut -} - -// GetID implements the Identiable interface -func (s *Subscription) GetID() string { - if s.ID == nil { - return "" - } - - return *s.ID -} - -// SetClient sets the client for the Subscription object and its -// children -func (s *Subscription) SetClient(c *ProcessOut) *Subscription { - if s == nil { - return s - } - s.client = c - if s.Project != nil { - s.Project.SetClient(c) - } - if s.Plan != nil { - s.Plan.SetClient(c) - } - if s.Customer != nil { - s.Customer.SetClient(c) - } - if s.Token != nil { - s.Token.SetClient(c) - } - - return s -} - -// Prefil prefills the object with data provided in the parameter -func (s *Subscription) Prefill(c *Subscription) *Subscription { - if c == nil { - return s - } - - s.ID = c.ID - s.Project = c.Project - s.ProjectID = c.ProjectID - s.Plan = c.Plan - s.PlanID = c.PlanID - s.Discounts = c.Discounts - s.Addons = c.Addons - s.Transactions = c.Transactions - s.Customer = c.Customer - s.CustomerID = c.CustomerID - s.Token = c.Token - s.TokenID = c.TokenID - s.URL = c.URL - s.Name = c.Name - s.Amount = c.Amount - s.BillableAmount = c.BillableAmount - s.DiscountedAmount = c.DiscountedAmount - s.AddonsAmount = c.AddonsAmount - s.Currency = c.Currency - s.Metadata = c.Metadata - s.Interval = c.Interval - s.TrialEndAt = c.TrialEndAt - s.Activated = c.Activated - s.Active = c.Active - s.CancelAt = c.CancelAt - s.Canceled = c.Canceled - s.CancellationReason = c.CancellationReason - s.PendingCancellation = c.PendingCancellation - s.ReturnURL = c.ReturnURL - s.CancelURL = c.CancelURL - s.UnpaidState = c.UnpaidState - s.Sandbox = c.Sandbox - s.CreatedAt = c.CreatedAt - s.ActivatedAt = c.ActivatedAt - s.IterateAt = c.IterateAt - - return s -} - -// SubscriptionFetchAddonsParameters is the structure representing the -// additional parameters used to call Subscription.FetchAddons -type SubscriptionFetchAddonsParameters struct { - *Options - *Subscription -} - -// FetchAddons allows you to get the addons applied to the subscription. -func (s Subscription) FetchAddons(options ...SubscriptionFetchAddonsParameters) (*Iterator, error) { - return s.FetchAddonsWithContext(context.Background(), options...) -} - -// FetchAddons allows you to get the addons applied to the subscription., passes the provided context to the request -func (s Subscription) FetchAddonsWithContext(ctx context.Context, options ...SubscriptionFetchAddonsParameters) (*Iterator, error) { - if s.client == nil { - panic("Please use the client.NewSubscription() method to create a new Subscription object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := SubscriptionFetchAddonsParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Subscription) - - type Response struct { - Addons []*Addon `json:"addons"` - - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - }{ - Options: opt.Options, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/subscriptions/" + url.QueryEscape(*s.ID) + "/addons" - - req, err := http.NewRequestWithContext( - ctx, - "GET", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - addonsList := []Identifiable{} - for _, o := range payload.Addons { - addonsList = append(addonsList, o.SetClient(s.client)) - } - addonsIterator := &Iterator{ - pos: -1, - path: path, - data: addonsList, - options: opt.Options, - decoder: func(b io.Reader, i interface{}) (bool, error) { - r := struct { - Data json.RawMessage `json:"addons"` - HasMore bool `json:"has_more"` - }{} - if err := json.NewDecoder(b).Decode(&r); err != nil { - return false, err - } - if err := json.Unmarshal(r.Data, i); err != nil { - return false, err - } - return r.HasMore, nil - }, - client: s.client, - hasMoreNext: payload.HasMore, - hasMorePrev: false, - } - return addonsIterator, nil -} - -// SubscriptionFindAddonParameters is the structure representing the -// additional parameters used to call Subscription.FindAddon -type SubscriptionFindAddonParameters struct { - *Options - *Subscription -} - -// FindAddon allows you to find a subscription's addon by its ID. -func (s Subscription) FindAddon(addonID string, options ...SubscriptionFindAddonParameters) (*Addon, error) { - return s.FindAddonWithContext(context.Background(), addonID, options...) -} - -// FindAddon allows you to find a subscription's addon by its ID., passes the provided context to the request -func (s Subscription) FindAddonWithContext(ctx context.Context, addonID string, options ...SubscriptionFindAddonParameters) (*Addon, error) { - if s.client == nil { - panic("Please use the client.NewSubscription() method to create a new Subscription object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := SubscriptionFindAddonParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Subscription) - - type Response struct { - Addon *Addon `json:"addon"` - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - }{ - Options: opt.Options, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/subscriptions/" + url.QueryEscape(*s.ID) + "/addons/" + url.QueryEscape(addonID) + "" - - req, err := http.NewRequestWithContext( - ctx, - "GET", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - payload.Addon.SetClient(s.client) - return payload.Addon, nil -} - -// SubscriptionDeleteAddonParameters is the structure representing the -// additional parameters used to call Subscription.DeleteAddon -type SubscriptionDeleteAddonParameters struct { - *Options - *Subscription - Prorate interface{} `json:"prorate"` - ProrationDate interface{} `json:"proration_date"` - Preview interface{} `json:"preview"` -} - -// DeleteAddon allows you to delete an addon applied to a subscription. -func (s Subscription) DeleteAddon(addonID string, options ...SubscriptionDeleteAddonParameters) error { - return s.DeleteAddonWithContext(context.Background(), addonID, options...) -} - -// DeleteAddon allows you to delete an addon applied to a subscription., passes the provided context to the request -func (s Subscription) DeleteAddonWithContext(ctx context.Context, addonID string, options ...SubscriptionDeleteAddonParameters) error { - if s.client == nil { - panic("Please use the client.NewSubscription() method to create a new Subscription object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := SubscriptionDeleteAddonParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Subscription) - - type Response struct { - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - Prorate interface{} `json:"prorate"` - ProrationDate interface{} `json:"proration_date"` - Preview interface{} `json:"preview"` - }{ - Options: opt.Options, - Prorate: opt.Prorate, - ProrationDate: opt.ProrationDate, - Preview: opt.Preview, - } - - body, err := json.Marshal(data) - if err != nil { - return errors.New(err, "", "") - } - - path := "/subscriptions/" + url.QueryEscape(*s.ID) + "/addons/" + url.QueryEscape(addonID) + "" - - req, err := http.NewRequestWithContext( - ctx, - "DELETE", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return erri - } - - return nil -} - -// SubscriptionFetchCustomerParameters is the structure representing the -// additional parameters used to call Subscription.FetchCustomer -type SubscriptionFetchCustomerParameters struct { - *Options - *Subscription -} - -// FetchCustomer allows you to get the customer owning the subscription. -func (s Subscription) FetchCustomer(options ...SubscriptionFetchCustomerParameters) (*Customer, error) { - return s.FetchCustomerWithContext(context.Background(), options...) -} - -// FetchCustomer allows you to get the customer owning the subscription., passes the provided context to the request -func (s Subscription) FetchCustomerWithContext(ctx context.Context, options ...SubscriptionFetchCustomerParameters) (*Customer, error) { - if s.client == nil { - panic("Please use the client.NewSubscription() method to create a new Subscription object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := SubscriptionFetchCustomerParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Subscription) - - type Response struct { - Customer *Customer `json:"customer"` - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - }{ - Options: opt.Options, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/subscriptions/" + url.QueryEscape(*s.ID) + "/customers" - - req, err := http.NewRequestWithContext( - ctx, - "GET", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - payload.Customer.SetClient(s.client) - return payload.Customer, nil -} - -// SubscriptionFetchDiscountsParameters is the structure representing the -// additional parameters used to call Subscription.FetchDiscounts -type SubscriptionFetchDiscountsParameters struct { - *Options - *Subscription -} - -// FetchDiscounts allows you to get the discounts applied to the subscription. -func (s Subscription) FetchDiscounts(options ...SubscriptionFetchDiscountsParameters) (*Iterator, error) { - return s.FetchDiscountsWithContext(context.Background(), options...) -} - -// FetchDiscounts allows you to get the discounts applied to the subscription., passes the provided context to the request -func (s Subscription) FetchDiscountsWithContext(ctx context.Context, options ...SubscriptionFetchDiscountsParameters) (*Iterator, error) { - if s.client == nil { - panic("Please use the client.NewSubscription() method to create a new Subscription object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := SubscriptionFetchDiscountsParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Subscription) - - type Response struct { - Discounts []*Discount `json:"discounts"` - - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - }{ - Options: opt.Options, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/subscriptions/" + url.QueryEscape(*s.ID) + "/discounts" - - req, err := http.NewRequestWithContext( - ctx, - "GET", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - discountsList := []Identifiable{} - for _, o := range payload.Discounts { - discountsList = append(discountsList, o.SetClient(s.client)) - } - discountsIterator := &Iterator{ - pos: -1, - path: path, - data: discountsList, - options: opt.Options, - decoder: func(b io.Reader, i interface{}) (bool, error) { - r := struct { - Data json.RawMessage `json:"discounts"` - HasMore bool `json:"has_more"` - }{} - if err := json.NewDecoder(b).Decode(&r); err != nil { - return false, err - } - if err := json.Unmarshal(r.Data, i); err != nil { - return false, err - } - return r.HasMore, nil - }, - client: s.client, - hasMoreNext: payload.HasMore, - hasMorePrev: false, - } - return discountsIterator, nil -} - -// SubscriptionFindDiscountParameters is the structure representing the -// additional parameters used to call Subscription.FindDiscount -type SubscriptionFindDiscountParameters struct { - *Options - *Subscription -} - -// FindDiscount allows you to find a subscription's discount by its ID. -func (s Subscription) FindDiscount(discountID string, options ...SubscriptionFindDiscountParameters) (*Discount, error) { - return s.FindDiscountWithContext(context.Background(), discountID, options...) -} - -// FindDiscount allows you to find a subscription's discount by its ID., passes the provided context to the request -func (s Subscription) FindDiscountWithContext(ctx context.Context, discountID string, options ...SubscriptionFindDiscountParameters) (*Discount, error) { - if s.client == nil { - panic("Please use the client.NewSubscription() method to create a new Subscription object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := SubscriptionFindDiscountParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Subscription) - - type Response struct { - Discount *Discount `json:"discount"` - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - }{ - Options: opt.Options, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/subscriptions/" + url.QueryEscape(*s.ID) + "/discounts/" + url.QueryEscape(discountID) + "" - - req, err := http.NewRequestWithContext( - ctx, - "GET", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - payload.Discount.SetClient(s.client) - return payload.Discount, nil -} - -// SubscriptionDeleteDiscountParameters is the structure representing the -// additional parameters used to call Subscription.DeleteDiscount -type SubscriptionDeleteDiscountParameters struct { - *Options - *Subscription -} - -// DeleteDiscount allows you to delete a discount applied to a subscription. -func (s Subscription) DeleteDiscount(discountID string, options ...SubscriptionDeleteDiscountParameters) error { - return s.DeleteDiscountWithContext(context.Background(), discountID, options...) -} - -// DeleteDiscount allows you to delete a discount applied to a subscription., passes the provided context to the request -func (s Subscription) DeleteDiscountWithContext(ctx context.Context, discountID string, options ...SubscriptionDeleteDiscountParameters) error { - if s.client == nil { - panic("Please use the client.NewSubscription() method to create a new Subscription object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := SubscriptionDeleteDiscountParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Subscription) - - type Response struct { - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - }{ - Options: opt.Options, - } - - body, err := json.Marshal(data) - if err != nil { - return errors.New(err, "", "") - } - - path := "/subscriptions/" + url.QueryEscape(*s.ID) + "/discounts/" + url.QueryEscape(discountID) + "" - - req, err := http.NewRequestWithContext( - ctx, - "DELETE", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return erri - } - - return nil -} - -// SubscriptionFetchTransactionsParameters is the structure representing the -// additional parameters used to call Subscription.FetchTransactions -type SubscriptionFetchTransactionsParameters struct { - *Options - *Subscription -} - -// FetchTransactions allows you to get the subscriptions past transactions. -func (s Subscription) FetchTransactions(options ...SubscriptionFetchTransactionsParameters) (*Iterator, error) { - return s.FetchTransactionsWithContext(context.Background(), options...) -} - -// FetchTransactions allows you to get the subscriptions past transactions., passes the provided context to the request -func (s Subscription) FetchTransactionsWithContext(ctx context.Context, options ...SubscriptionFetchTransactionsParameters) (*Iterator, error) { - if s.client == nil { - panic("Please use the client.NewSubscription() method to create a new Subscription object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := SubscriptionFetchTransactionsParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Subscription) - - type Response struct { - Transactions []*Transaction `json:"transactions"` - - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - }{ - Options: opt.Options, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/subscriptions/" + url.QueryEscape(*s.ID) + "/transactions" - - req, err := http.NewRequestWithContext( - ctx, - "GET", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - transactionsList := []Identifiable{} - for _, o := range payload.Transactions { - transactionsList = append(transactionsList, o.SetClient(s.client)) - } - transactionsIterator := &Iterator{ - pos: -1, - path: path, - data: transactionsList, - options: opt.Options, - decoder: func(b io.Reader, i interface{}) (bool, error) { - r := struct { - Data json.RawMessage `json:"transactions"` - HasMore bool `json:"has_more"` - }{} - if err := json.NewDecoder(b).Decode(&r); err != nil { - return false, err - } - if err := json.Unmarshal(r.Data, i); err != nil { - return false, err - } - return r.HasMore, nil - }, - client: s.client, - hasMoreNext: payload.HasMore, - hasMorePrev: false, - } - return transactionsIterator, nil -} - -// SubscriptionAllParameters is the structure representing the -// additional parameters used to call Subscription.All -type SubscriptionAllParameters struct { - *Options - *Subscription -} - -// All allows you to get all the subscriptions. -func (s Subscription) All(options ...SubscriptionAllParameters) (*Iterator, error) { - return s.AllWithContext(context.Background(), options...) -} - -// All allows you to get all the subscriptions., passes the provided context to the request -func (s Subscription) AllWithContext(ctx context.Context, options ...SubscriptionAllParameters) (*Iterator, error) { - if s.client == nil { - panic("Please use the client.NewSubscription() method to create a new Subscription object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := SubscriptionAllParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Subscription) - - type Response struct { - Subscriptions []*Subscription `json:"subscriptions"` - - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - }{ - Options: opt.Options, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/subscriptions" - - req, err := http.NewRequestWithContext( - ctx, - "GET", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - subscriptionsList := []Identifiable{} - for _, o := range payload.Subscriptions { - subscriptionsList = append(subscriptionsList, o.SetClient(s.client)) - } - subscriptionsIterator := &Iterator{ - pos: -1, - path: path, - data: subscriptionsList, - options: opt.Options, - decoder: func(b io.Reader, i interface{}) (bool, error) { - r := struct { - Data json.RawMessage `json:"subscriptions"` - HasMore bool `json:"has_more"` - }{} - if err := json.NewDecoder(b).Decode(&r); err != nil { - return false, err - } - if err := json.Unmarshal(r.Data, i); err != nil { - return false, err - } - return r.HasMore, nil - }, - client: s.client, - hasMoreNext: payload.HasMore, - hasMorePrev: false, - } - return subscriptionsIterator, nil -} - -// SubscriptionCreateParameters is the structure representing the -// additional parameters used to call Subscription.Create -type SubscriptionCreateParameters struct { - *Options - *Subscription - Source interface{} `json:"source"` - CouponID interface{} `json:"coupon_id"` -} - -// Create allows you to create a new subscription for the given customer. -func (s Subscription) Create(options ...SubscriptionCreateParameters) (*Subscription, error) { - return s.CreateWithContext(context.Background(), options...) -} - -// Create allows you to create a new subscription for the given customer., passes the provided context to the request -func (s Subscription) CreateWithContext(ctx context.Context, options ...SubscriptionCreateParameters) (*Subscription, error) { - if s.client == nil { - panic("Please use the client.NewSubscription() method to create a new Subscription object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := SubscriptionCreateParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Subscription) - - type Response struct { - Subscription *Subscription `json:"subscription"` - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - PlanID interface{} `json:"plan_id"` - CancelAt interface{} `json:"cancel_at"` - Name interface{} `json:"name"` - Amount interface{} `json:"amount"` - Currency interface{} `json:"currency"` - Metadata interface{} `json:"metadata"` - Interval interface{} `json:"interval"` - TrialEndAt interface{} `json:"trial_end_at"` - CustomerID interface{} `json:"customer_id"` - ReturnURL interface{} `json:"return_url"` - CancelURL interface{} `json:"cancel_url"` - Source interface{} `json:"source"` - CouponID interface{} `json:"coupon_id"` - }{ - Options: opt.Options, - PlanID: s.PlanID, - CancelAt: s.CancelAt, - Name: s.Name, - Amount: s.Amount, - Currency: s.Currency, - Metadata: s.Metadata, - Interval: s.Interval, - TrialEndAt: s.TrialEndAt, - CustomerID: s.CustomerID, - ReturnURL: s.ReturnURL, - CancelURL: s.CancelURL, - Source: opt.Source, - CouponID: opt.CouponID, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/subscriptions" - - req, err := http.NewRequestWithContext( - ctx, - "POST", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - payload.Subscription.SetClient(s.client) - return payload.Subscription, nil -} - -// SubscriptionFindParameters is the structure representing the -// additional parameters used to call Subscription.Find -type SubscriptionFindParameters struct { - *Options - *Subscription -} - -// Find allows you to find a subscription by its ID. -func (s Subscription) Find(subscriptionID string, options ...SubscriptionFindParameters) (*Subscription, error) { - return s.FindWithContext(context.Background(), subscriptionID, options...) -} - -// Find allows you to find a subscription by its ID., passes the provided context to the request -func (s Subscription) FindWithContext(ctx context.Context, subscriptionID string, options ...SubscriptionFindParameters) (*Subscription, error) { - if s.client == nil { - panic("Please use the client.NewSubscription() method to create a new Subscription object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := SubscriptionFindParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Subscription) - - type Response struct { - Subscription *Subscription `json:"subscription"` - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - }{ - Options: opt.Options, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/subscriptions/" + url.QueryEscape(subscriptionID) + "" - - req, err := http.NewRequestWithContext( - ctx, - "GET", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - payload.Subscription.SetClient(s.client) - return payload.Subscription, nil -} - -// SubscriptionSaveParameters is the structure representing the -// additional parameters used to call Subscription.Save -type SubscriptionSaveParameters struct { - *Options - *Subscription - CouponID interface{} `json:"coupon_id"` - Source interface{} `json:"source"` - Prorate interface{} `json:"prorate"` - ProrationDate interface{} `json:"proration_date"` - Preview interface{} `json:"preview"` -} - -// Save allows you to save the updated subscription attributes. -func (s Subscription) Save(options ...SubscriptionSaveParameters) (*Subscription, error) { - return s.SaveWithContext(context.Background(), options...) -} - -// Save allows you to save the updated subscription attributes., passes the provided context to the request -func (s Subscription) SaveWithContext(ctx context.Context, options ...SubscriptionSaveParameters) (*Subscription, error) { - if s.client == nil { - panic("Please use the client.NewSubscription() method to create a new Subscription object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := SubscriptionSaveParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Subscription) - - type Response struct { - Subscription *Subscription `json:"subscription"` - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - PlanID interface{} `json:"plan_id"` - Name interface{} `json:"name"` - Amount interface{} `json:"amount"` - Interval interface{} `json:"interval"` - TrialEndAt interface{} `json:"trial_end_at"` - Metadata interface{} `json:"metadata"` - CouponID interface{} `json:"coupon_id"` - Source interface{} `json:"source"` - Prorate interface{} `json:"prorate"` - ProrationDate interface{} `json:"proration_date"` - Preview interface{} `json:"preview"` - }{ - Options: opt.Options, - PlanID: s.PlanID, - Name: s.Name, - Amount: s.Amount, - Interval: s.Interval, - TrialEndAt: s.TrialEndAt, - Metadata: s.Metadata, - CouponID: opt.CouponID, - Source: opt.Source, - Prorate: opt.Prorate, - ProrationDate: opt.ProrationDate, - Preview: opt.Preview, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/subscriptions/" + url.QueryEscape(*s.ID) + "" - - req, err := http.NewRequestWithContext( - ctx, - "PUT", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - payload.Subscription.SetClient(s.client) - return payload.Subscription, nil -} - -// SubscriptionCancelParameters is the structure representing the -// additional parameters used to call Subscription.Cancel -type SubscriptionCancelParameters struct { - *Options - *Subscription - CancelAtEnd interface{} `json:"cancel_at_end"` -} - -// Cancel allows you to cancel a subscription. The reason may be provided as well. -func (s Subscription) Cancel(options ...SubscriptionCancelParameters) (*Subscription, error) { - return s.CancelWithContext(context.Background(), options...) -} - -// Cancel allows you to cancel a subscription. The reason may be provided as well., passes the provided context to the request -func (s Subscription) CancelWithContext(ctx context.Context, options ...SubscriptionCancelParameters) (*Subscription, error) { - if s.client == nil { - panic("Please use the client.NewSubscription() method to create a new Subscription object") - } - if len(options) > 1 { - panic("The options parameter should only be provided once.") - } - - opt := SubscriptionCancelParameters{} - if len(options) == 1 { - opt = options[0] - } - if opt.Options == nil { - opt.Options = &Options{} - } - s.Prefill(opt.Subscription) - - type Response struct { - Subscription *Subscription `json:"subscription"` - HasMore bool `json:"has_more"` - Success bool `json:"success"` - Message string `json:"message"` - Code string `json:"error_type"` - } - - data := struct { - *Options - CancelAt interface{} `json:"cancel_at"` - CancellationReason interface{} `json:"cancellation_reason"` - CancelAtEnd interface{} `json:"cancel_at_end"` - }{ - Options: opt.Options, - CancelAt: s.CancelAt, - CancellationReason: s.CancellationReason, - CancelAtEnd: opt.CancelAtEnd, - } - - body, err := json.Marshal(data) - if err != nil { - return nil, errors.New(err, "", "") - } - - path := "/subscriptions/" + url.QueryEscape(*s.ID) + "" - - req, err := http.NewRequestWithContext( - ctx, - "DELETE", - Host+path, - bytes.NewReader(body), - ) - if err != nil { - return nil, errors.NewNetworkError(err) - } - setupRequest(s.client, opt.Options, req) - - res, err := s.client.HTTPClient.Do(req) - if err != nil { - return nil, errors.NewNetworkError(err) - } - payload := &Response{} - defer res.Body.Close() - if res.StatusCode >= 500 { - return nil, errors.New(nil, "", "An unexpected error occurred while processing your request.. A lot of sweat is already flowing from our developers head!") - } - err = json.NewDecoder(res.Body).Decode(payload) - if err != nil { - return nil, errors.New(err, "", "") - } - - if !payload.Success { - erri := errors.NewFromResponse(res.StatusCode, payload.Code, - payload.Message) - - return nil, erri - } - - payload.Subscription.SetClient(s.client) - return payload.Subscription, nil -} - -// dummySubscription is a dummy function that's only -// here because some files need specific packages and some don't. -// It's easier to include it for every file. In case you couldn't -// tell, everything is generated. -func dummySubscription() { - type dummy struct { - a bytes.Buffer - b json.RawMessage - c http.File - d strings.Reader - e time.Time - f url.URL - g io.Reader - } - errors.New(nil, "", "") -} diff --git a/token.go b/token.go index d77cd1d..49267fe 100755 --- a/token.go +++ b/token.go @@ -61,6 +61,8 @@ type Token struct { CanGetBalance *bool `json:"can_get_balance,omitempty"` // WebhookURL is the custom webhook URL where updates about this specific customer token will be sent, on top of your project-wide URLs WebhookURL *string `json:"webhook_url,omitempty"` + // VaultID is the iD of the Vault that customer token resides in + VaultID *string `json:"vault_id,omitempty"` client *ProcessOut } @@ -126,6 +128,7 @@ func (s *Token) Prefill(c *Token) *Token { s.VerificationStatus = c.VerificationStatus s.CanGetBalance = c.CanGetBalance s.WebhookURL = c.WebhookURL + s.VaultID = c.VaultID return s } diff --git a/transaction.go b/transaction.go index 8a8e3f1..f3cf694 100755 --- a/transaction.go +++ b/transaction.go @@ -29,10 +29,6 @@ type Transaction struct { Customer *Customer `json:"customer,omitempty"` // CustomerID is the iD of the customer that was linked to the transaction, if any CustomerID *string `json:"customer_id,omitempty"` - // Subscription is the subscription to which this transaction belongs - Subscription *Subscription `json:"subscription,omitempty"` - // SubscriptionID is the iD of the subscription to which the transaction belongs, if any - SubscriptionID *string `json:"subscription_id,omitempty"` // Token is the token that was used to capture the payment of the transaction, if any Token *Token `json:"token,omitempty"` // TokenID is the iD of the token was used to capture the payment of the transaction, if any @@ -149,6 +145,8 @@ type Transaction struct { NativeApm *NativeAPMResponse `json:"native_apm,omitempty"` // ExternalDetails is the additional data about the transaction, originating from a PSP, for example customer shipping address ExternalDetails interface{} `json:"external_details,omitempty"` + // Origin is the the origin of the transaction, can be either 'api' - processed in the ProcessOut or 'pulling' - processed outside and pulled into the system. + Origin *string `json:"origin,omitempty"` client *ProcessOut } @@ -178,9 +176,6 @@ func (s *Transaction) SetClient(c *ProcessOut) *Transaction { if s.Customer != nil { s.Customer.SetClient(c) } - if s.Subscription != nil { - s.Subscription.SetClient(c) - } if s.Token != nil { s.Token.SetClient(c) } @@ -216,8 +211,6 @@ func (s *Transaction) Prefill(c *Transaction) *Transaction { s.InvoiceID = c.InvoiceID s.Customer = c.Customer s.CustomerID = c.CustomerID - s.Subscription = c.Subscription - s.SubscriptionID = c.SubscriptionID s.Token = c.Token s.TokenID = c.TokenID s.Card = c.Card @@ -276,6 +269,7 @@ func (s *Transaction) Prefill(c *Transaction) *Transaction { s.Eci = c.Eci s.NativeApm = c.NativeApm s.ExternalDetails = c.ExternalDetails + s.Origin = c.Origin return s } diff --git a/transaction_operation.go b/transaction_operation.go index d0a430e..d9995d5 100755 --- a/transaction_operation.go +++ b/transaction_operation.go @@ -68,6 +68,8 @@ type TransactionOperation struct { ProcessedWithNetworkToken *bool `json:"processed_with_network_token,omitempty"` // PaymentType is the payment type of the transaction PaymentType *string `json:"payment_type,omitempty"` + // CaptureType is the capture type of the transaction + CaptureType *string `json:"capture_type,omitempty"` // Metadata is the metadata related to the operation, in the form of a dictionary (key-value pair) Metadata *map[string]string `json:"metadata,omitempty"` // GatewayFee is the gateway fee generated by the operation @@ -152,6 +154,7 @@ func (s *TransactionOperation) Prefill(c *TransactionOperation) *TransactionOper s.SchemeID = c.SchemeID s.ProcessedWithNetworkToken = c.ProcessedWithNetworkToken s.PaymentType = c.PaymentType + s.CaptureType = c.CaptureType s.Metadata = c.Metadata s.GatewayFee = c.GatewayFee s.CreatedAt = c.CreatedAt diff --git a/unsupported_feature_bypass.go b/unsupported_feature_bypass.go index f04cc42..69107a9 100755 --- a/unsupported_feature_bypass.go +++ b/unsupported_feature_bypass.go @@ -16,6 +16,8 @@ import ( type UnsupportedFeatureBypass struct { // IncrementalAuthorization is the indicates whether to fallback to normal authorization if incremental is not supported IncrementalAuthorization *bool `json:"incremental_authorization,omitempty"` + // SplitPayments is the indicates whether to fallback to normal payment if split payments are not supported + SplitPayments *bool `json:"split_payments,omitempty"` client *ProcessOut } @@ -38,6 +40,7 @@ func (s *UnsupportedFeatureBypass) Prefill(c *UnsupportedFeatureBypass) *Unsuppo } s.IncrementalAuthorization = c.IncrementalAuthorization + s.SplitPayments = c.SplitPayments return s }