yield-sdk 0.5.1 → 0.7.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/.rubocop.yml +51 -0
- data/README.md +25 -10
- data/Rakefile +11 -2
- data/Steepfile +20 -0
- data/docs/index.md +12 -0
- data/docs/modules/customer.md +64 -0
- data/docs/modules/order.md +93 -0
- data/docs/modules/self.md +48 -0
- data/lib/yield/sdk/api/api_client.rb +54 -37
- data/lib/yield/sdk/api/api_error.rb +39 -0
- data/lib/yield/sdk/api/api_error_details.rb +9 -0
- data/lib/yield/sdk/api/api_result.rb +23 -6
- data/lib/yield/sdk/base_client.rb +6 -3
- data/lib/yield/sdk/client.rb +7 -4
- data/lib/yield/sdk/modules/customer/customer_base_client.rb +27 -0
- data/lib/yield/sdk/modules/customer/customer_client.rb +19 -0
- data/lib/yield/sdk/modules/customer/payloads/customer_credit_line_info.rb +22 -0
- data/lib/yield/sdk/modules/customer/payloads/customer_list_payload.rb +20 -0
- data/lib/yield/sdk/modules/customer/payloads/customer_row.rb +28 -0
- data/lib/yield/sdk/modules/order/order_base_client.rb +4 -1
- data/lib/yield/sdk/modules/order/payloads/order.rb +21 -11
- data/lib/yield/sdk/modules/order/payloads/order_create_payload.rb +1 -1
- data/lib/yield/sdk/modules/order/payloads/order_customer_info.rb +11 -5
- data/lib/yield/sdk/modules/order/payloads/order_status.rb +1 -1
- data/lib/yield/sdk/modules/self/payloads/self_info.rb +9 -5
- data/lib/yield/sdk/modules/self/payloads/self_organization_info.rb +9 -5
- data/lib/yield/sdk/types/cursor_payload.rb +19 -0
- data/lib/yield/sdk/types/money.rb +6 -3
- data/lib/yield/sdk/types/money_payload.rb +7 -3
- data/lib/yield/sdk/types/page.rb +51 -0
- data/lib/yield/sdk/utils/type_utils.rb +71 -0
- data/lib/yield/sdk/version.rb +3 -3
- data/lib/yield/sdk.rb +2 -1
- data/sig/vendor/faraday.rbs +23 -0
- data/sig/yield/sdk/api/api_client.rbs +26 -0
- data/sig/yield/sdk/api/api_error.rbs +13 -0
- data/sig/yield/sdk/api/api_error_details.rbs +14 -0
- data/sig/yield/sdk/api/api_result.rbs +19 -0
- data/sig/yield/sdk/base_client.rbs +13 -0
- data/sig/yield/sdk/client.rbs +13 -0
- data/sig/yield/sdk/modules/customer/customer_base_client.rbs +11 -0
- data/sig/yield/sdk/modules/customer/customer_client.rbs +11 -0
- data/sig/yield/sdk/modules/customer/payloads/customer_credit_line_info.rbs +13 -0
- data/sig/yield/sdk/modules/customer/payloads/customer_list_payload.rbs +16 -0
- data/sig/yield/sdk/modules/customer/payloads/customer_row.rbs +16 -0
- data/sig/yield/sdk/modules/order/payloads/order.rbs +30 -0
- data/sig/yield/sdk/modules/order/payloads/order_create_payload.rbs +15 -0
- data/sig/yield/sdk/modules/order/payloads/order_customer_info.rbs +15 -0
- data/sig/yield/sdk/modules/order/payloads/order_status.rbs +10 -0
- data/sig/yield/sdk/modules/order/self_base_client.rbs +12 -0
- data/sig/yield/sdk/modules/order/self_client.rbs +12 -0
- data/sig/yield/sdk/modules/self/payloads/self_info.rbs +14 -0
- data/sig/yield/sdk/modules/self/payloads/self_organization_info.rbs +14 -0
- data/sig/yield/sdk/modules/self/self_base_client.rbs +11 -0
- data/sig/yield/sdk/modules/self/self_client.rbs +11 -0
- data/sig/yield/sdk/types/cursor_payload.rbs +14 -0
- data/sig/yield/sdk/types/money.rbs +12 -0
- data/sig/yield/sdk/types/money_payload.rbs +15 -0
- data/sig/yield/sdk/types/page.rbs +20 -0
- data/sig/yield/sdk/utils/type_utils.rbs +26 -0
- data/sig/yield/sdk/version.rbs +8 -0
- data/sig/yield/sdk.rbs +0 -2
- metadata +66 -7
- data/.standard.yml +0 -3
- data/lib/yield/sdk/utils.rb +0 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: edf5ef23bf25b6d5b424ce3f6e9d0a3a40b045176901bf2de01078b86d34cce6
|
4
|
+
data.tar.gz: 8fa6343f723d3f4051f15b5e606e887775f819f0889438e6866fca59bdbb4e58
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 74d0b5a43f40bd586ebc345c7b8590c48bfd97d4c684236868516260f626efe78f25c73b2f21bf7ab6f152d5dc83f2fae7ad2e44b8d17f1ac5ea36d8df3daf19
|
7
|
+
data.tar.gz: 300efc9e709e883246445d924e004517408ab263e122b1cf46384e74228cca88623a23c5b92ea5adb2f973c36de97ffd0949b1ad65be9ad6919ae8d2b21a74b2
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
plugins:
|
2
|
+
- rubocop-minitest
|
3
|
+
- rubocop-rake
|
4
|
+
|
5
|
+
AllCops:
|
6
|
+
TargetRubyVersion: 3.0
|
7
|
+
NewCops: enable
|
8
|
+
|
9
|
+
Gemspec/RequireMFA:
|
10
|
+
Enabled: false # FIXME
|
11
|
+
|
12
|
+
Style/AccessorGrouping:
|
13
|
+
Enabled: false
|
14
|
+
|
15
|
+
Style/Documentation:
|
16
|
+
Enabled: false
|
17
|
+
|
18
|
+
Style/MultipleComparison:
|
19
|
+
Enabled: false
|
20
|
+
|
21
|
+
Style/StringLiterals:
|
22
|
+
Enabled: true
|
23
|
+
EnforcedStyle: double_quotes
|
24
|
+
|
25
|
+
Style/StringLiteralsInInterpolation:
|
26
|
+
Enabled: true
|
27
|
+
EnforcedStyle: double_quotes
|
28
|
+
|
29
|
+
Style/TrailingCommaInArguments:
|
30
|
+
Enabled: true
|
31
|
+
EnforcedStyleForMultiline: comma
|
32
|
+
|
33
|
+
Style/TrailingCommaInArrayLiteral:
|
34
|
+
Enabled: true
|
35
|
+
EnforcedStyleForMultiline: comma
|
36
|
+
|
37
|
+
Style/TrailingCommaInHashLiteral:
|
38
|
+
Enabled: true
|
39
|
+
EnforcedStyleForMultiline: comma
|
40
|
+
|
41
|
+
Layout/LineLength:
|
42
|
+
Enabled: false
|
43
|
+
|
44
|
+
Metrics/AbcSize:
|
45
|
+
Enabled: false
|
46
|
+
|
47
|
+
Metrics/ClassLength:
|
48
|
+
Enabled: false
|
49
|
+
|
50
|
+
Metrics/MethodLength:
|
51
|
+
Enabled: false
|
data/README.md
CHANGED
@@ -1,27 +1,42 @@
|
|
1
|
-
|
1
|
+
Yield SDK for Ruby [](https://rubygems.org/gems/yield-sdk)
|
2
|
+
==================
|
2
3
|
|
3
|
-
|
4
|
+
The official [Yield](https://www.paywithyield.com) SDK for Ruby.
|
5
|
+
|
6
|
+
|
7
|
+
Documentation
|
8
|
+
-------------
|
9
|
+
|
10
|
+
- [API reference](https://github.com/yield-tech/sdk-ruby/blob/main/docs/index.md)
|
11
|
+
|
12
|
+
|
13
|
+
Installation
|
14
|
+
------------
|
4
15
|
|
5
16
|
```sh
|
6
17
|
gem install yield-sdk
|
7
18
|
```
|
8
19
|
|
9
|
-
|
20
|
+
|
21
|
+
Usage
|
22
|
+
-----
|
10
23
|
|
11
24
|
```ruby
|
12
25
|
require "yield/sdk"
|
13
26
|
|
14
|
-
#
|
15
|
-
client = Yield::SDK::Client.new(ENV
|
27
|
+
# For security, don't save the actual key in your code or repo
|
28
|
+
client = Yield::SDK::Client.new(ENV.fetch("YIELD_API_KEY"))
|
16
29
|
|
17
|
-
#
|
30
|
+
# Fetch an existing order
|
18
31
|
order = client.order.fetch("ord_...")
|
19
32
|
p order.customer.registered_name
|
20
33
|
|
21
|
-
#
|
34
|
+
# Or create a new one
|
22
35
|
new_order = client.order.create({
|
23
|
-
|
24
|
-
|
25
|
-
|
36
|
+
customer_id: "org_...",
|
37
|
+
total_amount: "PHP 1234.50",
|
38
|
+
note: "Test order from the Ruby SDK!"
|
26
39
|
})
|
27
40
|
```
|
41
|
+
|
42
|
+
For more details, check out our [API reference](https://github.com/yield-tech/sdk-ruby/blob/main/docs/index.md).
|
data/Rakefile
CHANGED
@@ -9,6 +9,15 @@ Rake::TestTask.new(:test) do |t|
|
|
9
9
|
t.test_files = FileList["test/**/test_*.rb"]
|
10
10
|
end
|
11
11
|
|
12
|
-
require "
|
12
|
+
require "rubocop/rake_task"
|
13
13
|
|
14
|
-
|
14
|
+
RuboCop::RakeTask.new
|
15
|
+
|
16
|
+
require "steep/rake_task"
|
17
|
+
|
18
|
+
Steep::RakeTask.new do |t|
|
19
|
+
t.check.severity_level = :error
|
20
|
+
t.watch.verbose
|
21
|
+
end
|
22
|
+
|
23
|
+
task default: %i[test rubocop steep]
|
data/Steepfile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
D = Steep::Diagnostic
|
4
|
+
|
5
|
+
target :lib do
|
6
|
+
signature "sig"
|
7
|
+
|
8
|
+
check "lib"
|
9
|
+
# ignore "lib/.../*.rb"
|
10
|
+
|
11
|
+
library "base64"
|
12
|
+
library "bigdecimal"
|
13
|
+
library "date"
|
14
|
+
library "json"
|
15
|
+
library "openssl"
|
16
|
+
library "time"
|
17
|
+
library "uri"
|
18
|
+
|
19
|
+
configure_code_diagnostics(D::Ruby.strict)
|
20
|
+
end
|
data/docs/index.md
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
API Reference
|
2
|
+
=============
|
3
|
+
|
4
|
+
**Contents:**
|
5
|
+
- General overview (TBD)
|
6
|
+
- Error handling (TBD)
|
7
|
+
- Types (TBD)
|
8
|
+
- Pagination (TBD)
|
9
|
+
- Modules
|
10
|
+
- [Customer module](./modules/customer.md)
|
11
|
+
- [Order module](./modules/order.md)
|
12
|
+
- [Self module](./modules/self.md)
|
@@ -0,0 +1,64 @@
|
|
1
|
+
[*← Return to index*](../index.md)
|
2
|
+
|
3
|
+
Customer module
|
4
|
+
===============
|
5
|
+
|
6
|
+
**Endpoints:**
|
7
|
+
-  [`list(params)`](#-listparams)
|
8
|
+
|
9
|
+
**Objects:**
|
10
|
+
- [`CustomerRow`](#customerrow)
|
11
|
+
- [`CustomerCreditLineInfo`](#customercreditlineinfo)
|
12
|
+
|
13
|
+
|
14
|
+
Endpoints
|
15
|
+
---------
|
16
|
+
|
17
|
+
###  `list(params)`
|
18
|
+
|
19
|
+
Provides the list of customers under your account, ordered by creation time (newest first).
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
params = { field: value, ... }
|
23
|
+
customers = client.customer.list(params)
|
24
|
+
|
25
|
+
# or pass them as keyword arguments
|
26
|
+
customers = client.customer.list(field: value, ...)
|
27
|
+
|
28
|
+
# or since the parameters are all optional
|
29
|
+
customers = client.customer.list
|
30
|
+
```
|
31
|
+
|
32
|
+
**Returns:** `Page` of [`CustomerRow`](#customerrow)
|
33
|
+
|
34
|
+
**Parameters:**
|
35
|
+
|
36
|
+
- `params`: `Hash` — See the fields right below.
|
37
|
+
|
38
|
+
| Field | Required? | Type | Description |
|
39
|
+
| --------------- | --------- | ------------ | ------------------------------------------------------- |
|
40
|
+
| `limit` | Optional | `Integer` | The maximum number of results to return. Default: `10`. |
|
41
|
+
| `after` | Optional | `CursorLike` | See docs on pagination. |
|
42
|
+
| `customer_code` | Optional | `String` | Filter by customer code. |
|
43
|
+
|
44
|
+
|
45
|
+
Objects
|
46
|
+
-------
|
47
|
+
|
48
|
+
### `CustomerRow`
|
49
|
+
|
50
|
+
| Field | Type | Description |
|
51
|
+
| ----------------- | ------------------------------------------------------------ | --------------------------------------------- |
|
52
|
+
| `id` | `String` | The ID of the customer. |
|
53
|
+
| `registered_name` | `String` | The official registered name of the customer. |
|
54
|
+
| `trade_name` | `String` \| `nil` | The trade name of the customer. |
|
55
|
+
| `customer_code` | `String` \| `nil` | The customer code assigned to this customer. |
|
56
|
+
| `credit_line` | [`CustomerCreditLineInfo`](#customercreditlineinfo) \| `nil` | The credit line of the customer. |
|
57
|
+
|
58
|
+
|
59
|
+
### `CustomerCreditLineInfo`
|
60
|
+
|
61
|
+
| Field | Type | Description |
|
62
|
+
| ------------------ | ------- | ------------------------------------------ |
|
63
|
+
| `credit_limit` | `Money` | The credit limit. |
|
64
|
+
| `amount_available` | `Money` | The amount available for this credit line. |
|
@@ -0,0 +1,93 @@
|
|
1
|
+
[*← Return to index*](../index.md)
|
2
|
+
|
3
|
+
Order module
|
4
|
+
============
|
5
|
+
|
6
|
+
**Endpoints:**
|
7
|
+
-  [`fetch(id)`](#-fetchid)
|
8
|
+
-  [`create(params)`](#-createparams)
|
9
|
+
|
10
|
+
**Objects:**
|
11
|
+
- [`Order`](#order)
|
12
|
+
- [`OrderStatus`](#orderstatus)
|
13
|
+
- [`OrderCustomerInfo`](#ordercustomerinfo)
|
14
|
+
|
15
|
+
|
16
|
+
Endpoints
|
17
|
+
---------
|
18
|
+
|
19
|
+
###  `fetch(id)`
|
20
|
+
|
21
|
+
Provides information about the order specified.
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
order = client.order.fetch(id)
|
25
|
+
```
|
26
|
+
|
27
|
+
**Returns:** [Order](#order)
|
28
|
+
|
29
|
+
**Parameters:**
|
30
|
+
|
31
|
+
- `id`: `String` — The ID of the order.
|
32
|
+
|
33
|
+
|
34
|
+
###  `create(params)`
|
35
|
+
|
36
|
+
Creates a new order.
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
params = { field: value, ... }
|
40
|
+
order = client.order.create(params)
|
41
|
+
```
|
42
|
+
|
43
|
+
**Returns:** [`Order`](#order) — The newly created order.
|
44
|
+
|
45
|
+
**Parameters:**
|
46
|
+
|
47
|
+
- `params`: `Hash` — See the fields right below.
|
48
|
+
|
49
|
+
| Field | Required? | Type | Description |
|
50
|
+
| -------------- | --------- | ----------- | ------------------------------------------------------------------------------ |
|
51
|
+
| `customer_id` | Required* | `String` | The (Yield) customer ID that this order will belong to. |
|
52
|
+
| `total_amount` | Required | `MoneyLike` | The total amount of the order. |
|
53
|
+
| `note` | Required* | `String` | A note shown to the customer during checkout, such as details about the order. |
|
54
|
+
|
55
|
+
\* These fields may become optional in a future release.
|
56
|
+
|
57
|
+
|
58
|
+
Objects
|
59
|
+
-------
|
60
|
+
|
61
|
+
### `Order`
|
62
|
+
|
63
|
+
| Field | Type | Description |
|
64
|
+
| --------------- | -------------------------------------------------- | --------------------------------------------------------------------------------------------- |
|
65
|
+
| `id` | `String` | The ID of the order. |
|
66
|
+
| `order_number` | `String` | The order number. |
|
67
|
+
| `status` | [`OrderStatus`](#orderstatus) | The status of the order. |
|
68
|
+
| `customer` | [`OrderCustomerInfo`](#ordercustomerinfo) \| `nil` | The customer this order belongs to. |
|
69
|
+
| `date` | `Date` | The date of the order. |
|
70
|
+
| `total_amount` | `Money` | The total amount of the order. |
|
71
|
+
| `note` | `String` \| `nil` | A note shown to the customer during checkout, such as details about the order. |
|
72
|
+
| `payment_link` | `String` \| `nil` | The payment link for the customer to confirm this order. May be `nil` if no longer available. |
|
73
|
+
| `creation_time` | `Time` | The timestamp when this order was created. |
|
74
|
+
|
75
|
+
|
76
|
+
### `OrderStatus`
|
77
|
+
|
78
|
+
| Value | Description |
|
79
|
+
| ------------ | --------------------------------------------------------------------------------------- |
|
80
|
+
| `:pending` | The initial status for newly created orders. The customer has yet to confirm the order. |
|
81
|
+
| `:confirmed` | The customer has confirmed the order. |
|
82
|
+
| `:fulfilled` | The order has been marked as fulfilled. |
|
83
|
+
| `:cancelled` | The order has been cancelled. |
|
84
|
+
|
85
|
+
|
86
|
+
### `OrderCustomerInfo`
|
87
|
+
|
88
|
+
| Field | Type | Description |
|
89
|
+
| ----------------- | ----------------- | --------------------------------------------- |
|
90
|
+
| `id` | `String` | The ID of the customer. |
|
91
|
+
| `registered_name` | `String` | The official registered name of the customer. |
|
92
|
+
| `trade_name` | `String` \| `nil` | The trade name of the customer. |
|
93
|
+
| `customer_code` | `String` \| `nil` | The customer code assigned to this customer. |
|
@@ -0,0 +1,48 @@
|
|
1
|
+
[*← Return to index*](../index.md)
|
2
|
+
|
3
|
+
Self module
|
4
|
+
===========
|
5
|
+
|
6
|
+
**Endpoints:**
|
7
|
+
-  [`info`](#-info)
|
8
|
+
|
9
|
+
**Objects:**
|
10
|
+
- [`SelfInfo`](#selfinfo)
|
11
|
+
- [`SelfOrganizationInfo`](#selforganizationinfo)
|
12
|
+
|
13
|
+
|
14
|
+
Endpoints
|
15
|
+
---------
|
16
|
+
|
17
|
+
###  `info`
|
18
|
+
|
19
|
+
Provides information about the API key used to call this endpoint.
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
info = client.self.info
|
23
|
+
```
|
24
|
+
|
25
|
+
**Returns:** [`SelfInfo`](#selfinfo)
|
26
|
+
|
27
|
+
**Parameters:** None
|
28
|
+
|
29
|
+
|
30
|
+
Objects
|
31
|
+
-------
|
32
|
+
|
33
|
+
### `SelfInfo`
|
34
|
+
|
35
|
+
| Field | Type | Description |
|
36
|
+
| -------------- | ----------------------------------------------- | ------------------------------------- |
|
37
|
+
| `id` | `String` | The ID of the API key. |
|
38
|
+
| `name` | `String` | Name of the API key. |
|
39
|
+
| `organization` | [`SelfOrganizationInfo`](#selforganizationinfo) | The organization this key belongs to. |
|
40
|
+
|
41
|
+
|
42
|
+
### `SelfOrganizationInfo`
|
43
|
+
|
44
|
+
| Field | Type | Description |
|
45
|
+
| ----------------- | ----------------- | ------------------------------------------------- |
|
46
|
+
| `id` | `String` | The ID of the organization. |
|
47
|
+
| `registered_name` | `String` | The official registered name of the organization. |
|
48
|
+
| `trade_name` | `String` \| `nil` | The trade name of the organization. |
|
@@ -7,6 +7,7 @@ require "openssl"
|
|
7
7
|
require "time"
|
8
8
|
require "uri"
|
9
9
|
|
10
|
+
require_relative "../utils/type_utils"
|
10
11
|
require_relative "../version"
|
11
12
|
require_relative "api_result"
|
12
13
|
|
@@ -14,47 +15,74 @@ module Yield
|
|
14
15
|
module SDK
|
15
16
|
module API
|
16
17
|
class Client
|
18
|
+
def initialize(api_key, base_url: nil, conn: nil)
|
19
|
+
@base_url = base_url || "https://integrate.withyield.com/api/v1"
|
20
|
+
@api_key_token, @api_key_hmac_key = Client.extract_api_key(api_key)
|
21
|
+
@conn = conn || Faraday.new
|
22
|
+
@client_version = SDK.client_version
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.extract_api_key(key)
|
26
|
+
# "$" is the old separator, supported for backwards compatibility
|
27
|
+
key_parts = key.gsub("$", ":").split(":")
|
28
|
+
raise ArgumentError, "Invalid Yield API key" if key_parts.length != 3
|
29
|
+
|
30
|
+
token = "#{key_parts[0]}$#{key_parts[1]}"
|
31
|
+
hmac_key = Base64.urlsafe_decode64(key_parts[2])
|
32
|
+
[token, hmac_key]
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.build_signature(hmac_key, timestamp, path, body = nil)
|
36
|
+
parts = body.nil? ? [timestamp, path] : [timestamp, path, body]
|
37
|
+
message = parts.join("\n")
|
38
|
+
sig_bytes = OpenSSL::HMAC.digest("sha512", hmac_key, message)
|
39
|
+
Base64.urlsafe_encode64(sig_bytes, padding: false)
|
40
|
+
end
|
41
|
+
|
17
42
|
def self.process_response(response, &from_payload_block)
|
18
43
|
status_code = response.status
|
19
44
|
request_id = response["X-Request-Id"]
|
20
45
|
|
21
|
-
|
46
|
+
unless response.success?
|
22
47
|
error_type = "unexpected_error"
|
23
|
-
|
48
|
+
error_body = nil
|
24
49
|
|
25
50
|
begin
|
26
51
|
body = JSON.parse(response.body)
|
27
|
-
|
28
|
-
|
52
|
+
if body.is_a?(Hash)
|
53
|
+
error_type = body["error"] if body["error"].is_a?(String)
|
54
|
+
error_body = body
|
55
|
+
end
|
56
|
+
rescue StandardError
|
29
57
|
# ignore
|
30
58
|
end
|
31
59
|
|
32
|
-
return Result.failure(status_code, request_id, error_type)
|
60
|
+
return Result.failure(status_code, request_id, error_type, error_body, nil)
|
33
61
|
end
|
34
62
|
|
35
63
|
begin
|
36
|
-
|
37
|
-
|
38
|
-
|
64
|
+
body = JSON.parse(response.body, symbolize_names: true)
|
65
|
+
payload = TypeUtils.expect_record(body)
|
66
|
+
data = from_payload_block.call(payload)
|
67
|
+
rescue StandardError => e
|
68
|
+
return Result.failure(status_code, request_id, "invalid_response", nil, e)
|
39
69
|
end
|
40
70
|
|
41
71
|
Result.success(status_code, request_id, data)
|
42
72
|
end
|
43
73
|
|
44
|
-
def initialize(api_key, base_url: nil, faraday_conn: nil)
|
45
|
-
@base_url = base_url || "https://integrate.withyield.com/api/v1"
|
46
|
-
|
47
|
-
key_parts = api_key.split("$")
|
48
|
-
raise ArgumentError, "Invalid Yield API key" if key_parts.length != 3
|
49
|
-
@api_key_token = "#{key_parts[0]}$#{key_parts[1]}"
|
50
|
-
@api_key_hmac_key = Base64.urlsafe_decode64(key_parts[2])
|
51
|
-
|
52
|
-
@faraday_conn = faraday_conn || Faraday.new
|
53
|
-
@client_version = SDK.client_version
|
54
|
-
end
|
55
|
-
|
56
74
|
def run_query(path, params = nil)
|
57
|
-
full_path =
|
75
|
+
full_path = path
|
76
|
+
unless params.nil?
|
77
|
+
# Faraday sorts query parameters by default,
|
78
|
+
# so we need to sort it as well for the signature to match.
|
79
|
+
# We can disable this globally, but that may be undesirable for some users.
|
80
|
+
# See: https://lostisland.github.io/faraday/#/customization/index?id=order-of-parameters
|
81
|
+
params = params.compact.to_a.sort_by! { |k, _v| k }
|
82
|
+
query_string = URI.encode_www_form(params)
|
83
|
+
full_path += "?#{query_string}" unless query_string.empty?
|
84
|
+
end
|
85
|
+
|
58
86
|
call_endpoint(:get, full_path, nil)
|
59
87
|
end
|
60
88
|
|
@@ -62,30 +90,19 @@ module Yield
|
|
62
90
|
call_endpoint(:post, path, payload)
|
63
91
|
end
|
64
92
|
|
65
|
-
def build_signature(path, body = nil, now = Time.now)
|
66
|
-
timestamp = now.utc.iso8601
|
67
|
-
|
68
|
-
parts = body.nil? ? [timestamp, path] : [timestamp, path, body]
|
69
|
-
message = parts.join("\n")
|
70
|
-
|
71
|
-
signature_bytes = OpenSSL::HMAC.digest("sha512", @api_key_hmac_key, message)
|
72
|
-
signature_b64 = Base64.urlsafe_encode64(signature_bytes, padding: false)
|
73
|
-
|
74
|
-
"#{@api_key_token}$#{timestamp}$#{signature_b64}"
|
75
|
-
end
|
76
|
-
|
77
93
|
private
|
78
94
|
|
79
95
|
def call_endpoint(method, path, payload)
|
80
|
-
headers = {"X-Yield-Client" => @client_version}
|
96
|
+
headers = { "X-Yield-Client" => @client_version }
|
81
97
|
|
82
98
|
body = payload&.to_json
|
83
99
|
headers["Content-Type"] = "application/json" if body
|
84
100
|
|
85
|
-
|
86
|
-
|
101
|
+
timestamp = Time.now.utc.iso8601
|
102
|
+
signature = Client.build_signature(@api_key_hmac_key, timestamp, path, body)
|
103
|
+
headers["Authorization"] = "Yield-Sig #{@api_key_token}$#{timestamp}$#{signature}"
|
87
104
|
|
88
|
-
@
|
105
|
+
@conn.run_request(method, @base_url + path, body, headers)
|
89
106
|
end
|
90
107
|
end
|
91
108
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
|
5
|
+
module Yield
|
6
|
+
module SDK
|
7
|
+
module API
|
8
|
+
class Error < StandardError
|
9
|
+
attr_reader :status_code
|
10
|
+
attr_reader :request_id
|
11
|
+
attr_reader :details
|
12
|
+
|
13
|
+
def initialize(status_code, request_id, error)
|
14
|
+
@status_code = status_code
|
15
|
+
@request_id = request_id
|
16
|
+
@details = error
|
17
|
+
|
18
|
+
error_info = error.type
|
19
|
+
if error.type == "validation_error" && !error.body.nil?
|
20
|
+
issues = JSON.generate(error.body["issues"])
|
21
|
+
error_info = "#{error_info} #{issues}"
|
22
|
+
end
|
23
|
+
|
24
|
+
unless error.exception.nil?
|
25
|
+
message = JSON.generate(error.exception.message)
|
26
|
+
error_info = "#{error_info} #{message}"
|
27
|
+
end
|
28
|
+
|
29
|
+
extra_info = [
|
30
|
+
"status_code=#{status_code}",
|
31
|
+
"request_id=#{request_id || "<none>"}",
|
32
|
+
].join("; ")
|
33
|
+
|
34
|
+
super("Yield API error: #{error_info} [#{extra_info}]")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -1,24 +1,41 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "api_error"
|
4
|
+
require_relative "api_error_details"
|
5
|
+
|
3
6
|
module Yield
|
4
7
|
module SDK
|
5
8
|
module API
|
6
|
-
class Result
|
9
|
+
class Result
|
10
|
+
attr_reader :status_code
|
11
|
+
attr_reader :request_id
|
12
|
+
attr_reader :error
|
13
|
+
|
14
|
+
def initialize(status_code:, request_id:, data:, error:)
|
15
|
+
@status_code = status_code
|
16
|
+
@request_id = request_id
|
17
|
+
@data = data
|
18
|
+
@error = error
|
19
|
+
end
|
20
|
+
|
7
21
|
def ok?
|
8
22
|
error.nil?
|
9
23
|
end
|
10
24
|
|
11
25
|
def data
|
12
|
-
raise Error,
|
13
|
-
|
26
|
+
raise Error.new(status_code, request_id, error), cause: error.exception unless error.nil?
|
27
|
+
|
28
|
+
@data
|
14
29
|
end
|
15
30
|
|
16
31
|
def self.success(status_code, request_id, data)
|
17
|
-
new(status_code
|
32
|
+
new(status_code: status_code, request_id: request_id, data: data, error: nil)
|
18
33
|
end
|
19
34
|
|
20
|
-
def self.failure(status_code, request_id,
|
21
|
-
new(
|
35
|
+
def self.failure(status_code, request_id, error_type, error_body, exception)
|
36
|
+
error = ErrorDetails.new(error_type, error_body, exception)
|
37
|
+
|
38
|
+
new(status_code: status_code, request_id: request_id, data: nil, error: error)
|
22
39
|
end
|
23
40
|
end
|
24
41
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "api/api_client"
|
4
|
+
require_relative "modules/customer/customer_base_client"
|
4
5
|
require_relative "modules/order/order_base_client"
|
5
6
|
require_relative "modules/self/self_base_client"
|
6
7
|
|
@@ -9,14 +10,16 @@ module Yield
|
|
9
10
|
class BaseClient
|
10
11
|
attr_reader :api
|
11
12
|
|
13
|
+
attr_reader :customer
|
12
14
|
attr_reader :self
|
13
15
|
attr_reader :order
|
14
16
|
|
15
|
-
def initialize(api_key, base_url: nil,
|
16
|
-
@api = API::Client.new(api_key, base_url
|
17
|
+
def initialize(api_key, base_url: nil, conn: nil)
|
18
|
+
@api = API::Client.new(api_key, base_url: base_url, conn: conn)
|
17
19
|
|
18
|
-
@
|
20
|
+
@customer = Customer::BaseClient.new(@api)
|
19
21
|
@order = Order::BaseClient.new(@api)
|
22
|
+
@self = Self::BaseClient.new(@api)
|
20
23
|
end
|
21
24
|
end
|
22
25
|
end
|
data/lib/yield/sdk/client.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "base_client"
|
4
|
+
require_relative "modules/customer/customer_client"
|
4
5
|
require_relative "modules/order/order_client"
|
5
6
|
require_relative "modules/self/self_client"
|
6
7
|
|
@@ -9,14 +10,16 @@ module Yield
|
|
9
10
|
class Client
|
10
11
|
attr_reader :base
|
11
12
|
|
12
|
-
attr_reader :
|
13
|
+
attr_reader :customer
|
13
14
|
attr_reader :order
|
15
|
+
attr_reader :self
|
14
16
|
|
15
|
-
def initialize(api_key, base_url: nil,
|
16
|
-
@base = BaseClient.new(api_key, base_url
|
17
|
+
def initialize(api_key, base_url: nil, conn: nil)
|
18
|
+
@base = BaseClient.new(api_key, base_url: base_url, conn: conn)
|
17
19
|
|
18
|
-
@
|
20
|
+
@customer = Customer::Client.new(@base.customer)
|
19
21
|
@order = Order::Client.new(@base.order)
|
22
|
+
@self = Self::Client.new(@base.self)
|
20
23
|
end
|
21
24
|
end
|
22
25
|
end
|