diff --git a/checkout.go b/checkout.go index 6258c1f..15557e8 100644 --- a/checkout.go +++ b/checkout.go @@ -87,14 +87,58 @@ type CheckoutApiResponse = ApiResponse[CheckoutAttributes, ApiResponseRelationsh // CheckoutsApiResponse is the api response for a list of checkout. type CheckoutsApiResponse = ApiResponseList[CheckoutAttributes, ApiResponseRelationshipsDiscount] -// CheckoutCreateParams are parameters for creating a checkout -type CheckoutCreateParams struct { - CustomPrice int `json:"custom_price"` - EnabledVariants []int `json:"enabled_variants"` - ButtonColor string `json:"button_color"` - DiscountCode *string `json:"discount_code"` - CustomData map[string]string `json:"custom_data"` - ExpiresAt time.Time `json:"expires_at"` - StoreID string `json:"store_id"` - VariantID string `json:"variant_id"` +// CheckoutCreateDataQuantity represents variant quantities when creating checkout +type CheckoutCreateDataQuantity struct { + VariantId int `json:"variant_id"` + Quantity int `json:"quantity"` +} + +// CheckoutCreateData represents the data options for creating a checkout. +type CheckoutCreateData struct { + Email string `json:"email,omitempty"` + Name string `json:"name,omitempty"` + BillingAddressCountry string `json:"billing_address.country,omitempty"` + BillingAddressZip string `json:"billing_address.zip,omitempty"` + TaxNumber string `json:"tax_number,omitempty"` + DiscountCode string `json:"discount_code,omitempty"` + Custom map[string]any `json:"custom,omitempty"` + VariantQuantities []CheckoutCreateDataQuantity `json:"variant_quantities,omitempty"` +} + +// CheckoutCreateOptions represents the checkout options for creating a checkout. +// +// Note: We use pointers for the boolean fields as otherwise, setting them to "false" would omit them, which would +// break some of the boolean checks in the API. See: https://docs.lemonsqueezy.com/api/checkouts#create-a-checkout +type CheckoutCreateOptions struct { + Embed *bool `json:"embed,omitempty"` + Media *bool `json:"media,omitempty"` + Logo *bool `json:"logo,omitempty"` + Desc *bool `json:"desc,omitempty"` + Discount *bool `json:"discount,omitempty"` + Dark *bool `json:"dark,omitempty"` + SubscriptionPreview *bool `json:"subscription_preview,omitempty"` + ButtonColor string `json:"button_color,omitempty"` +} + +// CheckoutCreateProductOptions represents product options for creating a checkout. +type CheckoutCreateProductOptions struct { + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + Media []string `json:"media,omitempty"` + RedirectUrl string `json:"redirect_url,omitempty"` + ReceiptButtonText string `json:"receipt_button_text,omitempty"` + ReceiptLinkUrl string `json:"receipt_link_url,omitempty"` + ReceiptThankYouNote string `json:"receipt_thank_you_note,omitempty"` + EnabledVariants []int `json:"enabled_variants,omitempty"` +} + +// CheckoutCreateAttributes represents individual parameters for creating a checkout. +type CheckoutCreateAttributes struct { + CustomPrice *int `json:"custom_price,omitempty"` + ProductOptions CheckoutCreateProductOptions `json:"product_options,omitempty"` + CheckoutOptions CheckoutCreateOptions `json:"checkout_options,omitempty"` + CheckoutData CheckoutCreateData `json:"checkout_data,omitempty"` + Preview *bool `json:"preview,omitempty"` + TestMode *bool `json:"test_mode,omitempty"` + ExpiresAt *time.Time `json:"expires_at,omitempty"` } diff --git a/checkouts_service.go b/checkouts_service.go index 7b60881..0177164 100644 --- a/checkouts_service.go +++ b/checkouts_service.go @@ -4,7 +4,7 @@ import ( "context" "encoding/json" "net/http" - "time" + "strconv" ) // CheckoutsService is the API client for the `/v1/checkouts` endpoint @@ -13,39 +13,21 @@ type CheckoutsService service // Create a custom checkout. // // https://docs.lemonsqueezy.com/api/checkouts#create-a-checkout -func (service *CheckoutsService) Create(ctx context.Context, params *CheckoutCreateParams) (*CheckoutApiResponse, *Response, error) { - checkoutData := map[string]any{ - "custom": params.CustomData, - } - if params.DiscountCode != nil { - checkoutData["discount_code"] = params.DiscountCode - } - +func (service *CheckoutsService) Create(ctx context.Context, storeId int, variantId int, attributes *CheckoutCreateAttributes) (*CheckoutApiResponse, *Response, error) { payload := map[string]any{ "data": map[string]any{ - "type": "checkouts", - "attributes": map[string]any{ - "custom_price": params.CustomPrice, - "product_options": map[string]any{ - "enabled_variants": params.EnabledVariants, - }, - "checkout_options": map[string]any{ - "button_color": params.ButtonColor, - }, - "checkout_data": checkoutData, - "expires_at": params.ExpiresAt.Format(time.RFC3339), - "preview": true, - }, + "type": "checkouts", + "attributes": attributes, "relationships": map[string]any{ "store": map[string]any{ "data": map[string]any{ - "id": params.StoreID, + "id": strconv.Itoa(storeId), "type": "stores", }, }, "variant": map[string]any{ "data": map[string]any{ - "id": params.VariantID, + "id": strconv.Itoa(variantId), "type": "variants", }, }, diff --git a/checkouts_service_test.go b/checkouts_service_test.go index cb94272..77e9527 100644 --- a/checkouts_service_test.go +++ b/checkouts_service_test.go @@ -6,9 +6,10 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" + "github.com/NdoleStudio/lemonsqueezy-go/internal/helpers" "github.com/NdoleStudio/lemonsqueezy-go/internal/stubs" - "github.com/stretchr/testify/assert" ) func TestCheckoutService_Create(t *testing.T) { @@ -20,14 +21,20 @@ func TestCheckoutService_Create(t *testing.T) { client := New(WithBaseURL(server.URL)) // Act - checkout, response, err := client.Checkouts.Create(context.Background(), &CheckoutCreateParams{ - CustomPrice: 5000, - EnabledVariants: []int{1}, - ButtonColor: "#2DD272", - CustomData: map[string]string{"user_id": "123"}, - ExpiresAt: time.Now().UTC(), - StoreID: "1", - VariantID: "1", + expireAt := time.Now().UTC() + customPrice := 5000 + checkout, response, err := client.Checkouts.Create(context.Background(), 1, 1, &CheckoutCreateAttributes{ + CustomPrice: &customPrice, + ProductOptions: CheckoutCreateProductOptions{ + EnabledVariants: []int{1}, + }, + CheckoutOptions: CheckoutCreateOptions{ + ButtonColor: "2DD272", + }, + CheckoutData: CheckoutCreateData{ + Custom: map[string]any{"user_id": "123"}, + }, + ExpiresAt: &expireAt, }) // Assert @@ -50,7 +57,7 @@ func TestCheckoutService_CreateWithError(t *testing.T) { client := New(WithBaseURL(server.URL)) // Act - _, response, err := client.Checkouts.Create(context.Background(), &CheckoutCreateParams{}) + _, response, err := client.Checkouts.Create(context.Background(), 1, 1, &CheckoutCreateAttributes{}) // Assert assert.NotNil(t, err) diff --git a/discount.go b/discount.go index 86aeaf7..edeef1c 100644 --- a/discount.go +++ b/discount.go @@ -41,5 +41,5 @@ type DiscountCreateParams struct { Code string `json:"code"` Amount int `json:"amount"` AmountType string `json:"amountType"` - StoreID string `json:"storeID"` + StoreID int `json:"storeID"` } diff --git a/discounts_service.go b/discounts_service.go index c25b957..3f18459 100644 --- a/discounts_service.go +++ b/discounts_service.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "net/http" + "strconv" ) // DiscountsService is the API client for the `/v1/discounts` endpoint @@ -26,7 +27,7 @@ func (service *DiscountsService) Create(ctx context.Context, params *DiscountCre "store": map[string]any{ "data": map[string]any{ "type": "stores", - "id": params.StoreID, + "id": strconv.Itoa(params.StoreID), }, }, }, diff --git a/discounts_service_test.go b/discounts_service_test.go index b31d23b..659e46d 100644 --- a/discounts_service_test.go +++ b/discounts_service_test.go @@ -5,9 +5,10 @@ import ( "net/http" "testing" + "github.com/stretchr/testify/assert" + "github.com/NdoleStudio/lemonsqueezy-go/internal/helpers" "github.com/NdoleStudio/lemonsqueezy-go/internal/stubs" - "github.com/stretchr/testify/assert" ) func TestDiscountsService_Create(t *testing.T) { @@ -24,7 +25,7 @@ func TestDiscountsService_Create(t *testing.T) { Code: "10PERCENT", Amount: 10, AmountType: "percent", - StoreID: "1", + StoreID: 1, }) // Assert @@ -52,7 +53,7 @@ func TestDiscountsService_CreateWithError(t *testing.T) { Code: "10PERCENT", Amount: 10, AmountType: "percent", - StoreID: "1", + StoreID: 1, }) // Assert diff --git a/e2e/checkouts_service_test.go b/e2e/checkouts_service_test.go index 8339049..92712eb 100644 --- a/e2e/checkouts_service_test.go +++ b/e2e/checkouts_service_test.go @@ -2,33 +2,42 @@ package e2e import ( "context" - "fmt" "net/http" + "strconv" "testing" "time" - lemonsqueezy "github.com/NdoleStudio/lemonsqueezy-go" "github.com/stretchr/testify/assert" + + "github.com/NdoleStudio/lemonsqueezy-go" ) func TestCheckoutsService_Create(t *testing.T) { + storeID := 11559 + variantId := 36096 + expiresAt := time.Now().UTC().Add(time.Hour * 24) + customPrice := 5000 + // Act - storeID := "11559" - checkout, response, err := client.Checkouts.Create(context.Background(), &lemonsqueezy.CheckoutCreateParams{ - CustomPrice: 5000, - EnabledVariants: []int{36096}, - ButtonColor: "#2DD272", - CustomData: map[string]string{"user_id": "123"}, - ExpiresAt: time.Now().UTC().Add(time.Hour * 24), - StoreID: storeID, - VariantID: "36096", + checkout, response, err := client.Checkouts.Create(context.Background(), storeID, variantId, &lemonsqueezy.CheckoutCreateAttributes{ + CustomPrice: &customPrice, + ProductOptions: lemonsqueezy.CheckoutCreateProductOptions{ + EnabledVariants: []int{variantId}, + }, + CheckoutOptions: lemonsqueezy.CheckoutCreateOptions{ + ButtonColor: "#2DD272", + }, + CheckoutData: lemonsqueezy.CheckoutCreateData{ + Custom: map[string]any{"user_id": "123"}, + }, + ExpiresAt: &expiresAt, }) // Assert assert.Nil(t, err) assert.Equal(t, http.StatusCreated, response.HTTPResponse.StatusCode) - assert.Equal(t, storeID, fmt.Sprintf("%d", checkout.Data.Attributes.StoreID)) + assert.Equal(t, storeID, strconv.Itoa(checkout.Data.Attributes.StoreID)) } func TestCheckoutsService_Get(t *testing.T) { diff --git a/e2e/stores_service_test.go b/e2e/stores_service_test.go index 5216323..a3108c9 100644 --- a/e2e/stores_service_test.go +++ b/e2e/stores_service_test.go @@ -12,7 +12,7 @@ func TestStoreService_Get(t *testing.T) { // Setup t.Parallel() - store, response, err := client.Stores.Get(context.Background(), "11559") + store, response, err := client.Stores.Get(context.Background(), 11559) // Assert assert.Nil(t, err) diff --git a/e2e/variants_service_test.go b/e2e/variants_service_test.go index 3d677ae..30944f4 100644 --- a/e2e/variants_service_test.go +++ b/e2e/variants_service_test.go @@ -12,7 +12,7 @@ import ( func TestVariantsService_Get(t *testing.T) { // Act - variant, response, err := client.Variants.Get(context.Background(), "36095") + variant, response, err := client.Variants.Get(context.Background(), 36095) // Assert assert.Nil(t, err) diff --git a/stores_service.go b/stores_service.go index 95d21bf..0f0a2e6 100644 --- a/stores_service.go +++ b/stores_service.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "net/http" + "strconv" ) // StoresService is the API client for the `/v1/stores` endpoint @@ -12,8 +13,8 @@ type StoresService service // Get returns the store with the given ID. // // https://docs.lemonsqueezy.com/api/stores#retrieve-a-store -func (service *StoresService) Get(ctx context.Context, storeID string) (*StoreApiResponse, *Response, error) { - response, err := service.client.do(ctx, http.MethodGet, "/v1/stores/"+storeID) +func (service *StoresService) Get(ctx context.Context, storeID int) (*StoreApiResponse, *Response, error) { + response, err := service.client.do(ctx, http.MethodGet, "/v1/stores/"+strconv.Itoa(storeID)) if err != nil { return nil, response, err } diff --git a/stores_service_test.go b/stores_service_test.go index 0deab06..e421637 100644 --- a/stores_service_test.go +++ b/stores_service_test.go @@ -5,9 +5,10 @@ import ( "net/http" "testing" + "github.com/stretchr/testify/assert" + "github.com/NdoleStudio/lemonsqueezy-go/internal/helpers" "github.com/NdoleStudio/lemonsqueezy-go/internal/stubs" - "github.com/stretchr/testify/assert" ) func TestStoreService_Get(t *testing.T) { @@ -19,7 +20,7 @@ func TestStoreService_Get(t *testing.T) { client := New(WithBaseURL(server.URL)) // Act - stores, response, err := client.Stores.Get(context.Background(), "1") + stores, response, err := client.Stores.Get(context.Background(), 1) // Assert assert.Nil(t, err) @@ -41,7 +42,7 @@ func TestStoreService_GetWithError(t *testing.T) { client := New(WithBaseURL(server.URL)) // Act - _, response, err := client.Stores.Get(context.Background(), "1") + _, response, err := client.Stores.Get(context.Background(), 1) // Assert assert.NotNil(t, err) diff --git a/variants_service.go b/variants_service.go index 6310174..217ea01 100644 --- a/variants_service.go +++ b/variants_service.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "net/http" + "strconv" ) // VariantsService is the API client for the `/v1/variants` endpoint @@ -12,8 +13,8 @@ type VariantsService service // Get returns the variant with the given ID. // // https://docs.lemonsqueezy.com/api/variants#retrieve-a-variant -func (service *VariantsService) Get(ctx context.Context, variantID string) (*VariantApiResponse, *Response, error) { - response, err := service.client.do(ctx, http.MethodGet, "/v1/variants/"+variantID) +func (service *VariantsService) Get(ctx context.Context, variantID int) (*VariantApiResponse, *Response, error) { + response, err := service.client.do(ctx, http.MethodGet, "/v1/variants/"+strconv.Itoa(variantID)) if err != nil { return nil, response, err } diff --git a/variants_service_test.go b/variants_service_test.go index 6df2151..2293c3c 100644 --- a/variants_service_test.go +++ b/variants_service_test.go @@ -5,9 +5,10 @@ import ( "net/http" "testing" + "github.com/stretchr/testify/assert" + "github.com/NdoleStudio/lemonsqueezy-go/internal/helpers" "github.com/NdoleStudio/lemonsqueezy-go/internal/stubs" - "github.com/stretchr/testify/assert" ) func TestVariantsService_Get(t *testing.T) { @@ -19,7 +20,7 @@ func TestVariantsService_Get(t *testing.T) { client := New(WithBaseURL(server.URL)) // Act - variant, response, err := client.Variants.Get(context.Background(), "1") + variant, response, err := client.Variants.Get(context.Background(), 1) // Assert assert.Nil(t, err) @@ -41,7 +42,7 @@ func TestVariantsService_GetWithError(t *testing.T) { client := New(WithBaseURL(server.URL)) // Act - _, response, err := client.Variants.Get(context.Background(), "1") + _, response, err := client.Variants.Get(context.Background(), 1) // Assert assert.NotNil(t, err) diff --git a/webhook.go b/webhook.go index 76e7cf2..6b58fd3 100644 --- a/webhook.go +++ b/webhook.go @@ -4,10 +4,9 @@ import "time" // WebhookCreateParams are parameters for creating a webhook type WebhookCreateParams struct { - URL string `json:"url"` - Events []string `json:"events"` - Secret string `json:"secret"` - StoreID string `json:"store_id"` + URL string `json:"url"` + Events []string `json:"events"` + Secret string `json:"secret"` } // WebhookUpdateParams are parameters for updating a webhook diff --git a/webhooks_service.go b/webhooks_service.go index 6f13f0c..49a685c 100644 --- a/webhooks_service.go +++ b/webhooks_service.go @@ -7,6 +7,7 @@ import ( "encoding/hex" "encoding/json" "net/http" + "strconv" ) // WebhooksService is the used to verify the signature in webhook requests @@ -25,7 +26,7 @@ func (service *WebhooksService) Verify(_ context.Context, signature string, body // Create a webhook. // // https://docs.lemonsqueezy.com/api/webhooks#create-a-webhook -func (service *WebhooksService) Create(ctx context.Context, params *WebhookCreateParams) (*WebhookApiResponse, *Response, error) { +func (service *WebhooksService) Create(ctx context.Context, storeId int, params *WebhookCreateParams) (*WebhookApiResponse, *Response, error) { payload := map[string]any{ "data": map[string]any{ "type": "webhooks", @@ -38,7 +39,7 @@ func (service *WebhooksService) Create(ctx context.Context, params *WebhookCreat "store": map[string]any{ "data": map[string]any{ "type": "stores", - "id": params.StoreID, + "id": strconv.Itoa(storeId), }, }, }, diff --git a/webhooks_service_test.go b/webhooks_service_test.go index 6fec3ee..bab348f 100644 --- a/webhooks_service_test.go +++ b/webhooks_service_test.go @@ -7,8 +7,9 @@ import ( "github.com/NdoleStudio/lemonsqueezy-go/internal/helpers" - "github.com/NdoleStudio/lemonsqueezy-go/internal/stubs" "github.com/stretchr/testify/assert" + + "github.com/NdoleStudio/lemonsqueezy-go/internal/stubs" ) func TestWebhooksService_Verify(t *testing.T) { @@ -32,11 +33,10 @@ func TestWebhooksService_Create(t *testing.T) { client := New(WithBaseURL(server.URL)) // Act - webhook, response, err := client.Webhooks.Create(context.Background(), &WebhookCreateParams{ - URL: "https://mysite.com/webhooks/", - Events: []string{"order_created", "subscription_created"}, - Secret: "SIGNING_SECRET", - StoreID: "1", + webhook, response, err := client.Webhooks.Create(context.Background(), 1, &WebhookCreateParams{ + URL: "https://mysite.com/webhooks/", + Events: []string{"order_created", "subscription_created"}, + Secret: "SIGNING_SECRET", }) // Assert @@ -59,11 +59,10 @@ func TestWebhooksService_CreateWithError(t *testing.T) { client := New(WithBaseURL(server.URL)) // Act - _, response, err := client.Webhooks.Create(context.Background(), &WebhookCreateParams{ - URL: "https://mysite.com/webhooks/", - Events: []string{"order_created", "subscription_created"}, - Secret: "SIGNING_SECRET", - StoreID: "1", + _, response, err := client.Webhooks.Create(context.Background(), 1, &WebhookCreateParams{ + URL: "https://mysite.com/webhooks/", + Events: []string{"order_created", "subscription_created"}, + Secret: "SIGNING_SECRET", }) // Assert