metrifox-sdk 1.0.3 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -2
- data/README.md +68 -29
- data/lib/metrifox_sdk/client.rb +8 -3
- data/lib/metrifox_sdk/types.rb +3 -104
- data/lib/metrifox_sdk/usages/api.rb +8 -6
- data/lib/metrifox_sdk/usages/module.rb +7 -3
- data/lib/metrifox_sdk/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1dff9fd808bc32d6349ca7a116713b9985ed31e1bd77bf49fd52d96d72ebedb3
|
|
4
|
+
data.tar.gz: 03364bfa5c26be341eee0ba665bef63913e1992ad82edd0d14123fdb1e21d607
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ffe66393b2b92925c2f3dc15cc699b7129ca06fa8baf7a06eb73fc635637d2c42a8c193a94ca17a1f2405aa7e119a6725c3de225ef779db58301ac05367cebaf
|
|
7
|
+
data.tar.gz: e271a28735a68ce97be07578c748fd8e01247bdbb633112fbcdd664a1a945c028adac9f549d776e7cc452fd4d68520df7292f3ee30595477d1266f58afbc070b
|
data/CHANGELOG.md
CHANGED
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
|
+
- Update usage access and recording to call the meter service (`https://api-meter.metrifox.com`).
|
|
6
7
|
|
|
7
|
-
## [1.0.
|
|
8
|
+
## [1.0.3] - 2025-09-01
|
|
8
9
|
- Initial release
|
|
9
10
|
- Access control functionality
|
|
10
11
|
- Usage tracking
|
|
11
12
|
- Customer management
|
|
12
|
-
- CSV upload support
|
|
13
|
+
- CSV upload support
|
data/README.md
CHANGED
|
@@ -35,6 +35,7 @@ METRIFOX_SDK = MetrifoxSDK.init({ api_key: "your-api-key"})
|
|
|
35
35
|
# Or set environment variable
|
|
36
36
|
ENV["METRIFOX_API_KEY"] = "your-api-key"
|
|
37
37
|
METRIFOX_SDK = MetrifoxSDK.init
|
|
38
|
+
|
|
38
39
|
```
|
|
39
40
|
|
|
40
41
|
### Access Control
|
|
@@ -46,7 +47,28 @@ response = METRIFOX_SDK.usages.check_access({
|
|
|
46
47
|
customer_key: "customer_123"
|
|
47
48
|
})
|
|
48
49
|
|
|
49
|
-
puts response["can_access"] # true/false
|
|
50
|
+
puts response["data"]["can_access"] # true/false
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
> Access checks are now served by the Metrifox Meter service (`https://api-meter.metrifox.com`).
|
|
54
|
+
Example response payload:
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"data": {
|
|
59
|
+
"customer_key": "cust-mit7k5v8obzs",
|
|
60
|
+
"feature_key": "feature_seats",
|
|
61
|
+
"requested_quantity": 1,
|
|
62
|
+
"can_access": true,
|
|
63
|
+
"unlimited": false,
|
|
64
|
+
"balance": 4,
|
|
65
|
+
"used_quantity": 0,
|
|
66
|
+
"entitlement_active": true,
|
|
67
|
+
"prepaid": false,
|
|
68
|
+
"wallet_balance": 0,
|
|
69
|
+
"message": "Feature found"
|
|
70
|
+
}
|
|
71
|
+
}
|
|
50
72
|
```
|
|
51
73
|
|
|
52
74
|
### Usage Tracking
|
|
@@ -56,17 +78,27 @@ puts response["can_access"] # true/false
|
|
|
56
78
|
response = METRIFOX_SDK.usages.record_usage({
|
|
57
79
|
customer_key: "customer_123",
|
|
58
80
|
event_name: "api_call",
|
|
59
|
-
amount: 1
|
|
81
|
+
amount: 1,
|
|
82
|
+
event_id: "evt_12345", # required idempotency key
|
|
83
|
+
timestamp: (Time.now.to_f * 1000).to_i # recommended (milliseconds)
|
|
60
84
|
})
|
|
85
|
+
puts response["message"] # "Event received"
|
|
86
|
+
puts response["data"]["quantity"] # 1
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The usage event endpoint now returns a simple payload with the recorded `data` and a `message` confirming the event reception.
|
|
90
|
+
|
|
91
|
+
> You can send either an `event_name` or a `feature_key` when recording usage events.
|
|
61
92
|
|
|
93
|
+
```ruby
|
|
62
94
|
# Advanced usage recording with additional fields
|
|
63
95
|
response = METRIFOX_SDK.usages.record_usage({
|
|
64
96
|
customer_key: "customer_123",
|
|
65
|
-
event_name: "api_call",
|
|
97
|
+
event_name: "api_call", # Or use feature_key
|
|
66
98
|
amount: 1,
|
|
99
|
+
event_id: "event_uuid_123", # required idempotency key
|
|
67
100
|
credit_used: 5,
|
|
68
|
-
|
|
69
|
-
timestamp: 1640995200,
|
|
101
|
+
timestamp: (Time.now.to_f * 1000).to_i,
|
|
70
102
|
metadata: {
|
|
71
103
|
source: "web_app",
|
|
72
104
|
feature: "premium_search"
|
|
@@ -76,17 +108,30 @@ response = METRIFOX_SDK.usages.record_usage({
|
|
|
76
108
|
# Using structured request object
|
|
77
109
|
usage_request = MetrifoxSDK::Types::UsageEventRequest.new(
|
|
78
110
|
customer_key: "customer_123",
|
|
79
|
-
|
|
111
|
+
feature_key: "feat_my_feat_234", # OR use event_name
|
|
80
112
|
amount: 1,
|
|
81
113
|
credit_used: 5,
|
|
82
114
|
event_id: "event_uuid_123",
|
|
83
|
-
timestamp: Time.now.to_i,
|
|
115
|
+
timestamp: (Time.now.to_f * 1000).to_i,
|
|
84
116
|
metadata: { source: "mobile_app" }
|
|
85
117
|
)
|
|
86
118
|
|
|
87
119
|
response = METRIFOX_SDK.usages.record_usage(usage_request)
|
|
88
120
|
```
|
|
89
121
|
|
|
122
|
+
Sample response body:
|
|
123
|
+
|
|
124
|
+
```json
|
|
125
|
+
{
|
|
126
|
+
"data": {
|
|
127
|
+
"customer_key": "cust-mit7k5v8obzs",
|
|
128
|
+
"quantity": 1,
|
|
129
|
+
"feature_key": "feature_job_posts"
|
|
130
|
+
},
|
|
131
|
+
"message": "Event received"
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
90
135
|
### Customer Management
|
|
91
136
|
|
|
92
137
|
```ruby
|
|
@@ -199,35 +244,29 @@ response = METRIFOX_SDK.usages.check_access({
|
|
|
199
244
|
|
|
200
245
|
## Type Safety with Structs
|
|
201
246
|
|
|
202
|
-
The SDK
|
|
247
|
+
The SDK exposes lightweight structs for the usage and checkout helpers when you want a bit more structure:
|
|
203
248
|
|
|
204
249
|
```ruby
|
|
205
|
-
#
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
# Customer creation with structured data (customer_key is REQUIRED)
|
|
214
|
-
customer_request = MetrifoxSDK::Types::CustomerCreateRequest.new(
|
|
215
|
-
customer_key: "customer_123", # Required
|
|
216
|
-
customer_type: MetrifoxSDK::Types::CustomerType::BUSINESS,
|
|
217
|
-
primary_email: "customer@example.com",
|
|
218
|
-
legal_name: "Acme Corp"
|
|
250
|
+
# Usage events (event_id required for idempotency)
|
|
251
|
+
usage_request = MetrifoxSDK::Types::UsageEventRequest.new(
|
|
252
|
+
customer_key: "customer_123",
|
|
253
|
+
feature_key: "feature_seats",
|
|
254
|
+
amount: 1,
|
|
255
|
+
event_id: "event_uuid_123",
|
|
256
|
+
timestamp: (Time.now.to_f * 1000).to_i,
|
|
257
|
+
metadata: { source: "mobile_app" }
|
|
219
258
|
)
|
|
220
259
|
|
|
221
|
-
response = METRIFOX_SDK.
|
|
260
|
+
response = METRIFOX_SDK.usages.record_usage(usage_request)
|
|
222
261
|
|
|
223
|
-
#
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
262
|
+
# Checkout configuration
|
|
263
|
+
checkout_config = MetrifoxSDK::Types::CheckoutConfig.new(
|
|
264
|
+
offering_key: "premium_plan",
|
|
265
|
+
billing_interval: "monthly",
|
|
266
|
+
customer_key: "customer_123"
|
|
228
267
|
)
|
|
229
268
|
|
|
230
|
-
|
|
269
|
+
checkout_url = METRIFOX_SDK.checkout.url(checkout_config)
|
|
231
270
|
```
|
|
232
271
|
|
|
233
272
|
## Error Handling
|
data/lib/metrifox_sdk/client.rb
CHANGED
|
@@ -4,13 +4,18 @@ module MetrifoxSDK
|
|
|
4
4
|
class Client
|
|
5
5
|
include MetrifoxSDK::UtilMethods
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
DEFAULT_BASE_URL = "https://api.metrifox.com/api/v1/".freeze
|
|
8
|
+
DEFAULT_WEB_APP_BASE_URL = "https://app.metrifox.com".freeze
|
|
9
|
+
METER_SERVICE_BASE_URL = "https://api-meter.metrifox.com/".freeze
|
|
10
|
+
|
|
11
|
+
attr_reader :config, :api_key, :base_url, :web_app_base_url, :meter_service_base_url
|
|
8
12
|
|
|
9
13
|
def initialize(config = {})
|
|
10
14
|
@config = config
|
|
11
15
|
@api_key = config[:api_key] || get_api_key_from_environment
|
|
12
|
-
@base_url = config[:base_url] ||
|
|
13
|
-
@web_app_base_url = config[:web_app_base_url] ||
|
|
16
|
+
@base_url = config[:base_url] || DEFAULT_BASE_URL
|
|
17
|
+
@web_app_base_url = config[:web_app_base_url] || DEFAULT_WEB_APP_BASE_URL
|
|
18
|
+
@meter_service_base_url = METER_SERVICE_BASE_URL
|
|
14
19
|
end
|
|
15
20
|
|
|
16
21
|
def customers
|
data/lib/metrifox_sdk/types.rb
CHANGED
|
@@ -1,115 +1,14 @@
|
|
|
1
1
|
module MetrifoxSDK
|
|
2
2
|
module Types
|
|
3
|
-
# Enums
|
|
4
|
-
module TaxStatus
|
|
5
|
-
TAXABLE = "TAXABLE"
|
|
6
|
-
TAX_EXEMPT = "TAX_EXEMPT"
|
|
7
|
-
REVERSE_CHARGE = "REVERSE_CHARGE"
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
module CustomerType
|
|
11
|
-
BUSINESS = "BUSINESS"
|
|
12
|
-
INDIVIDUAL = "INDIVIDUAL"
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
# Value objects / Structs
|
|
16
|
-
EmailAddress = Struct.new(:email, :is_primary, keyword_init: true)
|
|
17
|
-
PhoneNumber = Struct.new(:phone_number, :country_code, :is_primary, keyword_init: true)
|
|
18
|
-
|
|
19
|
-
Address = Struct.new(
|
|
20
|
-
:country, :address_line_one, :address_line_two, :city,
|
|
21
|
-
:state, :zip_code, :phone_number, keyword_init: true
|
|
22
|
-
)
|
|
23
|
-
|
|
24
|
-
BillingConfig = Struct.new(
|
|
25
|
-
:preferred_payment_gateway, :preferred_payment_method, :billing_email,
|
|
26
|
-
:billing_address, :payment_reminder_days, keyword_init: true
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
TaxIdentification = Struct.new(:type, :number, :country, keyword_init: true)
|
|
30
|
-
|
|
31
|
-
ContactPerson = Struct.new(
|
|
32
|
-
:first_name, :last_name, :email_address, :designation,
|
|
33
|
-
:department, :is_primary, :phone_number, keyword_init: true
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
PaymentTerm = Struct.new(:type, :value, keyword_init: true)
|
|
37
|
-
|
|
38
|
-
# Request/Response objects
|
|
39
|
-
AccessCheckRequest = Struct.new(:feature_key, :customer_key, keyword_init: true)
|
|
40
|
-
|
|
41
|
-
AccessResponse = Struct.new(
|
|
42
|
-
:message, :can_access, :customer_id, :feature_key, :required_quantity,
|
|
43
|
-
:used_quantity, :included_usage, :next_reset_at, :quota, :unlimited,
|
|
44
|
-
:carryover_quantity, :balance, keyword_init: true
|
|
45
|
-
)
|
|
46
|
-
|
|
47
3
|
UsageEventRequest = Struct.new(
|
|
48
|
-
:customer_key, :event_name, :amount, :credit_used, :event_id, :timestamp, :metadata,
|
|
4
|
+
:customer_key, :event_name, :feature_key, :amount, :credit_used, :event_id, :timestamp, :metadata,
|
|
49
5
|
keyword_init: true
|
|
50
6
|
) do
|
|
51
|
-
def initialize(customer_key:, event_name
|
|
7
|
+
def initialize(customer_key:, event_name: nil, feature_key: nil, amount: 1, credit_used: nil, event_id: nil, timestamp: nil, metadata: {})
|
|
52
8
|
super
|
|
53
9
|
end
|
|
54
10
|
end
|
|
55
11
|
|
|
56
|
-
UsageEventResponse = Struct.new(:message, :event_name, :customer_key, keyword_init: true)
|
|
57
|
-
|
|
58
|
-
CustomerCreateRequest = Struct.new(
|
|
59
|
-
# Core fields (customer_key is REQUIRED)
|
|
60
|
-
:customer_key, :customer_type, :primary_email, :primary_phone,
|
|
61
|
-
# Business fields
|
|
62
|
-
:legal_name, :display_name, :legal_number, :tax_identification_number,
|
|
63
|
-
:logo_url, :website_url, :account_manager,
|
|
64
|
-
# Individual fields
|
|
65
|
-
:first_name, :middle_name, :last_name, :date_of_birth, :billing_email,
|
|
66
|
-
# Preferences
|
|
67
|
-
:timezone, :language, :currency, :tax_status,
|
|
68
|
-
# Address fields
|
|
69
|
-
:address_line1, :address_line2, :city, :state, :country, :zip_code,
|
|
70
|
-
# Shipping address fields
|
|
71
|
-
:shipping_address_line1, :shipping_address_line2, :shipping_city,
|
|
72
|
-
:shipping_state, :shipping_country, :shipping_zip_code,
|
|
73
|
-
# Complex fields
|
|
74
|
-
:billing_configuration, :tax_identifications, :contact_people,
|
|
75
|
-
:payment_terms, :metadata, keyword_init: true
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
CustomerUpdateRequest = Struct.new(
|
|
79
|
-
# Core fields (customer_key is NOT included - it's immutable and passed as a parameter)
|
|
80
|
-
:customer_type, :primary_email, :primary_phone, :billing_email,
|
|
81
|
-
# Business fields
|
|
82
|
-
:legal_name, :display_name, :legal_number, :tax_identification_number,
|
|
83
|
-
:logo_url, :website_url, :account_manager,
|
|
84
|
-
# Individual fields
|
|
85
|
-
:first_name, :middle_name, :last_name, :date_of_birth,
|
|
86
|
-
# Preferences
|
|
87
|
-
:timezone, :language, :currency, :tax_status,
|
|
88
|
-
# Address fields
|
|
89
|
-
:address_line1, :address_line2, :city, :state, :country, :zip_code,
|
|
90
|
-
# Shipping address fields
|
|
91
|
-
:shipping_address_line1, :shipping_address_line2, :shipping_city,
|
|
92
|
-
:shipping_state, :shipping_country, :shipping_zip_code,
|
|
93
|
-
# Complex fields
|
|
94
|
-
:billing_configuration, :tax_identifications, :contact_people,
|
|
95
|
-
:payment_terms, :metadata, :phone_numbers, :email_addresses, keyword_init: true
|
|
96
|
-
)
|
|
97
|
-
|
|
98
|
-
CustomerDeleteRequest = Struct.new(:customer_key, keyword_init: true)
|
|
99
|
-
CustomerGetRequest = Struct.new(:customer_key, keyword_init: true)
|
|
100
|
-
|
|
101
|
-
CustomerCSVSyncResponse = Struct.new(
|
|
102
|
-
:status_code, :message, :data, :errors, :meta, keyword_init: true
|
|
103
|
-
) do
|
|
104
|
-
CSVSyncData = Struct.new(
|
|
105
|
-
:total_customers, :successful_upload_count, :failed_upload_count,
|
|
106
|
-
:customers_added, :customers_failed, keyword_init: true
|
|
107
|
-
)
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
APIResponse = Struct.new(:status_code, :message, :data, :errors, :meta, keyword_init: true)
|
|
111
|
-
|
|
112
|
-
EmbedConfig = Struct.new(:container, :product_key, keyword_init: true)
|
|
113
12
|
CheckoutConfig = Struct.new(:offering_key, :billing_interval, :customer_key, keyword_init: true)
|
|
114
13
|
end
|
|
115
|
-
end
|
|
14
|
+
end
|
|
@@ -22,7 +22,7 @@ module MetrifoxSDK::Usages
|
|
|
22
22
|
parse_response(response, "Failed to check access")
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
def
|
|
25
|
+
def record_usage(base_url, api_key, request_payload)
|
|
26
26
|
uri = URI.join(base_url, "usage/events")
|
|
27
27
|
|
|
28
28
|
# Handle both hash and struct access patterns
|
|
@@ -33,18 +33,20 @@ module MetrifoxSDK::Usages
|
|
|
33
33
|
event_id = get_value(request_payload, :event_id)
|
|
34
34
|
timestamp = get_value(request_payload, :timestamp)
|
|
35
35
|
metadata = get_value(request_payload, :metadata) || {}
|
|
36
|
+
feature_key = get_value(request_payload, :feature_key)
|
|
36
37
|
|
|
37
38
|
body = {
|
|
38
|
-
customer_key
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
customer_key:,
|
|
40
|
+
amount:,
|
|
41
|
+
event_id:
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
# Add optional fields if present
|
|
44
45
|
body[:credit_used] = credit_used if credit_used
|
|
45
|
-
body[:event_id] = event_id if event_id && !event_id.empty?
|
|
46
46
|
body[:timestamp] = timestamp if timestamp
|
|
47
47
|
body[:metadata] = metadata if metadata
|
|
48
|
+
body[:feature_key] = feature_key if feature_key
|
|
49
|
+
body[:event_name] = event_name if event_name
|
|
48
50
|
|
|
49
51
|
response = make_request(uri, "POST", api_key, body)
|
|
50
52
|
parse_response(response, "Failed to record usage")
|
|
@@ -77,4 +79,4 @@ module MetrifoxSDK::Usages
|
|
|
77
79
|
end
|
|
78
80
|
end
|
|
79
81
|
end
|
|
80
|
-
end
|
|
82
|
+
end
|
|
@@ -6,12 +6,12 @@ module MetrifoxSDK
|
|
|
6
6
|
class Module < BaseModule
|
|
7
7
|
def check_access(request_payload)
|
|
8
8
|
validate_api_key!
|
|
9
|
-
api.fetch_access(
|
|
9
|
+
api.fetch_access(meter_service_base_url, api_key, request_payload)
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def record_usage(request_payload)
|
|
13
13
|
validate_api_key!
|
|
14
|
-
api.
|
|
14
|
+
api.record_usage(meter_service_base_url, api_key, request_payload)
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def get_tenant_id
|
|
@@ -26,9 +26,13 @@ module MetrifoxSDK
|
|
|
26
26
|
|
|
27
27
|
private
|
|
28
28
|
|
|
29
|
+
def meter_service_base_url
|
|
30
|
+
client.respond_to?(:meter_service_base_url) ? client.meter_service_base_url : base_url
|
|
31
|
+
end
|
|
32
|
+
|
|
29
33
|
def api
|
|
30
34
|
@api ||= API.new
|
|
31
35
|
end
|
|
32
36
|
end
|
|
33
37
|
end
|
|
34
|
-
end
|
|
38
|
+
end
|
data/lib/metrifox_sdk/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: metrifox-sdk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0
|
|
4
|
+
version: 1.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Metrifox
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2025-
|
|
10
|
+
date: 2025-12-12 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: json
|