paypal/subscription_plan.go
2024-05-27 12:36:25 +02:00

234 lines
8.6 KiB
Go

package paypal
import (
"context"
"fmt"
"net/http"
"time"
)
type (
// SubscriptionDetailResp struct
SubscriptionPlan struct {
ID string `json:"id,omitempty"`
ProductId string `json:"product_id"`
Name string `json:"name"`
Status SubscriptionPlanStatus `json:"status"`
Description string `json:"description,omitempty"`
BillingCycles []BillingCycle `json:"billing_cycles"`
PaymentPreferences *PaymentPreferences `json:"payment_preferences"`
Taxes *Taxes `json:"taxes"`
QuantitySupported bool `json:"quantity_supported"` //Indicates whether you can subscribe to this plan by providing a quantity for the goods or service.
}
// Doc https://developer.paypal.com/docs/api/subscriptions/v1/#definition-billing_cycle
BillingCycle struct {
PricingScheme PricingScheme `json:"pricing_scheme"` // The active pricing scheme for this billing cycle. A free trial billing cycle does not require a pricing scheme.
Frequency Frequency `json:"frequency"` // The frequency details for this billing cycle.
TenureType TenureType `json:"tenure_type"` // The tenure type of the billing cycle. In case of a plan having trial cycle, only 2 trial cycles are allowed per plan. The possible values are:
Sequence int `json:"sequence"` // The order in which this cycle is to run among other billing cycles. For example, a trial billing cycle has a sequence of 1 while a regular billing cycle has a sequence of 2, so that trial cycle runs before the regular cycle.
TotalCycles int `json:"total_cycles"` // The number of times this billing cycle gets executed. Trial billing cycles can only be executed a finite number of times (value between 1 and 999 for total_cycles). Regular billing cycles can be executed infinite times (value of 0 for total_cycles) or a finite number of times (value between 1 and 999 for total_cycles).
}
// Doc: https://developer.paypal.com/docs/api/subscriptions/v1/#definition-payment_preferences
PaymentPreferences struct {
AutoBillOutstanding bool `json:"auto_bill_outstanding"`
SetupFee *Money `json:"setup_fee"`
SetupFeeFailureAction SetupFeeFailureAction `json:"setup_fee_failure_action"`
PaymentFailureThreshold int `json:"payment_failure_threshold"`
}
PricingScheme struct {
Version int `json:"version"`
FixedPrice Money `json:"fixed_price"`
CreateTime time.Time `json:"create_time"`
UpdateTime time.Time `json:"update_time"`
}
PricingSchemeUpdateRequest struct {
Schemes []PricingSchemeUpdate `json:"pricing_schemes"`
}
PricingSchemeUpdate struct {
BillingCycleSequence int `json:"billing_cycle_sequence"`
PricingScheme PricingScheme `json:"pricing_scheme"`
}
//doc: https://developer.paypal.com/docs/api/subscriptions/v1/#definition-frequency
Frequency struct {
IntervalUnit IntervalUnit `json:"interval_unit"`
IntervalCount int `json:"interval_count"` //different per unit. check documentation
}
Taxes struct {
Percentage string `json:"percentage"`
Inclusive bool `json:"inclusive"`
}
CreateSubscriptionPlanResponse struct {
SubscriptionPlan
SharedResponse
}
SubscriptionPlanListParameters struct {
ProductId string `json:"product_id"`
PlanIds string `json:"plan_ids"` // Filters the response by list of plan IDs. Filter supports upto 10 plan IDs.
ListParams
}
ListSubscriptionPlansResponse struct {
Plans []SubscriptionPlan `json:"plans"`
SharedListResponse
}
)
func (p *SubscriptionPlan) GetUpdatePatch() []Patch {
result := []Patch{
{
Operation: "replace",
Path: "/description",
Value: p.Description,
},
}
if p.Taxes != nil {
result = append(result, Patch{
Operation: "replace",
Path: "/taxes/percentage",
Value: p.Taxes.Percentage,
})
}
if p.PaymentPreferences != nil {
if p.PaymentPreferences.SetupFee != nil {
result = append(result, Patch{
Operation: "replace",
Path: "/payment_preferences/setup_fee",
Value: p.PaymentPreferences.SetupFee,
},
)
}
result = append(result, []Patch{{
Operation: "replace",
Path: "/payment_preferences/auto_bill_outstanding",
Value: p.PaymentPreferences.AutoBillOutstanding,
},
{
Operation: "replace",
Path: "/payment_preferences/payment_failure_threshold",
Value: p.PaymentPreferences.PaymentFailureThreshold,
},
{
Operation: "replace",
Path: "/payment_preferences/setup_fee_failure_action",
Value: p.PaymentPreferences.SetupFeeFailureAction,
}}...)
}
return result
}
// CreateSubscriptionPlan creates a subscriptionPlan
// Doc: https://developer.paypal.com/docs/api/subscriptions/v1/#plans_create
// Endpoint: POST /v1/billing/plans
func (c *Client) CreateSubscriptionPlan(ctx context.Context, newPlan SubscriptionPlan) (*CreateSubscriptionPlanResponse, error) {
req, err := c.NewRequest(ctx, http.MethodPost, fmt.Sprintf("%s%s", c.APIBase, "/v1/billing/plans"), newPlan)
response := &CreateSubscriptionPlanResponse{}
if err != nil {
return response, err
}
err = c.SendWithAuth(req, response)
return response, err
}
// UpdateSubscriptionPlan. updates a plan
// Doc: https://developer.paypal.com/docs/api/subscriptions/v1/#plans_patch
// Endpoint: PATCH /v1/billing/plans/:plan_id
func (c *Client) UpdateSubscriptionPlan(ctx context.Context, updatedPlan SubscriptionPlan) error {
req, err := c.NewRequest(ctx, http.MethodPatch, fmt.Sprintf("%s%s%s", c.APIBase, "/v1/billing/plans/", updatedPlan.ID), updatedPlan.GetUpdatePatch())
if err != nil {
return err
}
err = c.SendWithAuth(req, nil)
return err
}
// UpdateSubscriptionPlan. updates a plan
// Doc: https://developer.paypal.com/docs/api/subscriptions/v1/#plans_get
// Endpoint: GET /v1/billing/plans/:plan_id
func (c *Client) GetSubscriptionPlan(ctx context.Context, planId string) (*SubscriptionPlan, error) {
req, err := c.NewRequest(ctx, http.MethodGet, fmt.Sprintf("%s%s%s", c.APIBase, "/v1/billing/plans/", planId), nil)
response := &SubscriptionPlan{}
if err != nil {
return response, err
}
err = c.SendWithAuth(req, response)
return response, err
}
// List all plans
// Doc: https://developer.paypal.com/docs/api/subscriptions/v1/#plans_list
// Endpoint: GET /v1/billing/plans
func (c *Client) ListSubscriptionPlans(ctx context.Context, params *SubscriptionPlanListParameters) (*ListSubscriptionPlansResponse, error) {
req, err := c.NewRequest(ctx, http.MethodGet, fmt.Sprintf("%s%s", c.APIBase, "/v1/billing/plans"), nil)
response := &ListSubscriptionPlansResponse{}
if err != nil {
return response, err
}
if params != nil {
q := req.URL.Query()
q.Add("page", params.Page)
q.Add("page_size", params.PageSize)
q.Add("total_required", params.TotalRequired)
q.Add("product_id", params.ProductId)
q.Add("plan_ids", params.PlanIds)
req.URL.RawQuery = q.Encode()
}
err = c.SendWithAuth(req, response)
return response, err
}
// Activates a plan
// Doc: https://developer.paypal.com/docs/api/subscriptions/v1/#plans_activate
// Endpoint: POST /v1/billing/plans/{id}/activate
func (c *Client) ActivateSubscriptionPlan(ctx context.Context, planId string) error {
req, err := c.NewRequest(ctx, http.MethodPost, fmt.Sprintf("%s/v1/billing/plans/%s/activate", c.APIBase, planId), nil)
if err != nil {
return err
}
err = c.SendWithAuth(req, nil)
return err
}
// Deactivates a plan
// Doc: https://developer.paypal.com/docs/api/subscriptions/v1/#plans_deactivate
// Endpoint: POST /v1/billing/plans/{id}/deactivate
func (c *Client) DeactivateSubscriptionPlans(ctx context.Context, planId string) error {
req, err := c.NewRequest(ctx, http.MethodPost, fmt.Sprintf("%s/v1/billing/plans/%s/deactivate", c.APIBase, planId), nil)
if err != nil {
return err
}
err = c.SendWithAuth(req, nil)
return err
}
// Updates pricing for a plan. For example, you can update a regular billing cycle from $5 per month to $7 per month.
// Doc: https://developer.paypal.com/docs/api/subscriptions/v1/#plans_update-pricing-schemes
// Endpoint: POST /v1/billing/plans/{id}/update-pricing-schemes
func (c *Client) UpdateSubscriptionPlanPricing(ctx context.Context, planId string, pricingSchemes []PricingSchemeUpdate) error {
req, err := c.NewRequest(ctx, http.MethodPost, fmt.Sprintf("%s/v1/billing/plans/%s/update-pricing-schemes", c.APIBase, planId), PricingSchemeUpdateRequest{
Schemes: pricingSchemes,
})
if err != nil {
return err
}
err = c.SendWithAuth(req, nil)
return err
}