forked from go-packages/paypal
Subscriptions, Subscription plans and Products API (#151)
This commit is contained in:
parent
b3eb2c69dd
commit
d355a65df0
40
README.md
40
README.md
|
@ -20,11 +20,6 @@ Currently supports **v2** only, if you want to use **v1**, use **v1.1.4** git ta
|
|||
* GET /v1/payment-experience/web-profiles/**ID**
|
||||
* PUT /v1/payment-experience/web-profiles/**ID**
|
||||
* DELETE /v1/payment-experience/web-profiles/**ID**
|
||||
* POST /v1/vault/credit-cards
|
||||
* DELETE /v1/vault/credit-cards/**ID**
|
||||
* PATCH /v1/vault/credit-cards/**ID**
|
||||
* GET /v1/vault/credit-cards/**ID**
|
||||
* GET /v1/vault/credit-cards
|
||||
* GET /v2/payments/authorizations/**ID**
|
||||
* POST /v2/payments/authorizations/**ID**/capture
|
||||
* POST /v2/payments/authorizations/**ID**/void
|
||||
|
@ -32,24 +27,55 @@ Currently supports **v2** only, if you want to use **v1**, use **v1.1.4** git ta
|
|||
* GET /v1/payments/sale/**ID**
|
||||
* POST /v1/payments/sale/**ID**/refund
|
||||
* GET /v2/payments/refund/**ID**
|
||||
* POST /v1/reporting/transactions
|
||||
#Vault
|
||||
* POST /v1/vault/credit-cards
|
||||
* DELETE /v1/vault/credit-cards/**ID**
|
||||
* PATCH /v1/vault/credit-cards/**ID**
|
||||
* GET /v1/vault/credit-cards/**ID**
|
||||
* GET /v1/vault/credit-cards
|
||||
#Checkout
|
||||
* POST /v2/checkout/orders
|
||||
* GET /v2/checkout/orders/**ID**
|
||||
* PATCH /v2/checkout/orders/**ID**
|
||||
* POST /v2/checkout/orders/**ID**/authorize
|
||||
* POST /v2/checkout/orders/**ID**/capture
|
||||
#Billing plans (payments)
|
||||
* GET /v1/payments/billing-plans
|
||||
* POST /v1/payments/billing-plans
|
||||
* PATCH /v1/payments/billing-plans/***ID***
|
||||
* POST /v1/payments/billing-agreements
|
||||
* POST /v1/payments/billing-agreements/***TOKEN***/agreement-execute
|
||||
#Notifications
|
||||
* POST /v1/notifications/webhooks
|
||||
* GET /v1/notifications/webhooks
|
||||
* GET /v1/notifications/webhooks/**ID**
|
||||
* PATCH /v1/notifications/webhooks/**ID**
|
||||
* DELETE /v1/notifications/webhooks/**ID**
|
||||
* POST /v1/notifications/verify-webhook-signature
|
||||
* POST /v1/reporting/transactions
|
||||
|
||||
#Products (Catalog)
|
||||
* POST /v1/catalogs/products
|
||||
* PATCH /v1/catalogs/products/**ID**
|
||||
* GET /v1/catalogs/products/**ID**
|
||||
* GET /v1/catalogs/products
|
||||
#Billing Plans (Subscriptions)
|
||||
* POST /v1/billing/plans
|
||||
* PATCH /v1/billing/plans/**ID**
|
||||
* GET /v1/billing/plans/**ID**
|
||||
* GET /v1/billing/plans
|
||||
* POST /v1/billing/plans/**ID**/activate
|
||||
* POST /v1/billing/plans/**ID**/deactivate
|
||||
* POST /v1/billing/plans/**ID**/update-pricing-schemes
|
||||
#Subscriptions
|
||||
* POST /v1/billing/subscriptions
|
||||
* PATCH /v1/billing/subscriptions/**ID**
|
||||
* GET /v1/billing/subscriptions/**ID**
|
||||
* POST /v1/billing/subscriptions/**ID**/activate
|
||||
* POST /v1/billing/subscriptions/**ID**/cancel
|
||||
* POST /v1/billing/subscriptions/**ID**/capture
|
||||
* POST /v1/billing/subscriptions/**ID**/suspend
|
||||
* GET /v1/billing/subscriptions/**ID**/transactions
|
||||
|
||||
### Missing endpoints
|
||||
It is possible that some endpoints are missing in this SDK Client, but you can use built-in **paypal** functions to perform a request: **NewClient -> NewRequest -> SendWithAuth**
|
||||
|
||||
|
|
63
billing.go
63
billing.go
|
@ -2,6 +2,7 @@ package paypal
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
@ -31,26 +32,21 @@ type (
|
|||
|
||||
// BillingPlanListParams struct
|
||||
BillingPlanListParams struct {
|
||||
Page string `json:"page,omitempty"` //Default: 0.
|
||||
Status string `json:"status,omitempty"` //Allowed values: CREATED, ACTIVE, INACTIVE, ALL.
|
||||
PageSize string `json:"page_size,omitempty"` //Default: 10.
|
||||
TotalRequired string `json:"total_required,omitempty"` //Default: no.
|
||||
|
||||
ListParams
|
||||
Status string `json:"status,omitempty"` //Allowed values: CREATED, ACTIVE, INACTIVE, ALL.
|
||||
}
|
||||
|
||||
//BillingPlanListResp struct
|
||||
BillingPlanListResp struct {
|
||||
Plans []BillingPlan `json:"plans,omitempty"`
|
||||
TotalItems string `json:"total_items,omitempty"`
|
||||
TotalPages string `json:"total_pages,omitempty"`
|
||||
Links []Link `json:"links,omitempty"`
|
||||
SharedListResponse
|
||||
Plans []BillingPlan `json:"plans,omitempty"`
|
||||
}
|
||||
)
|
||||
|
||||
// CreateBillingPlan creates a billing plan in Paypal
|
||||
// Endpoint: POST /v1/payments/billing-plans
|
||||
func (c *Client) CreateBillingPlan(plan BillingPlan) (*CreateBillingResp, error) {
|
||||
req, err := c.NewRequest("POST", fmt.Sprintf("%s%s", c.APIBase, "/v1/payments/billing-plans"), plan)
|
||||
req, err := c.NewRequest(http.MethodPost, fmt.Sprintf("%s%s", c.APIBase, "/v1/payments/billing-plans"), plan)
|
||||
response := &CreateBillingResp{}
|
||||
if err != nil {
|
||||
return response, err
|
||||
|
@ -59,18 +55,35 @@ func (c *Client) CreateBillingPlan(plan BillingPlan) (*CreateBillingResp, error)
|
|||
return response, err
|
||||
}
|
||||
|
||||
// UpdateBillingPlan updates values inside a billing plan
|
||||
// Endpoint: PATCH /v1/payments/billing-plans
|
||||
func (c *Client) UpdateBillingPlan(planId string, pathValues map[string]map[string]interface{}) error {
|
||||
patchData := []Patch{}
|
||||
for path, data := range pathValues {
|
||||
patchData = append(patchData, Patch{
|
||||
Operation: "replace",
|
||||
Path: path,
|
||||
Value: data,
|
||||
})
|
||||
}
|
||||
|
||||
jsonData, err := json.Marshal(patchData)
|
||||
buf := bytes.NewBuffer(jsonData)
|
||||
req, err := c.NewRequest(http.MethodPatch, fmt.Sprintf("%s%s%s", c.APIBase, "/v1/payments/billing-plans/", planId), buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = c.SendWithAuth(req, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
// ActivatePlan activates a billing plan
|
||||
// By default, a new plan is not activated
|
||||
// Endpoint: PATCH /v1/payments/billing-plans/
|
||||
func (c *Client) ActivatePlan(planID string) error {
|
||||
buf := bytes.NewBuffer([]byte(`[{"op":"replace","path":"/","value":{"state":"ACTIVE"}}]`))
|
||||
req, err := http.NewRequest("PATCH", fmt.Sprintf("%s%s", c.APIBase, "/v1/payments/billing-plans/"+planID), buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.SetBasicAuth(c.ClientID, c.Secret)
|
||||
req.Header.Set("Authorization", "Bearer "+c.Token.Token)
|
||||
return c.SendWithAuth(req, nil)
|
||||
return c.UpdateBillingPlan(planID, map[string]map[string]interface{}{
|
||||
"/": {"state": BillingPlanStatusActive},
|
||||
})
|
||||
}
|
||||
|
||||
// CreateBillingAgreement creates an agreement for specified plan
|
||||
|
@ -81,7 +94,7 @@ func (c *Client) CreateBillingAgreement(a BillingAgreement) (*CreateAgreementRes
|
|||
ID: a.Plan.ID,
|
||||
}
|
||||
|
||||
req, err := c.NewRequest("POST", fmt.Sprintf("%s%s", c.APIBase, "/v1/payments/billing-agreements"), a)
|
||||
req, err := c.NewRequest(http.MethodPost, fmt.Sprintf("%s%s", c.APIBase, "/v1/payments/billing-agreements"), a)
|
||||
response := &CreateAgreementResp{}
|
||||
if err != nil {
|
||||
return response, err
|
||||
|
@ -93,7 +106,7 @@ func (c *Client) CreateBillingAgreement(a BillingAgreement) (*CreateAgreementRes
|
|||
// ExecuteApprovedAgreement - Use this call to execute (complete) a PayPal agreement that has been approved by the payer.
|
||||
// Endpoint: POST /v1/payments/billing-agreements/token/agreement-execute
|
||||
func (c *Client) ExecuteApprovedAgreement(token string) (*ExecuteAgreementResponse, error) {
|
||||
req, err := http.NewRequest("POST", fmt.Sprintf("%s%s", c.APIBase, "/v1/payments/billing-agreements/"+token+"/agreement-execute"), nil)
|
||||
req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/v1/payments/billing-agreements/%s/agreement-execute", c.APIBase, token), nil)
|
||||
response := &ExecuteAgreementResponse{}
|
||||
|
||||
if err != nil {
|
||||
|
@ -118,16 +131,18 @@ func (c *Client) ExecuteApprovedAgreement(token string) (*ExecuteAgreementRespon
|
|||
// Endpoint: GET /v1/payments/billing-plans
|
||||
func (c *Client) ListBillingPlans(bplp BillingPlanListParams) (*BillingPlanListResp, error) {
|
||||
req, err := c.NewRequest("GET", fmt.Sprintf("%s%s", c.APIBase, "/v1/payments/billing-plans"), nil)
|
||||
response := &BillingPlanListResp{}
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
q := req.URL.Query()
|
||||
q.Add("page", bplp.Page)
|
||||
q.Add("page_size", bplp.PageSize)
|
||||
q.Add("status", bplp.Status)
|
||||
q.Add("total_required", bplp.TotalRequired)
|
||||
req.URL.RawQuery = q.Encode()
|
||||
response := &BillingPlanListResp{}
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
err = c.SendWithAuth(req, response)
|
||||
return response, err
|
||||
}
|
||||
|
|
79
const.go
Normal file
79
const.go
Normal file
|
@ -0,0 +1,79 @@
|
|||
package paypal
|
||||
|
||||
type SubscriptionPlanStatus string
|
||||
|
||||
const (
|
||||
SubscriptionPlanStatusCreated SubscriptionPlanStatus = "CREATED"
|
||||
SubscriptionPlanStatusInactive SubscriptionPlanStatus = "INACTIVE"
|
||||
SubscriptionPlanStatusActive SubscriptionPlanStatus = "ACTIVE"
|
||||
)
|
||||
|
||||
type BillingPlanStatus string
|
||||
|
||||
const (
|
||||
BillingPlanStatusActive BillingPlanStatus = "ACTIVE"
|
||||
)
|
||||
|
||||
type IntervalUnit string
|
||||
|
||||
const (
|
||||
IntervalUnitDay IntervalUnit = "DAY"
|
||||
IntervalUnitWeek IntervalUnit = "WEEK"
|
||||
IntervalUnitMonth IntervalUnit = "MONTH"
|
||||
IntervalUnitYear IntervalUnit = "YEAR"
|
||||
)
|
||||
|
||||
type TenureType string
|
||||
|
||||
const (
|
||||
TenureTypeRegular TenureType = "REGULAR"
|
||||
TenureTypeTrial TenureType = "TRIAL"
|
||||
)
|
||||
|
||||
type SetupFeeFailureAction string
|
||||
|
||||
const (
|
||||
SetupFeeFailureActionContinue SetupFeeFailureAction = "CONTINUE"
|
||||
SetupFeeFailureActionCancel SetupFeeFailureAction = "CANCEL"
|
||||
)
|
||||
|
||||
type ShippingPreference string
|
||||
|
||||
const (
|
||||
ShippingPreferenceGetFromFile ShippingPreference = "GET_FROM_FILE"
|
||||
ShippingPreferenceNoShipping ShippingPreference = "NO_SHIPPING"
|
||||
ShippingPreferenceSetProvidedAddress ShippingPreference = "SET_PROVIDED_ADDRESS"
|
||||
)
|
||||
|
||||
type UserAction string
|
||||
|
||||
const (
|
||||
UserActionContinue UserAction = "CONTINUE"
|
||||
UserActionSubscribeNow UserAction = "SUBSCRIBE_NOW"
|
||||
)
|
||||
|
||||
type SubscriptionStatus string
|
||||
|
||||
const (
|
||||
SubscriptionStatusApprovalPending SubscriptionStatus = "APPROVAL_PENDING"
|
||||
SubscriptionStatusApproved SubscriptionStatus = "APPROVED"
|
||||
SubscriptionStatusActive SubscriptionStatus = "ACTIVE"
|
||||
SubscriptionStatusSuspended SubscriptionStatus = "SUSPENDED"
|
||||
SubscriptionStatusCancelled SubscriptionStatus = "CANCELLED"
|
||||
SubscriptionStatusExpired SubscriptionStatus = "EXPIRED"
|
||||
)
|
||||
|
||||
//Doc: https://developer.paypal.com/docs/api/subscriptions/v1/#definition-transaction
|
||||
type SubscriptionTransactionStatus string
|
||||
const (
|
||||
SubscriptionCaptureStatusCompleted SubscriptionTransactionStatus = "COMPLETED"
|
||||
SubscriptionCaptureStatusDeclined SubscriptionTransactionStatus = "DECLINED"
|
||||
SubscriptionCaptureStatusPartiallyRefunded SubscriptionTransactionStatus = "PARTIALLY_REFUNDED"
|
||||
SubscriptionCaptureStatusPending SubscriptionTransactionStatus = "PENDING"
|
||||
SubscriptionCaptureStatusRefunded SubscriptionTransactionStatus = "REFUNDED"
|
||||
)
|
||||
|
||||
type CaptureType string
|
||||
const (
|
||||
CaptureTypeOutstandingBalance CaptureType = "OUTSTANDING_BALANCE"
|
||||
)
|
2
go.mod
2
go.mod
|
@ -1,3 +1,5 @@
|
|||
module github.com/plutov/paypal/v3
|
||||
|
||||
go 1.12
|
||||
|
||||
require github.com/stretchr/testify v1.6.0
|
||||
|
|
11
go.sum
11
go.sum
|
@ -0,0 +1,11 @@
|
|||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.6.0 h1:jlIyCplCJFULU/01vCkhKuTyc3OorI3bJFuw6obfgho=
|
||||
github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
@ -3,7 +3,9 @@
|
|||
package paypal
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// All test values are defined here
|
||||
|
@ -12,6 +14,9 @@ var testSecret = "EBoIiUSkCKeSk49hHSgTem1qnjzzJgRQHDEHvGpzlLEf_nIoJd91xu8rPOBDCd
|
|||
var testUserID = "https://www.paypal.com/webapps/auth/identity/user/VBqgHcgZwb1PBs69ybjjXfIW86_Hr93aBvF_Rgbh2II"
|
||||
var testCardID = "CARD-54E6956910402550WKGRL6EA"
|
||||
|
||||
var testProductId = "" // will be fetched in func TestProduct(t *testing.T)
|
||||
var testBillingPlan = "" // will be fetched in func TestSubscriptionPlans(t *testing.T)
|
||||
|
||||
func TestGetAccessToken(t *testing.T) {
|
||||
c, _ := NewClient(testClientID, testSecret, APIBaseSandBox)
|
||||
token, err := c.GetAccessToken()
|
||||
|
@ -212,3 +217,155 @@ func TestListWebhooks(t *testing.T) {
|
|||
t.Errorf("Cannot registered list webhooks, error %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProduct(t *testing.T) {
|
||||
c, _ := NewClient(testClientID, testSecret, APIBaseSandBox)
|
||||
c.GetAccessToken()
|
||||
|
||||
//create a product
|
||||
productData := Product{
|
||||
Name: "Test Product",
|
||||
Description: "A Test Product",
|
||||
Category: PRODUCT_CATEGORY_SOFTWARE,
|
||||
Type: PRODUCT_TYPE_SERVICE,
|
||||
ImageUrl: "https://example.com/image.png",
|
||||
HomeUrl: "https://example.com",
|
||||
}
|
||||
|
||||
productCreateResponse, err := c.CreateProduct(productData)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
testProductId = productCreateResponse.ID
|
||||
|
||||
//update the product
|
||||
productData.ID = productCreateResponse.ID
|
||||
productData.Description = "Updated product"
|
||||
|
||||
err = c.UpdateProduct(productData)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
//get product data
|
||||
productFetched, err := c.GetProduct(productData.ID)
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, productFetched.Description, "Updated product")
|
||||
|
||||
//test that lising products have more than one product
|
||||
productList, err := c.ListProducts(nil)
|
||||
assert.Equal(t, nil, err)
|
||||
assert.NotEqual(t, len(productList.Products), 0)
|
||||
}
|
||||
|
||||
func TestSubscriptionPlans(t *testing.T) {
|
||||
c, _ := NewClient(testClientID, testSecret, APIBaseSandBox)
|
||||
c.GetAccessToken()
|
||||
|
||||
//create a product
|
||||
newSubscriptionPlan := SubscriptionPlan{
|
||||
ProductId: testProductId,
|
||||
Name: "Test subscription plan",
|
||||
Status: SubscriptionPlanStatusCreated,
|
||||
Description: "Integration test subscription plan",
|
||||
BillingCycles: []BillingCycle{
|
||||
{
|
||||
PricingScheme: PricingScheme{
|
||||
Version: 1,
|
||||
FixedPrice: Money{
|
||||
Currency: "EUR",
|
||||
Value: "5",
|
||||
},
|
||||
CreateTime: time.Now(),
|
||||
UpdateTime: time.Now(),
|
||||
},
|
||||
Frequency: Frequency{
|
||||
IntervalUnit: IntervalUnitYear,
|
||||
IntervalCount: 1,
|
||||
},
|
||||
TenureType: TenureTypeRegular,
|
||||
Sequence: 1,
|
||||
TotalCycles: 0,
|
||||
},
|
||||
},
|
||||
PaymentPreferences: PaymentPreferences{
|
||||
AutoBillOutstanding: false,
|
||||
SetupFee: nil,
|
||||
SetupFeeFailureAction: SetupFeeFailureActionCancel,
|
||||
PaymentFailureThreshold: 0,
|
||||
},
|
||||
Taxes: Taxes{
|
||||
Percentage: "19",
|
||||
Inclusive: false,
|
||||
},
|
||||
QuantitySupported: false,
|
||||
}
|
||||
|
||||
//test create new plan
|
||||
planCreateResponse, err := c.CreateSubscriptionPlan(newSubscriptionPlan)
|
||||
assert.Equal(t, nil, err)
|
||||
testBillingPlan = planCreateResponse.ID // for next test
|
||||
|
||||
//test update the newly created plan
|
||||
newSubscriptionPlan.ID = planCreateResponse.ID
|
||||
newSubscriptionPlan.Description = "updated description"
|
||||
err = c.UpdateSubscriptionPlan(newSubscriptionPlan)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
//test get plan information
|
||||
existingPlan, err := c.GetSubscriptionPlan(newSubscriptionPlan.ID)
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, newSubscriptionPlan.Description, existingPlan.Description)
|
||||
|
||||
//test activate plan
|
||||
err = c.ActivateSubscriptionPlan(newSubscriptionPlan.ID)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
//test deactivate plan
|
||||
err = c.DeactivateSubscriptionPlans(newSubscriptionPlan.ID)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
//reactivate this plan for next next (subscription)
|
||||
err = c.ActivateSubscriptionPlan(newSubscriptionPlan.ID)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
//test upadte plan pricing
|
||||
err = c.UpdateSubscriptionPlanPricing(newSubscriptionPlan.ID, []PricingSchemeUpdate{
|
||||
{
|
||||
BillingCycleSequence: 1,
|
||||
PricingScheme: PricingScheme{
|
||||
Version: 1,
|
||||
FixedPrice: Money{
|
||||
Currency: "EUR",
|
||||
Value: "6",
|
||||
},
|
||||
CreateTime: time.Now(),
|
||||
UpdateTime: time.Now(),
|
||||
},
|
||||
},
|
||||
})
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
//test update pricing scheme
|
||||
updatedPricingPlan, err := c.GetSubscriptionPlan(newSubscriptionPlan.ID)
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, "6.0", updatedPricingPlan.BillingCycles[0].PricingScheme.FixedPrice.Value)
|
||||
|
||||
}
|
||||
|
||||
func TestSubscription(t *testing.T) {
|
||||
c, _ := NewClient(testClientID, testSecret, APIBaseSandBox)
|
||||
c.GetAccessToken()
|
||||
|
||||
newSubscription := SubscriptionBase{
|
||||
PlanID: testBillingPlan,
|
||||
}
|
||||
|
||||
//create new subscription
|
||||
newSubResponse, err := c.CreateSubscription(newSubscription)
|
||||
assert.Equal(t, nil, err)
|
||||
assert.NotEqual(t, "", newSubResponse.ID)
|
||||
|
||||
//get subscription details
|
||||
subDetails, err := c.GetSubscriptionDetails(newSubResponse.ID)
|
||||
assert.Equal(t, nil, err)
|
||||
assert.NotEqual(t, "", subDetails.ID)
|
||||
|
||||
}
|
||||
|
|
7
patch.go
Normal file
7
patch.go
Normal file
|
@ -0,0 +1,7 @@
|
|||
package paypal
|
||||
|
||||
type Patch struct {
|
||||
Operation string `json:"op"`
|
||||
Path string `json:"path"`
|
||||
Value interface{} `json:"value"`
|
||||
}
|
129
products.go
Normal file
129
products.go
Normal file
|
@ -0,0 +1,129 @@
|
|||
package paypal
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type (
|
||||
ProductType string
|
||||
ProductCategory string
|
||||
|
||||
// Product struct
|
||||
Product struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Description string `json:"description"`
|
||||
Category ProductCategory `json:"category,omitempty"`
|
||||
Type ProductType `json:"type"`
|
||||
ImageUrl string `json:"image_url"`
|
||||
HomeUrl string `json:"home_url"`
|
||||
}
|
||||
|
||||
CreateProductResponse struct {
|
||||
Product
|
||||
SharedResponse
|
||||
}
|
||||
|
||||
ListProductsResponse struct {
|
||||
Products []Product `json:"products"`
|
||||
SharedListResponse
|
||||
}
|
||||
|
||||
ProductListParameters struct {
|
||||
ListParams
|
||||
}
|
||||
)
|
||||
|
||||
func (self *Product) GetUpdatePatch() []Patch {
|
||||
return []Patch{
|
||||
{
|
||||
Operation: "replace",
|
||||
Path: "/description",
|
||||
Value: self.Description,
|
||||
},
|
||||
{
|
||||
Operation: "replace",
|
||||
Path: "/category",
|
||||
Value: self.Category,
|
||||
},
|
||||
{
|
||||
Operation: "replace",
|
||||
Path: "/image_url",
|
||||
Value: self.ImageUrl,
|
||||
},
|
||||
{
|
||||
Operation: "replace",
|
||||
Path: "/home_url",
|
||||
Value: self.HomeUrl,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
PRODUCT_TYPE_PHYSICAL ProductType = "PHYSICAL"
|
||||
PRODUCT_TYPE_DIGITAL ProductType = "DIGITAL"
|
||||
PRODUCT_TYPE_SERVICE ProductType = "SERVICE"
|
||||
|
||||
PRODUCT_CATEGORY_SOFTWARE ProductCategory = "software"
|
||||
)
|
||||
|
||||
// CreateProduct creates a product
|
||||
// Doc: https://developer.paypal.com/docs/api/catalog-products/v1/#products_create
|
||||
// Endpoint: POST /v1/catalogs/products
|
||||
func (c *Client) CreateProduct(product Product) (*CreateProductResponse, error) {
|
||||
req, err := c.NewRequest(http.MethodPost, fmt.Sprintf("%s%s", c.APIBase, "/v1/catalogs/products"), product)
|
||||
response := &CreateProductResponse{}
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
err = c.SendWithAuth(req, response)
|
||||
return response, err
|
||||
}
|
||||
|
||||
// UpdateProduct. updates a product information
|
||||
// Doc: https://developer.paypal.com/docs/api/catalog-products/v1/#products_patch
|
||||
// Endpoint: PATCH /v1/catalogs/products/:product_id
|
||||
func (c *Client) UpdateProduct(product Product) error {
|
||||
req, err := c.NewRequest(http.MethodPatch, fmt.Sprintf("%s%s%s", c.APIBase, "/v1/catalogs/products/", product.ID), product.GetUpdatePatch())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = c.SendWithAuth(req, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
// Get product details
|
||||
// Doc: https://developer.paypal.com/docs/api/catalog-products/v1/#products_get
|
||||
// Endpoint: GET /v1/catalogs/products/:product_id
|
||||
func (c *Client) GetProduct(productId string) (*Product, error) {
|
||||
req, err := c.NewRequest(http.MethodGet, fmt.Sprintf("%s%s%s", c.APIBase, "/v1/catalogs/products/", productId), nil)
|
||||
response := &Product{}
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
err = c.SendWithAuth(req, response)
|
||||
return response, err
|
||||
}
|
||||
|
||||
// List all products
|
||||
// Doc: https://developer.paypal.com/docs/api/catalog-products/v1/#products_list
|
||||
// Endpoint: GET /v1/catalogs/products
|
||||
func (c *Client) ListProducts(params *ProductListParameters) (*ListProductsResponse, error) {
|
||||
req, err := c.NewRequest(http.MethodGet, fmt.Sprintf("%s%s", c.APIBase, "/v1/catalogs/products"), nil)
|
||||
response := &ListProductsResponse{}
|
||||
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)
|
||||
req.URL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
err = c.SendWithAuth(req, response)
|
||||
return response, err
|
||||
}
|
176
subscription.go
176
subscription.go
|
@ -7,27 +7,110 @@ import (
|
|||
)
|
||||
|
||||
type (
|
||||
SubscriptionBase struct {
|
||||
PlanID string `json:"plan_id"`
|
||||
StartTime *JSONTime `json:"start_time,omitempty"`
|
||||
Quantity string `json:"quantity,omitempty"`
|
||||
ShippingAmount *Money `json:"shipping_amount,omitempty"`
|
||||
Subscriber *Subscriber `json:"subscriber,omitempty"`
|
||||
AutoRenewal bool `json:"auto_renewal,omitempty"`
|
||||
ApplicationContext *ApplicationContext `json:"application_context,omitempty"`
|
||||
}
|
||||
|
||||
SubscriptionDetails struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
SubscriptionStatus SubscriptionStatus `json:"status,omitempty"`
|
||||
SubscriptionStatusChangeNote string `json:"status_change_note,omitempty"`
|
||||
StatusUpdateTime time.Time `json:"status_update_time,omitempty"`
|
||||
}
|
||||
|
||||
Subscription struct {
|
||||
SubscriptionDetailResp
|
||||
}
|
||||
|
||||
// SubscriptionDetailResp struct
|
||||
SubscriptionDetailResp struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
PlanID string `json:"plan_id,omitempty"`
|
||||
StartTime time.Time `json:"start_time,omitempty"`
|
||||
Quantity string `json:"quantity,omitempty"`
|
||||
ShippingAmount ShippingAmount `json:"shipping_amount,omitempty"`
|
||||
Subscriber Subscriber `json:"subscriber,omitempty"`
|
||||
BillingInfo BillingInfo `json:"billing_info,omitempty"`
|
||||
CreateTime time.Time `json:"create_time,omitempty"`
|
||||
UpdateTime time.Time `json:"update_time,omitempty"`
|
||||
Links []Link `json:"links,omitempty"`
|
||||
Status string `json:"status,omitempty"`
|
||||
StatusUpdateTime time.Time `json:"status_update_time,omitempty"`
|
||||
SubscriptionBase
|
||||
SubscriptionDetails
|
||||
BillingInfo BillingInfo `json:"billing_info,omitempty"` // not found in documentation
|
||||
}
|
||||
|
||||
SubscriptionCaptureResponse struct {
|
||||
Status SubscriptionTransactionStatus `json:"status"`
|
||||
Id string `json:"id"`
|
||||
AmountWithBreakdown AmountWithBreakdown `json:"amount_with_breakdown"`
|
||||
PayerName Name `json:"payer_name"`
|
||||
PayerEmail string `json:"payer_email"`
|
||||
Time time.Time `json:"time"`
|
||||
}
|
||||
|
||||
//Doc: https://developer.paypal.com/docs/api/subscriptions/v1/#definition-amount_with_breakdown
|
||||
AmountWithBreakdown struct {
|
||||
GrossAmount Money `json:"gross_amount"`
|
||||
FeeAmount Money `json:"fee_amount"`
|
||||
ShippingAmount Money `json:"shipping_amount"`
|
||||
TaxAmount Money `json:"tax_amount"`
|
||||
NetAmount Money `json:"net_amount"`
|
||||
}
|
||||
|
||||
SubscriptionTransactionsParams struct {
|
||||
SubscriptionId string
|
||||
StartTime time.Time
|
||||
EndTime time.Time
|
||||
}
|
||||
|
||||
SubscriptionTransactionsResponse struct {
|
||||
Transactions []SubscriptionCaptureResponse `json:"transactions"`
|
||||
SharedListResponse
|
||||
}
|
||||
|
||||
CaptureReqeust struct {
|
||||
Note string `json:"note"`
|
||||
CaptureType CaptureType `json:"capture_type"`
|
||||
Amount Money `json:"amount"`
|
||||
}
|
||||
)
|
||||
|
||||
func (self *Subscription) GetUpdatePatch() []Patch {
|
||||
result := []Patch{
|
||||
{
|
||||
Operation: "replace",
|
||||
Path: "/billing_info/outstanding_balance",
|
||||
Value: self.BillingInfo.OutstandingBalance,
|
||||
},
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// CreateSubscriptionPlan creates a subscriptionPlan
|
||||
// Doc: https://developer.paypal.com/docs/api/subscriptions/v1/#subscriptions_create
|
||||
// Endpoint: POST /v1/billing/subscriptions
|
||||
func (c *Client) CreateSubscription(newSubscription SubscriptionBase) (*Subscription, error) {
|
||||
req, err := c.NewRequest(http.MethodPost, fmt.Sprintf("%s%s", c.APIBase, "/v1/billing/subscriptions"), newSubscription)
|
||||
response := &Subscription{}
|
||||
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/#subscriptions_patch
|
||||
// Endpoint: PATCH /v1/billing/subscriptions/:subscription_id
|
||||
func (c *Client) UpdateSubscription(updatedSubscription Subscription) error {
|
||||
req, err := c.NewRequest(http.MethodPatch, fmt.Sprintf("%s%s%s", c.APIBase, "/v1/billing/subscriptions/", updatedSubscription.ID), updatedSubscription.GetUpdatePatch())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = c.SendWithAuth(req, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
// GetSubscriptionDetails shows details for a subscription, by ID.
|
||||
// Endpoint: GET /v1/billing/subscriptions/
|
||||
func (c *Client) GetSubscriptionDetails(subscriptionID string) (*SubscriptionDetailResp, error) {
|
||||
req, err := http.NewRequest("GET", fmt.Sprintf("%s/v1/billing/subscriptions/%s", c.APIBase, subscriptionID), nil)
|
||||
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/v1/billing/subscriptions/%s", c.APIBase, subscriptionID), nil)
|
||||
response := &SubscriptionDetailResp{}
|
||||
if err != nil {
|
||||
return response, err
|
||||
|
@ -35,3 +118,70 @@ func (c *Client) GetSubscriptionDetails(subscriptionID string) (*SubscriptionDet
|
|||
err = c.SendWithAuth(req, response)
|
||||
return response, err
|
||||
}
|
||||
|
||||
// Activates the subscription.
|
||||
// Doc: https://developer.paypal.com/docs/api/subscriptions/v1/#subscriptions_activate
|
||||
// Endpoint: POST /v1/billing/subscriptions/{id}/activate
|
||||
func (c *Client) ActivateSubscription(subscriptionId, activateReason string) error {
|
||||
req, err := c.NewRequest(http.MethodPost, fmt.Sprintf("%s/v1/billing/subscriptions/%s/activate", c.APIBase, subscriptionId), map[string]string{"reason":activateReason})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = c.SendWithAuth(req, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
// Cancels the subscription.
|
||||
// Doc: https://developer.paypal.com/docs/api/subscriptions/v1/#subscriptions_cancel
|
||||
// Endpoint: POST /v1/billing/subscriptions/{id}/cancel
|
||||
func (c *Client) CancelSubscription(subscriptionId, cancelReason string) error {
|
||||
req, err := c.NewRequest(http.MethodPost, fmt.Sprintf("%s/v1/billing/subscriptions/%s/cancel", c.APIBase, subscriptionId), map[string]string{"reason": cancelReason})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = c.SendWithAuth(req, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
// Captures an authorized payment from the subscriber on the subscription.
|
||||
// Doc: https://developer.paypal.com/docs/api/subscriptions/v1/#subscriptions_capture
|
||||
// Endpoint: POST /v1/billing/subscriptions/{id}/capture
|
||||
func (c *Client) CaptureSubscription(subscriptionId string, request CaptureReqeust) (*SubscriptionCaptureResponse, error) {
|
||||
req, err := c.NewRequest(http.MethodPost, fmt.Sprintf("%s/v1/billing/subscriptions/%s/capture", c.APIBase, subscriptionId), request)
|
||||
response := &SubscriptionCaptureResponse{}
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
err = c.SendWithAuth(req, response)
|
||||
return response, err
|
||||
}
|
||||
|
||||
// Suspends the subscription.
|
||||
// Doc: https://developer.paypal.com/docs/api/subscriptions/v1/#subscriptions_suspend
|
||||
// Endpoint: POST /v1/billing/subscriptions/{id}/suspend
|
||||
func (c *Client) SuspendSubscription(subscriptionId, reason string) error {
|
||||
req, err := c.NewRequest(http.MethodPost, fmt.Sprintf("%s/v1/billing/subscriptions/%s/suspend", c.APIBase, subscriptionId), map[string]string{"reason": reason})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = c.SendWithAuth(req, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
// Lists transactions for a subscription.
|
||||
// Doc: https://developer.paypal.com/docs/api/subscriptions/v1/#subscriptions_transactions
|
||||
// Endpoint: GET /v1/billing/subscriptions/{id}/transactions
|
||||
func (c *Client) GetSubscriptionTransactions(requestParams SubscriptionTransactionsParams) (*SubscriptionTransactionsResponse, error) {
|
||||
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s/v1/billing/subscriptions/%s/transactions", c.APIBase, requestParams.SubscriptionId), nil)
|
||||
response := &SubscriptionTransactionsResponse{}
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
q := req.URL.Query()
|
||||
q.Add("start_time", requestParams.StartTime.Format(time.RFC3339Nano))
|
||||
q.Add("end_time", requestParams.EndTime.Format(time.RFC3339Nano))
|
||||
|
||||
err = c.SendWithAuth(req, response)
|
||||
return response, err
|
||||
}
|
||||
|
|
226
subscription_plan.go
Normal file
226
subscription_plan.go
Normal file
|
@ -0,0 +1,226 @@
|
|||
package paypal
|
||||
|
||||
import (
|
||||
"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 SubscriptionPlanStatus `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 (self *SubscriptionPlan) GetUpdatePatch() []Patch {
|
||||
result := []Patch{
|
||||
{
|
||||
Operation: "replace",
|
||||
Path: "/description",
|
||||
Value: self.Description,
|
||||
},
|
||||
{
|
||||
Operation: "replace",
|
||||
Path: "/payment_preferences/auto_bill_outstanding",
|
||||
Value: self.PaymentPreferences.AutoBillOutstanding,
|
||||
},
|
||||
{
|
||||
Operation: "replace",
|
||||
Path: "/payment_preferences/payment_failure_threshold",
|
||||
Value: self.PaymentPreferences.PaymentFailureThreshold,
|
||||
},
|
||||
{
|
||||
Operation: "replace",
|
||||
Path: "/payment_preferences/setup_fee_failure_action",
|
||||
Value: self.PaymentPreferences.SetupFeeFailureAction,
|
||||
},
|
||||
{
|
||||
Operation: "replace",
|
||||
Path: "/taxes/percentage",
|
||||
Value: self.Taxes.Percentage,
|
||||
},
|
||||
}
|
||||
|
||||
if self.PaymentPreferences.SetupFee != nil {
|
||||
result = append(result, Patch{
|
||||
Operation: "replace",
|
||||
Path: "/payment_preferences/setup_fee",
|
||||
Value: self.PaymentPreferences.SetupFee,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
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(newPlan SubscriptionPlan) (*CreateSubscriptionPlanResponse, error) {
|
||||
req, err := c.NewRequest(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(updatedPlan SubscriptionPlan) error {
|
||||
req, err := c.NewRequest(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(planId string) (*SubscriptionPlan, error) {
|
||||
req, err := c.NewRequest(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(params *SubscriptionPlanListParameters) (*ListProductsResponse, error) {
|
||||
req, err := c.NewRequest(http.MethodGet, fmt.Sprintf("%s%s", c.APIBase, "/v1/billing/plans"), nil)
|
||||
response := &ListProductsResponse{}
|
||||
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(planId string) error {
|
||||
req, err := c.NewRequest(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(planId string) error {
|
||||
req, err := c.NewRequest(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(planId string, pricingSchemes []PricingSchemeUpdate) error {
|
||||
req, err := c.NewRequest(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
|
||||
}
|
|
@ -30,9 +30,7 @@ type TransactionSearchResponse struct {
|
|||
EndDate JSONTime `json:"end_date"`
|
||||
LastRefreshDatetime JSONTime `json:"last_refreshed_datetime"`
|
||||
Page int `json:"page"`
|
||||
TotalItems int `json:"total_items"`
|
||||
TotalPages int `json:"total_pages"`
|
||||
Links []Link `json:"links"`
|
||||
SharedListResponse
|
||||
}
|
||||
|
||||
// ListTransactions - Use this to search PayPal transactions from the last 31 days.
|
||||
|
|
55
types.go
55
types.go
|
@ -85,11 +85,6 @@ const (
|
|||
// Possible values for `shipping_preference` in ApplicationContext
|
||||
//
|
||||
// https://developer.paypal.com/docs/api/orders/v2/#definition-application_context
|
||||
const (
|
||||
ShippingPreferenceGetFromFile string = "GET_FROM_FILE"
|
||||
ShippingPreferenceNoShipping string = "NO_SHIPPING"
|
||||
ShippingPreferenceSetProvidedAddress string = "SET_PROVIDED_ADDRESS"
|
||||
)
|
||||
|
||||
const (
|
||||
EventPaymentCaptureCompleted string = "PAYMENT.CAPTURE.COMPLETED"
|
||||
|
@ -171,14 +166,15 @@ type (
|
|||
}
|
||||
|
||||
// ApplicationContext struct
|
||||
//Doc: https://developer.paypal.com/docs/api/subscriptions/v1/#definition-application_context
|
||||
ApplicationContext struct {
|
||||
BrandName string `json:"brand_name,omitempty"`
|
||||
Locale string `json:"locale,omitempty"`
|
||||
LandingPage string `json:"landing_page,omitempty"`
|
||||
ShippingPreference string `json:"shipping_preference,omitempty"`
|
||||
UserAction string `json:"user_action,omitempty"`
|
||||
ReturnURL string `json:"return_url,omitempty"`
|
||||
CancelURL string `json:"cancel_url,omitempty"`
|
||||
BrandName string `json:"brand_name,omitempty"`
|
||||
Locale string `json:"locale,omitempty"`
|
||||
ShippingPreference ShippingPreference `json:"shipping_preference,omitempty"`
|
||||
UserAction UserAction `json:"user_action,omitempty"`
|
||||
//LandingPage string `json:"landing_page,omitempty"` // not found in documentation
|
||||
ReturnURL string `json:"return_url,omitempty"`
|
||||
CancelURL string `json:"cancel_url,omitempty"`
|
||||
}
|
||||
|
||||
// Authorization struct
|
||||
|
@ -358,10 +354,8 @@ type (
|
|||
|
||||
// CreditCards GET /v1/vault/credit-cards
|
||||
CreditCards struct {
|
||||
Items []CreditCard `json:"items"`
|
||||
Links []Link `json:"links"`
|
||||
TotalItems int `json:"total_items"`
|
||||
TotalPages int `json:"total_pages"`
|
||||
Items []CreditCard `json:"items"`
|
||||
SharedListResponse
|
||||
}
|
||||
|
||||
// CreditCardToken struct
|
||||
|
@ -829,8 +823,7 @@ type (
|
|||
|
||||
//ShippingAmount struct
|
||||
ShippingAmount struct {
|
||||
CurrencyCode string `json:"currency_code,omitempty"`
|
||||
Value string `json:"value,omitempty"`
|
||||
Money
|
||||
}
|
||||
|
||||
// ShippingAddress struct
|
||||
|
@ -857,8 +850,14 @@ type (
|
|||
}
|
||||
|
||||
// Name struct
|
||||
//Doc: https://developer.paypal.com/docs/api/subscriptions/v1/#definition-name
|
||||
Name struct {
|
||||
FullName string `json:"full_name,omitempty"`
|
||||
FullName string `json:"full_name,omitempty"`
|
||||
Suffix string `json:"suffix,omitempty"`
|
||||
Prefix string `json:"prefix,omitempty"`
|
||||
GivenName string `json:"given_name,omitempty"`
|
||||
Surname string `json:"surname,omitempty"`
|
||||
MiddleName string `json:"middle_name,omitempty"`
|
||||
}
|
||||
|
||||
// ShippingDetail struct
|
||||
|
@ -1184,6 +1183,24 @@ type (
|
|||
ShippingInfo *SearchShippingInfo `json:"shipping_info"`
|
||||
CartInfo *SearchCartInfo `json:"cart_info"`
|
||||
}
|
||||
|
||||
SharedResponse struct {
|
||||
CreateTime string `json:"create_time"`
|
||||
UpdateTime string `json:"update_time"`
|
||||
Links []Link `json:"links"`
|
||||
}
|
||||
|
||||
ListParams struct {
|
||||
Page string `json:"page,omitempty"` //Default: 0.
|
||||
PageSize string `json:"page_size,omitempty"` //Default: 10.
|
||||
TotalRequired string `json:"total_required,omitempty"` //Default: no.
|
||||
}
|
||||
|
||||
SharedListResponse struct {
|
||||
TotalItems string `json:"total_items,omitempty"`
|
||||
TotalPages string `json:"total_pages,omitempty"`
|
||||
Links []Link `json:"links,omitempty"`
|
||||
}
|
||||
)
|
||||
|
||||
// Error method implementation for ErrorResponse struct
|
||||
|
|
Loading…
Reference in New Issue
Block a user