diff --git a/lib/revenuecat/revenuecat.go b/lib/revenuecat/revenuecat.go new file mode 100644 index 0000000..bf86998 --- /dev/null +++ b/lib/revenuecat/revenuecat.go @@ -0,0 +1,68 @@ +package revenuecat + +import ( + "context" + "fmt" + "net/url" + "time" + + "github.com/wearemojo/mojo-public-go/lib/httpclient" + "github.com/wearemojo/mojo-public-go/lib/jsonclient" + "github.com/wearemojo/mojo-public-go/lib/secret" +) + +const baseURL = "https://api.revenuecat.com/v1" + +type Client struct { + client *jsonclient.Client +} + +func NewClient(ctx context.Context, serverTokenSecretID string) (*Client, error) { + if _, err := secret.Get(ctx, serverTokenSecretID); err != nil { + return nil, err + } + + return &Client{ + client: jsonclient.NewClient( + baseURL, + httpclient.NewClient(5*time.Second, roundTripper{serverTokenSecretID}), + ), + }, nil +} + +type UserInfoResponse struct { + Subscriber Subscriber `json:"subscriber"` +} + +type Subscriber struct { + Entitlements map[string]Entitlement `json:"entitlements"` + Subscriptions map[string]Subscription `json:"subscriptions"` +} + +type Entitlement struct { + ExpiresDate time.Time `json:"expires_date"` + ProductIdentifier string `json:"product_identifier"` +} + +type Subscription struct { + PeriodType PeriodType `json:"period_type"` + UnsubscribeDetectedAt *time.Time `json:"unsubscribe_detected_at"` +} + +type PeriodType string + +const ( + PeriodTypeTrial PeriodType = "trial" + PeriodTypeIntro PeriodType = "intro" + PeriodTypeNormal PeriodType = "normal" +) + +// https://www.revenuecat.com/reference/subscribers +// This API either fetches a user or creates one :shrug: +// for now, we only care about the expiry date of the full_access entitlement +// and the period type of the subscription. See useSubscriptionStateIap.ts +func (c *Client) GetOrCreateSubscriberInfo(ctx context.Context, appUserID string) (res *UserInfoResponse, err error) { + escapedAppUserID := url.PathEscape(appUserID) + path := fmt.Sprintf("/subscribers/%s", escapedAppUserID) + return res, c.client.Do(ctx, "GET", path, nil, nil, &res) +} diff --git a/lib/revenuecat/roundtripper.go b/lib/revenuecat/roundtripper.go new file mode 100644 index 0000000..116fa33 --- /dev/null +++ b/lib/revenuecat/roundtripper.go @@ -0,0 +1,30 @@ +package revenuecat + +import ( + "fmt" + "net/http" + + "github.com/wearemojo/mojo-public-go/lib/secret" +) + +type roundTripper struct { + SecretID string +} + +func (r roundTripper) RoundTrip(req *http.Request) (*http.Response, error) { + ctx := req.Context() + req = req.Clone(ctx) + + apiKey, err := secret.Get(ctx, r.SecretID) + if err != nil { + return nil, err + } + + if req.Header == nil { + req.Header = http.Header{} + } + + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", apiKey)) + + return http.DefaultTransport.RoundTrip(req) +}