generated from NdoleStudio/go-http-client
-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
816aa18
commit fec294d
Showing
12 changed files
with
602 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
package client | ||
|
||
import "time" | ||
|
||
// CheckoutAttributes contains information about a percentage or amount discount that can be applied to an order at checkout via a code. | ||
type CheckoutAttributes struct { | ||
StoreID int `json:"store_id"` | ||
VariantID int `json:"variant_id"` | ||
CustomPrice interface{} `json:"custom_price"` | ||
ProductOptions CheckoutProductOptions `json:"product_options"` | ||
CheckoutOptions CheckoutOptions `json:"checkout_options"` | ||
CheckoutData CheckoutData `json:"checkout_data"` | ||
ExpiresAt *time.Time `json:"expires_at"` | ||
CreatedAt time.Time `json:"created_at"` | ||
UpdatedAt time.Time `json:"updated_at"` | ||
TestMode bool `json:"test_mode"` | ||
URL string `json:"url"` | ||
} | ||
|
||
// CheckoutProductOptions are options for a checkout product | ||
type CheckoutProductOptions struct { | ||
Name string `json:"name"` | ||
Description string `json:"description"` | ||
Media []any `json:"media"` | ||
RedirectURL string `json:"redirect_url"` | ||
ReceiptButtonText string `json:"receipt_button_text"` | ||
ReceiptLinkURL string `json:"receipt_link_url"` | ||
ReceiptThankYouNote string `json:"receipt_thank_you_note"` | ||
EnabledVariants []int `json:"enabled_variants"` | ||
} | ||
|
||
// CheckoutOptions are options for a checkout | ||
type CheckoutOptions struct { | ||
Embed bool `json:"embed"` | ||
Media bool `json:"media"` | ||
Logo bool `json:"logo"` | ||
Desc bool `json:"desc"` | ||
Discount bool `json:"discount"` | ||
Dark bool `json:"dark"` | ||
SubscriptionPreview bool `json:"subscription_preview"` | ||
ButtonColor string `json:"button_color"` | ||
} | ||
|
||
// BillingAddress contains the checkout billing address | ||
type BillingAddress struct { | ||
Country string `json:"country"` | ||
Zip string `json:"zip"` | ||
} | ||
|
||
// CheckoutData contains information about a checkout | ||
type CheckoutData struct { | ||
Email string `json:"email"` | ||
Name string `json:"name"` | ||
BillingAddress []BillingAddress `json:"billing_address"` | ||
TaxNumber string `json:"tax_number"` | ||
DiscountCode string `json:"discount_code"` | ||
Custom map[string]any `json:"custom"` | ||
} | ||
|
||
// CheckoutPreview contains information about a percentage or amount discount that can be applied to an order at checkout via a code. | ||
type CheckoutPreview struct { | ||
Currency string `json:"currency"` | ||
CurrencyRate int `json:"currency_rate"` | ||
Subtotal int `json:"subtotal"` | ||
DiscountTotal int `json:"discount_total"` | ||
Tax int `json:"tax"` | ||
Total int `json:"total"` | ||
SubtotalUsd int `json:"subtotal_usd"` | ||
DiscountTotalUsd int `json:"discount_total_usd"` | ||
TaxUsd int `json:"tax_usd"` | ||
TotalUsd int `json:"total_usd"` | ||
SubtotalFormatted string `json:"subtotal_formatted"` | ||
DiscountTotalFormatted string `json:"discount_total_formatted"` | ||
TaxFormatted string `json:"tax_formatted"` | ||
TotalFormatted string `json:"total_formatted"` | ||
} | ||
|
||
// ApiResponseRelationshipsCheckout relationships of a checkout | ||
type ApiResponseRelationshipsCheckout struct { | ||
Store ApiResponseLinks `json:"store"` | ||
Variant ApiResponseLinks `json:"variant"` | ||
} | ||
|
||
// CheckoutApiResponse is the api response for one checkout | ||
type CheckoutApiResponse = ApiResponse[CheckoutAttributes, ApiResponseRelationshipsDiscount] | ||
|
||
// 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"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
package client | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"net/http" | ||
"time" | ||
) | ||
|
||
// CheckoutsService is the API client for the `/v1/checkouts` endpoint | ||
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 | ||
} | ||
|
||
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, | ||
}, | ||
"relationships": map[string]any{ | ||
"store": map[string]any{ | ||
"data": map[string]any{ | ||
"id": params.StoreID, | ||
"type": "stores", | ||
}, | ||
}, | ||
"variant": map[string]any{ | ||
"data": map[string]any{ | ||
"id": params.VariantID, | ||
"type": "variants", | ||
}, | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
response, err := service.client.do(ctx, http.MethodPost, "/v1/checkouts", payload) | ||
if err != nil { | ||
return nil, response, err | ||
} | ||
|
||
checkout := new(CheckoutApiResponse) | ||
if err = json.Unmarshal(*response.Body, checkout); err != nil { | ||
return nil, response, err | ||
} | ||
|
||
return checkout, response, nil | ||
} | ||
|
||
// Get the checkout with the given ID. | ||
// | ||
// https://docs.lemonsqueezy.com/api/checkouts#retrieve-a-checkout | ||
func (service *CheckoutsService) Get(ctx context.Context, checkoutID string) (*CheckoutApiResponse, *Response, error) { | ||
response, err := service.client.do(ctx, http.MethodGet, "/v1/checkouts/"+checkoutID) | ||
if err != nil { | ||
return nil, response, err | ||
} | ||
|
||
checkout := new(CheckoutApiResponse) | ||
if err = json.Unmarshal(*response.Body, checkout); err != nil { | ||
return nil, response, err | ||
} | ||
|
||
return checkout, response, nil | ||
} | ||
|
||
// List returns a paginated list of checkouts. | ||
// | ||
// https://docs.lemonsqueezy.com/api/checkouts#list-all-checkouts | ||
func (service *CheckoutsService) List(ctx context.Context) (*CheckoutsApiResponse, *Response, error) { | ||
response, err := service.client.do(ctx, http.MethodGet, "/v1/checkouts") | ||
if err != nil { | ||
return nil, response, err | ||
} | ||
|
||
checkouts := new(CheckoutsApiResponse) | ||
if err = json.Unmarshal(*response.Body, checkouts); err != nil { | ||
return nil, response, err | ||
} | ||
|
||
return checkouts, response, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
package client | ||
|
||
import ( | ||
"context" | ||
"net/http" | ||
"testing" | ||
"time" | ||
|
||
"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) { | ||
// Setup | ||
t.Parallel() | ||
|
||
// Arrange | ||
server := helpers.MakeTestServer(http.StatusCreated, stubs.CheckoutGetResponse()) | ||
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", | ||
}) | ||
|
||
// Assert | ||
assert.Nil(t, err) | ||
|
||
assert.Equal(t, http.StatusCreated, response.HTTPResponse.StatusCode) | ||
assert.Equal(t, stubs.CheckoutGetResponse(), *response.Body) | ||
assert.Equal(t, "5e8b546c-c561-4a2c-a586-40c18bb2a195", checkout.Data.ID) | ||
|
||
// Teardown | ||
server.Close() | ||
} | ||
|
||
func TestCheckoutService_CreateWithError(t *testing.T) { | ||
// Setup | ||
t.Parallel() | ||
|
||
// Arrange | ||
server := helpers.MakeTestServer(http.StatusInternalServerError, nil) | ||
client := New(WithBaseURL(server.URL)) | ||
|
||
// Act | ||
_, response, err := client.Checkouts.Create(context.Background(), &CheckoutCreateParams{}) | ||
|
||
// Assert | ||
assert.NotNil(t, err) | ||
|
||
assert.Equal(t, http.StatusInternalServerError, response.HTTPResponse.StatusCode) | ||
|
||
// Teardown | ||
server.Close() | ||
} | ||
|
||
func TestCheckoutService_Get(t *testing.T) { | ||
// Setup | ||
t.Parallel() | ||
|
||
// Arrange | ||
server := helpers.MakeTestServer(http.StatusOK, stubs.CheckoutGetResponse()) | ||
client := New(WithBaseURL(server.URL)) | ||
|
||
// Act | ||
checkout, response, err := client.Checkouts.Get(context.Background(), "1") | ||
|
||
// Assert | ||
assert.Nil(t, err) | ||
|
||
assert.Equal(t, http.StatusOK, response.HTTPResponse.StatusCode) | ||
assert.Equal(t, stubs.CheckoutGetResponse(), *response.Body) | ||
assert.Equal(t, "5e8b546c-c561-4a2c-a586-40c18bb2a195", checkout.Data.ID) | ||
|
||
// Teardown | ||
server.Close() | ||
} | ||
|
||
func TestCheckoutService_GetWithError(t *testing.T) { | ||
// Setup | ||
t.Parallel() | ||
|
||
// Arrange | ||
server := helpers.MakeTestServer(http.StatusInternalServerError, nil) | ||
client := New(WithBaseURL(server.URL)) | ||
|
||
// Act | ||
_, response, err := client.Checkouts.Get(context.Background(), "1") | ||
|
||
// Assert | ||
assert.NotNil(t, err) | ||
|
||
assert.Equal(t, http.StatusInternalServerError, response.HTTPResponse.StatusCode) | ||
|
||
// Teardown | ||
server.Close() | ||
} | ||
|
||
func TestCheckoutService_List(t *testing.T) { | ||
// Setup | ||
t.Parallel() | ||
|
||
// Arrange | ||
server := helpers.MakeTestServer(http.StatusOK, stubs.CheckoutListResponse()) | ||
client := New(WithBaseURL(server.URL)) | ||
|
||
// Act | ||
checkouts, response, err := client.Checkouts.List(context.Background()) | ||
|
||
// Assert | ||
assert.Nil(t, err) | ||
|
||
assert.Equal(t, http.StatusOK, response.HTTPResponse.StatusCode) | ||
assert.Equal(t, stubs.CheckoutListResponse(), *response.Body) | ||
assert.Equal(t, 1, len(checkouts.Data)) | ||
|
||
// Teardown | ||
server.Close() | ||
} | ||
|
||
func TestCheckoutService_ListWithError(t *testing.T) { | ||
// Setup | ||
t.Parallel() | ||
|
||
// Arrange | ||
server := helpers.MakeTestServer(http.StatusInternalServerError, nil) | ||
client := New(WithBaseURL(server.URL)) | ||
|
||
// Act | ||
_, response, err := client.Checkouts.List(context.Background()) | ||
|
||
// Assert | ||
assert.NotNil(t, err) | ||
|
||
assert.Equal(t, http.StatusInternalServerError, response.HTTPResponse.StatusCode) | ||
|
||
// Teardown | ||
server.Close() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.