Skip to content

Commit

Permalink
Ben/commerce feature plans (#364)
Browse files Browse the repository at this point in the history
* chore: Remove the Github PR template (#211) (#212)

The PR template is probably not needed.

* feat: Ability to configure a SAML Connection via IdP Metadata URL

Some IdP providers, expose a metadata url which contains all their necessary
information in order to configure an integration. We update our SAML Connection
Create & Update operations to accept this new url as the 'idp_metadata_url'
property

* fix: Add URL to actor token responses (#217)

Added the ActorTokenResponse.URL field.

* feat: Support define SAML Connection Attribute mapping

As part of the SAML Connection Create and Update operations, allow to define
the attribute mapping of IdP properties to Clerk's user properties

* feat: Add create session token given a template slug endpoint

* feat: Introduce 'allow_subdomains' SAML Connection property

We now expose a new property 'allow_subdomains' as part of the SAML Connection
response. You can also define it during the Update operation.
Default value is false

* feat: Introduce 'allow_idp_initiated' SAML Connection property

We now expose a new property 'allow_idp_initiated' as part of the SAML
Connection response. You can also define it during the Update operation.
Default value is false

* chore: add github action for semgrep to run security scans in monitoring mode (#264)

* feat: Allow SAML Connection configuration with IdP Metadata

Our SAML Connection Create/Update operations now accepts a new optional property
'IdpMetadata' which you can use in order to configure an IdP using the metadata
file. If provided, we also include it in the response as well

* feat: Add `external_account_id` to OAuth access token response (#274)

* feat: Support reply to email name for templates

* chore: Update CODEOWNERS

* docs: changing clerk hiring page

* Add IgnoreDotsForGmailAddresses on SDK restriction resource (#291)

* feat: add IgnoreDotsForGmailAddresses restriction on sdk

* test: IgnoreDotsForGmailAddresses restriction

* feat: Add SAMLAccounts for users (#299)

Backporting the SAMLAccounts field on the User struct for v1.

* sessions.go: Fix typo in tokens url for CreateTokenFromTemplate

This URL can be found here: https://clerk.com/docs/reference/backend-api/tag/Sessions#operation/CreateSessionTokenFromTemplate

* sessions_test.go: Update CreateTokenFromTemplate URL for integration tests

* chore: merge

* chore(commerce): revert accidental merge with wrong branch

* chore(commerce): more reverts for bad merge

* feat(commerce): add features to plan

* feat(commerce): feature responses

* feat(commerce): feature inputs

* fix(commerce): add missing fields

* feat(commerce): delete plan feature ids

* fix(commerce): update params name

* fix for deleting PlanFeatures

* feat(commerce): add payee types

* fix(commerce): fix payees package name

* update some payee types

* feat(commerce): add payers

* feat(commerce): add payment sources

* feat(commerce): payment source params

* fix(commerce): single feature create

* fix(commerce): change to payer

* add is_free to plan

* feat(commerce): missing fields

* feat(commerce): string dates to ms

---------

Co-authored-by: Giannis Katsanos <[email protected]>
Co-authored-by: Haris Chaniotakis <[email protected]>
Co-authored-by: Roberto Garcia Navarro <[email protected]>
Co-authored-by: Ross Nanopoulos <[email protected]>
Co-authored-by: Konstantinos Pittas <[email protected]>
Co-authored-by: Mary Zhong <[email protected]>
Co-authored-by: pedroimpulcetto <[email protected]>
Co-authored-by: nicolas lopes <[email protected]>
Co-authored-by: Shashank Verma <[email protected]>
Co-authored-by: Michael Osuna Jr <[email protected]>
Co-authored-by: Keiran Flanigan <[email protected]>
  • Loading branch information
12 people authored Jan 7, 2025
1 parent fa24797 commit 7584b41
Show file tree
Hide file tree
Showing 11 changed files with 522 additions and 57 deletions.
190 changes: 135 additions & 55 deletions commerce.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ type CreateProductParams struct {
Name string `json:"name"`
Slug string `json:"slug"`
Currency string `json:"currency"`
SubscriberType []string `json:"subscriber_type"`
PayerType []string `json:"payer_type"`
OwnerEntityType string `json:"owner_entity_type"`
}

type UpdateProductParams struct {
APIParams
Name *string `json:"name,omitempty"`
Slug *string `json:"slug,omitempty"`
Currency *string `json:"currency,omitempty"`
SubscriberType *[]string `json:"subscriber_type,omitempty"`
Name *string `json:"name,omitempty"`
Slug *string `json:"slug,omitempty"`
Currency *string `json:"currency,omitempty"`
PayerType *[]string `json:"payer_type,omitempty"`
}

type GetProductByIDParams struct {
Expand All @@ -36,10 +36,10 @@ type CommerceProduct struct {
Slug string `json:"slug"`
Currency string `json:"currency"`
Plans []*CommercePlan `json:"plans"`
SubscriberType []string `json:"subscriber_type"`
PayerType []string `json:"payer_type"`
OwnerEntityType string `json:"owner_entity_type"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"`
}

type CommerceProductWithPlans struct {
Expand All @@ -62,10 +62,20 @@ type CommerceFeatureUnitPricing struct {
Qty int `json:"qty"`
}

type CommercePlanFeature struct {
APIResource
ID string `json:"id"`
PlanID string `json:"plan_id"`
FeatureID string `json:"feature_id"`
CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"`
}

type CommercePlanFeatureList PaginatedList[CommercePlanFeature]

type CommerceFeature struct {
APIResource
ID string `json:"id"`
PlanID string `json:"plan_id"`
Name string `json:"name"`
Description string `json:"description"`
AvatarURL string `json:"avatar_url"`
Expand All @@ -82,17 +92,34 @@ type CommerceFeature struct {
HasTrialUnits bool `json:"has_trial_units"`
TrialUnits int `json:"trial_units"`
UnitPricing []CommerceFeatureUnitPricing `json:"unit_pricing"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"`
}

type CommerceFeatureList PaginatedList[CommerceFeature]

type CreatePlanFeatureParams struct {
APIParams
PlanID string `json:"plan_id"`
FeatureID string `json:"feature_id"`
}

type CreateMultiplePlanFeaturesParams struct {
APIParams
PlanID string `json:"plan_id"`
FeatureIDs []string `json:"feature_ids"`
}

type DeletePlanFeaturesParams struct {
APIParams
FeatureIDs []string `json:"feature_ids"`
PlanID string `json:"plan_id"`
}

type CreateFeatureParams struct {
APIParams
Name string `json:"name"`
Description string `json:"description"`
PlanID string `json:"plan_id"`
AvatarURL string `json:"avatar_url"`
Slug string `json:"slug"`
PubliclyVisible bool `json:"publicly_visible"`
Expand All @@ -108,6 +135,11 @@ type CreateFeatureParams struct {
UnitPricing []CommerceFeatureUnitPricing `json:"unit_pricing"`
}

type CreateMultipleFeaturesParams struct {
APIParams
Features []CreateFeatureParams `json:"features"`
}

type UpdateFeatureParams struct {
APIParams
ID string `json:"id"`
Expand Down Expand Up @@ -144,9 +176,11 @@ type CreatePlanParams struct {
APIParams
Name string `json:"name"`
ProductID string `json:"product_id"`
Slug string `json:"slug"`
Amount int64 `json:"amount"`
IsRecurring bool `json:"is_recurring"`
IsProrated bool `json:"is_prorated"`
IsFree bool `json:"is_free"`
Period string `json:"period"`
Interval int `json:"interval"`
AvatarURL string `json:"avatar_url"`
Expand All @@ -158,8 +192,11 @@ type UpdatePlanParams struct {
ID string `json:"id"`
Name *string `json:"name,omitempty"`
Amount *int64 `json:"amount,omitempty"`
Slug *string `json:"slug,omitempty"`
IsRecurring *bool `json:"is_recurring,omitempty"`
Description *string `json:"description,omitempty"`
IsProrated *bool `json:"is_prorated,omitempty"`
IsFree bool `json:"is_free"`
Period *string `json:"period,omitempty"`
Interval *int `json:"interval,omitempty"`
AvatarURL *string `json:"avatar_url,omitempty"`
Expand All @@ -172,22 +209,25 @@ type GetPlanByIDParams struct {

type CommercePlan struct {
APIResource
ID string `json:"id"`
Name string `json:"name"`
Product *CommerceProduct `json:"product,omitempty"`
Amount int64 `json:"amount"`
IsRecurring bool `json:"is_recurring"`
IsProrated bool `json:"is_prorated"`
Period string `json:"period"`
Interval int `json:"interval"`
AvatarURL string `json:"avatar_url"`
ProductID string `json:"product_id"`
Description string `json:"description"`
Slug string `json:"slug"`
BillingCycles *int `json:"billing_cycles,omitempty"`
SubscriberCount int64 `json:"subscriber_count"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
ID string `json:"id"`
Name string `json:"name"`
Product *CommerceProduct `json:"product,omitempty"`
Amount int64 `json:"amount"`
IsRecurring bool `json:"is_recurring"`
IsProrated bool `json:"is_prorated"`
IsFree bool `json:"is_free"`
IsDefault bool `json:"is_default"`
Period string `json:"period"`
Interval int `json:"interval"`
AvatarURL string `json:"avatar_url"`
ProductID string `json:"product_id"`
Description string `json:"description"`
Slug string `json:"slug"`
BillingCycles *int `json:"billing_cycles,omitempty"`
PayerCount int64 `json:"payer_count"`
CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"`
Features []CommerceFeature `json:"features"`
}

type CommercePlanWithNoProduct struct {
Expand All @@ -205,7 +245,7 @@ type ListPlansByInstanceIDParams struct {

type CreateSubscriptionParams struct {
APIParams
CustomerID string `json:"customer_id"`
PayerID string `json:"payer_id"`
PlanID string `json:"plan_id"`
PaymentSourceID string `json:"payment_source_id"`
}
Expand All @@ -222,52 +262,87 @@ type GetSubscriptionByIDParams struct {

type ListSubscriptionsByUserIDParams struct {
APIParams
ID string `json:"id"`
SubscriberType string `json:"subscriber_type"`
ID string `json:"id"`
PayerType string `json:"payer_type"`
}

type CommerceSubscription struct {
APIResource
ID string `json:"id"`
AppID string `json:"app_id"`
Customer *CommerceCustomer `json:"customer,omitempty"`
InstanceID string `json:"instance_id"`
PaymentSourceID string `json:"payment_source_id"`
PlanID string `json:"plan_id"`
Plan *CommercePlan `json:"plan,omitempty"`
Status string `json:"status"`
LastInvoice *CommerceInvoice `json:"last_invoice,omitempty"`
NextInvoice *CommerceInvoice `json:"next_invoice,omitempty"`
CreatedAt string `json:"created_at"` // ISO 8601 format
UpdatedAt string `json:"updated_at"` // ISO 8601 format
ID string `json:"id"`
AppID string `json:"app_id"`
Payer *CommercePayer `json:"payer,omitempty"`
InstanceID string `json:"instance_id"`
PaymentSourceID string `json:"payment_source_id"`
PlanID string `json:"plan_id"`
Plan *CommercePlan `json:"plan,omitempty"`
Status string `json:"status"`
LastInvoice *CommerceInvoice `json:"last_invoice,omitempty"`
NextInvoice *CommerceInvoice `json:"next_invoice,omitempty"`
CreatedAt int64 `json:"created_at"` // ISO 8601 format
UpdatedAt int64 `json:"updated_at"` // ISO 8601 format
}

type ListCommerceSubscriptionsResponse struct {
APIResource
PaginatedList[CommerceSubscription]
}

type CreatePaymentSourceParams struct {
APIParams
PayerID string `json:"payer_id"`
Gateway string `json:"gateway"`
PayeeID string `json:"payee_id"`
ExternalID string `json:"external_id"`
Last4 string `json:"last4"`
CardType string `json:"card_type"`
}

type CommercePaymentSource struct {
APIResource
ID string `json:"id"`
PayerID string `json:"payer_id"`
Gateway string `json:"gateway"`
PayeeID string `json:"payee_id"`
ExternalID string `json:"external_id"`
CardType string `json:"card_type"`
LastFour string `json:"last4"`
CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"`
}

type CommercePaymentSourceList PaginatedList[CommercePaymentSource]

// --- Subscription Types ---

type GetSubscriptionParams struct {
APIParams
ID string `json:"id"`
}

type ListSubscribersParams struct {
type ListPayersParams struct {
APIParams
InstanceID string `json:"instance_id"`
}

type CommerceSubscriber struct {
type CommercePayer struct {
APIResource
ID string `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}

type ListCommerceSubscribersResponse struct {
type CommercePayerList PaginatedList[CommercePayer]

type CreatePayerParams struct {
APIParams
InstanceID string `json:"instance_id"`
Name string `json:"name"`
Email string `json:"email"`
}

type ListCommercePayersResponse struct {
APIResource
PaginatedList[CommerceSubscriber]
PaginatedList[CommercePayer]
}

// Supporting structs for emails
Expand Down Expand Up @@ -304,13 +379,18 @@ type ListCommercePaymentAttemptsResponse struct {
PaginatedList[CommercePaymentAttempt]
}

// --- Customer Types ---
// --- Payee Types ---

type CommercePayee struct {
APIResource

type CommerceCustomer struct {
ID string `json:"id"`
AppID string `json:"app_id"`
Entity *struct {
ID string `json:"id"`
Name string `json:"name"`
} `json:"entity"`
ID string `json:"id"`
GatewayStatus string `json:"gateway_status"`
GatewayType string `json:"gateway_type"`
StripeURL string `json:"stripe_url"`
StripeID string `json:"stripe_id"`
CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"`
}

type CommercePayeeList PaginatedList[CommercePayee]
8 changes: 8 additions & 0 deletions commerce/features/api.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 25 additions & 1 deletion commerce/features/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func NewClient(config *clerk.ClientConfig) *Client {
}

func (c *Client) Create(ctx context.Context, params *clerk.CreateFeatureParams) (*clerk.CommerceFeature, error) {
reqPath, err := clerk.JoinPath(rootPath, "plans", params.PlanID, path)
reqPath, err := clerk.JoinPath(rootPath, path)
if err != nil {
return nil, err
}
Expand All @@ -35,6 +35,30 @@ func (c *Client) Create(ctx context.Context, params *clerk.CreateFeatureParams)
return resource, err
}

func (c *Client) CreatePlanFeatures(ctx context.Context, params *clerk.CreateMultiplePlanFeaturesParams) (*clerk.CommercePlanFeatureList, error) {
reqPath, err := clerk.JoinPath(rootPath, "plans", params.PlanID, path)
if err != nil {
return nil, err
}
req := clerk.NewAPIRequest(http.MethodPost, reqPath)
req.SetParams(params)
resource := &clerk.CommercePlanFeatureList{}
err = c.Backend.Call(ctx, req, resource)
return resource, err
}

func (c *Client) DeletePlanFeatures(ctx context.Context, params *clerk.DeletePlanFeaturesParams) (*clerk.DeletedResource, error) {
reqPath, err := clerk.JoinPath(rootPath, "plans", params.PlanID, path)
if err != nil {
return nil, err
}
req := clerk.NewAPIRequest(http.MethodDelete, reqPath)
req.SetParams(params)
resource := &clerk.DeletedResource{}
err = c.Backend.Call(ctx, req, resource)
return resource, err
}

func (c *Client) List(ctx context.Context, params *clerk.ListFeaturesByInstanceIDParams) (*clerk.CommerceFeatureList, error) {
reqPath, err := clerk.JoinPath(rootPath, path)
if err != nil {
Expand Down
Loading

0 comments on commit 7584b41

Please sign in to comment.