-
Notifications
You must be signed in to change notification settings - Fork 9
/
subscribers.go
160 lines (141 loc) · 5.74 KB
/
subscribers.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package revenuecat
import (
"encoding/json"
"time"
)
// Subscriber holds a subscriber returned by the RevenueCat API.
type Subscriber struct {
OriginalAppUserID string `json:"original_app_user_id"`
OriginalApplicationVersion *string `json:"original_application_version"`
FirstSeen time.Time `json:"first_seen"`
LastSeen time.Time `json:"last_seen"`
Entitlements map[string]Entitlement `json:"entitlements"`
Subscriptions map[string]Subscription `json:"subscriptions"`
NonSubscriptions map[string][]NonSubscription `json:"non_subscriptions"`
SubscriberAttributes map[string]SubscriberAttribute `json:"subscriber_attributes"`
}
// https://docs.revenuecat.com/reference#the-entitlement-object
type Entitlement struct {
ExpiresDate time.Time `json:"expires_date"`
GracePeriodExpiresDate *time.Time `json:"grace_period_expires_date"`
PurchaseDate time.Time `json:"purchase_date"`
ProductIdentifier string `json:"product_identifier"`
ProductPlanIdentifier string `json:"product_plan_identifier"`
}
// https://docs.revenuecat.com/reference#the-subscription-object
type Subscription struct {
ExpiresDate *time.Time `json:"expires_date"`
PurchaseDate time.Time `json:"purchase_date"`
OriginalPurchaseDate time.Time `json:"original_purchase_date"`
PeriodType PeriodType `json:"period_type"`
Store Store `json:"store"`
IsSandbox bool `json:"is_sandbox"`
UnsubscribeDetectedAt *time.Time `json:"unsubscribe_detected_at"`
BillingIssuesDetectedAt *time.Time `json:"billing_issues_detected_at"`
AutoResumeDate *time.Time `json:"auto_resume_date"`
GracePeriodExpiresDate *time.Time `json:"grace_period_expires_date"`
RefundedAt *time.Time `json:"refunded_at"`
OwnershipType OwnershipType `json:"ownership_type"`
StoreTransactionID string `json:"store_transaction_id"`
}
// https://docs.revenuecat.com/reference#section-the-non-subscription-object
type NonSubscription struct {
ID string `json:"id"`
PurchaseDate time.Time `json:"purchase_date"`
Store Store `json:"store"`
IsSandbox bool `json:"is_sandbox"`
}
// https://docs.revenuecat.com/reference#section-the-subscriber-attribute-object
type SubscriberAttribute struct {
Value string
UpdatedAt time.Time
}
// PeriodType holds the predefined values for a subscription period.
type PeriodType string
// https://docs.revenuecat.com/reference#the-subscription-object
const (
NormalPeriodType PeriodType = "normal"
TrialPeriodType PeriodType = "trial"
IntroPeriodType PeriodType = "intro"
)
// OwnershipType holds the predefined values for a subscription ownership type.
type OwnershipType string
const (
PurchasedOwnershipType OwnershipType = "PURCHASED"
FamilySharedOwnershipType OwnershipType = "FAMILY_SHARED"
)
// Store holds the predefined values for a store.
type Store string
// https://docs.revenuecat.com/reference#the-subscription-object
const (
AppStore Store = "app_store"
MacAppStore Store = "mac_app_store"
PlayStore Store = "play_store"
StripeStore Store = "stripe"
PromotionalStore Store = "promotional"
)
// IsEntitledTo returns true if the Subscriber has the given entitlement.
func (s Subscriber) IsEntitledTo(entitlement string) bool {
e, ok := s.Entitlements[entitlement]
if !ok {
return false
}
return !e.ExpiresDate.Before(time.Now())
}
// GetSubscriber gets the latest subscriber info or creates one if it doesn't exist.
// https://docs.revenuecat.com/reference#subscribers
func (c *Client) GetSubscriber(userID string) (Subscriber, error) {
return c.GetSubscriberWithPlatform(userID, "")
}
// GetSubscriberWithPlatform gets the latest subscriber info or creates one if it doesn't exist, updating the subscriber record's last_seen
// value for the platform provided.
// https://docs.revenuecat.com/reference#subscribers
func (c *Client) GetSubscriberWithPlatform(userID string, platform string) (Subscriber, error) {
var resp struct {
Subscriber Subscriber `json:"subscriber"`
}
err := c.call("GET", "subscribers/"+userID, nil, platform, &resp)
return resp.Subscriber, err
}
// UpdateSubscriberAttributes updates subscriber attributes for a user.
// https://docs.revenuecat.com/reference#update-subscriber-attributes
func (c *Client) UpdateSubscriberAttributes(userID string, attributes map[string]SubscriberAttribute) error {
req := struct {
Attributes map[string]SubscriberAttribute `json:"attributes"`
}{
Attributes: attributes,
}
return c.call("POST", "subscribers/"+userID+"/attributes", req, "", nil)
}
// DeleteSubscriber permanently deletes a subscriber.
// https://docs.revenuecat.com/reference#subscribersapp_user_id
func (c *Client) DeleteSubscriber(userID string) error {
return c.call("DELETE", "subscribers/"+userID, nil, "", nil)
}
func (attr SubscriberAttribute) MarshalJSON() ([]byte, error) {
var updatedAt int64
if !attr.UpdatedAt.IsZero() {
updatedAt = toMilliseconds(attr.UpdatedAt)
}
return json.Marshal(&struct {
Value string `json:"value"`
UpdatedAt int64 `json:"updated_at_ms,omitempty"`
}{
Value: attr.Value,
UpdatedAt: updatedAt,
})
}
func (attr *SubscriberAttribute) UnmarshalJSON(data []byte) error {
var jsonAttr struct {
Value string `json:"value"`
UpdatedAt int64 `json:"updated_at_ms,omitempty"`
}
if err := json.Unmarshal(data, &jsonAttr); err != nil {
return err
}
attr.Value = jsonAttr.Value
if jsonAttr.UpdatedAt > 0 {
attr.UpdatedAt = fromMilliseconds(jsonAttr.UpdatedAt)
}
return nil
}