Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for all checkout creation options #18

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 54 additions & 10 deletions checkout.go
Original file line number Diff line number Diff line change
@@ -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"`
}
30 changes: 6 additions & 24 deletions checkouts_service.go
Original file line number Diff line number Diff line change
@@ -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",
},
},
27 changes: 17 additions & 10 deletions checkouts_service_test.go
Original file line number Diff line number Diff line change
@@ -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)
2 changes: 1 addition & 1 deletion discount.go
Original file line number Diff line number Diff line change
@@ -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"`
}
3 changes: 2 additions & 1 deletion discounts_service.go
Original file line number Diff line number Diff line change
@@ -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),
},
},
},
7 changes: 4 additions & 3 deletions discounts_service_test.go
Original file line number Diff line number Diff line change
@@ -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
33 changes: 21 additions & 12 deletions e2e/checkouts_service_test.go
Original file line number Diff line number Diff line change
@@ -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) {
2 changes: 1 addition & 1 deletion e2e/stores_service_test.go
Original file line number Diff line number Diff line change
@@ -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)
2 changes: 1 addition & 1 deletion e2e/variants_service_test.go
Original file line number Diff line number Diff line change
@@ -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)
5 changes: 3 additions & 2 deletions stores_service.go
Original file line number Diff line number Diff line change
@@ -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
}
7 changes: 4 additions & 3 deletions stores_service_test.go
Original file line number Diff line number Diff line change
@@ -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)
5 changes: 3 additions & 2 deletions variants_service.go
Original file line number Diff line number Diff line change
@@ -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
}
7 changes: 4 additions & 3 deletions variants_service_test.go
Original file line number Diff line number Diff line change
@@ -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)
Loading
Loading