smartpay 0.6.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +62 -31
- data/lib/smartpay/api.rb +45 -12
- data/lib/smartpay/client.rb +48 -24
- data/lib/smartpay/configuration.rb +18 -4
- data/lib/smartpay/requests/checkout_session.rb +21 -115
- data/lib/smartpay/requests/checkout_session_for_token.rb +43 -0
- data/lib/smartpay/requests/normalizer.rb +108 -0
- data/lib/smartpay/requests/order.rb +48 -0
- data/lib/smartpay/requests/validator.rb +15 -0
- data/lib/smartpay/responses/base.rb +11 -2
- data/lib/smartpay/responses/checkout_session.rb +1 -1
- data/lib/smartpay/version.rb +1 -1
- data/lib/smartpay.rb +2 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f015233da3625d9cb3178fb715f7885d9cd0680816dbb368a0ed4ab530577a37
|
4
|
+
data.tar.gz: 98909c98c67fd90c2bb66862edb643f54680b236bdb027e8f6ae6bf3fdd11e77
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 556f127ac1e15bec24476e88d2dfaa47918d19818ce24c3a208ee2e6d0a1a367e6f4a97613060d855358414c55980f446d5ef924c06fac50e2912ed69e39da0b
|
7
|
+
data.tar.gz: d5c98640761e4ae80d39520d8b9d8b97864cc13ab3e50fbcea6bee56f794331c610012e4aff41d6aff20bf65013387719e1db306b0784db09471d445db369738
|
data/README.md
CHANGED
@@ -55,35 +55,66 @@ You can find the description and requirement for request payload in [API Documen
|
|
55
55
|
|
56
56
|
```ruby
|
57
57
|
payloaad = {
|
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
|
-
|
58
|
+
currency: "JPY",
|
59
|
+
items: [
|
60
|
+
{
|
61
|
+
name: "オリジナルス STAN SMITH",
|
62
|
+
amount: 1000,
|
63
|
+
currency: "JPY",
|
64
|
+
quantity: 1
|
65
|
+
},
|
66
|
+
{
|
67
|
+
currency: "JPY",
|
68
|
+
amount: 500,
|
69
|
+
name: "Merchant special discount",
|
70
|
+
kind: "discount"
|
71
|
+
},
|
72
|
+
{
|
73
|
+
currency: "JPY",
|
74
|
+
amount: 100,
|
75
|
+
name: "explicit taxes",
|
76
|
+
kind: "tax"
|
77
|
+
}
|
78
|
+
],
|
79
|
+
customerInfo: {
|
80
|
+
accountAge: 20,
|
81
|
+
email: "merchant-support@smartpay.co",
|
82
|
+
firstName: "田中",
|
83
|
+
lastName: "太郎",
|
84
|
+
firstNameKana: "たなか",
|
85
|
+
lastNameKana: "たろう",
|
86
|
+
address: {
|
87
|
+
line1: "北青山 3-6-7",
|
88
|
+
line2: "青山パラシオタワー 11階",
|
89
|
+
subLocality: "",
|
90
|
+
locality: "港区",
|
91
|
+
administrativeArea: "東京都",
|
92
|
+
postalCode: "107-0061",
|
93
|
+
country: "JP"
|
94
|
+
},
|
95
|
+
dateOfBirth: "1985-06-30",
|
96
|
+
gender: "male"
|
97
|
+
},
|
98
|
+
shippingInfo: {
|
99
|
+
address: {
|
100
|
+
line1: "北青山 3-6-7",
|
101
|
+
line2: "青山パラシオタワー 11階",
|
102
|
+
subLocality: "",
|
103
|
+
locality: "港区",
|
104
|
+
administrativeArea: "東京都",
|
105
|
+
postalCode: "107-0061",
|
106
|
+
country: "JP"
|
107
|
+
},
|
108
|
+
feeAmount: 100,
|
109
|
+
feeCurrency: "JPY"
|
110
|
+
},
|
111
|
+
|
112
|
+
captureMethod: "manual",
|
113
|
+
|
114
|
+
reference: "order_ref_1234567",
|
115
|
+
successUrl: "https://docs.smartpay.co/example-pages/checkout-successful",
|
116
|
+
cancelUrl: "https://docs.smartpay.co/example-pages/checkout-canceled"
|
117
|
+
}
|
87
118
|
```
|
88
119
|
|
89
120
|
Create a checkout session by using `Smartpay::Api.create_checkout_session` with your request payload.
|
@@ -170,7 +201,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
170
201
|
|
171
202
|
## Contributing
|
172
203
|
|
173
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
204
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/smartpay-co/sdk-ruby. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/smartpay-co/sdk-ruby/blob/master/CODE_OF_CONDUCT.md).
|
174
205
|
|
175
206
|
## License
|
176
207
|
|
@@ -178,4 +209,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
178
209
|
|
179
210
|
## Code of Conduct
|
180
211
|
|
181
|
-
Everyone interacting in the Smartpay project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/
|
212
|
+
Everyone interacting in the Smartpay project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/smartpay-co/sdk-ruby/blob/master/CODE_OF_CONDUCT.md).
|
data/lib/smartpay/api.rb
CHANGED
@@ -3,9 +3,23 @@
|
|
3
3
|
module Smartpay
|
4
4
|
class Api
|
5
5
|
class << self
|
6
|
-
def create_checkout_session(payload)
|
6
|
+
def create_checkout_session(payload, idempotency_key: nil)
|
7
|
+
return create_checkout_session_for_token(payload, idempotency_key: idempotency_key) if payload[:mode] == "token"
|
8
|
+
|
9
|
+
Responses::CheckoutSession.new(
|
10
|
+
Client.post("/checkout-sessions", params: {}, payload: Requests::CheckoutSession.new(payload).as_hash, idempotency_key: idempotency_key)
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
def create_checkout_session_for_token(payload, idempotency_key: nil)
|
7
15
|
Responses::CheckoutSession.new(
|
8
|
-
Client.post("/checkout-sessions", params: {}, payload: Requests::
|
16
|
+
Client.post("/checkout-sessions", params: {}, payload: Requests::CheckoutSessionForToken.new(payload).as_hash, idempotency_key: idempotency_key)
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
def create_order(payload, idempotency_key: nil)
|
21
|
+
Responses::Base.new(
|
22
|
+
Client.post("/orders", params:{}, payload: Requests::Order.new(payload).as_hash, idempotency_key: idempotency_key)
|
9
23
|
)
|
10
24
|
end
|
11
25
|
|
@@ -17,40 +31,59 @@ module Smartpay
|
|
17
31
|
Responses::Base.new(Client.get("/orders/%s" % id, params: { expand: expand }))
|
18
32
|
end
|
19
33
|
|
20
|
-
def cancel_order(id)
|
34
|
+
def cancel_order(id, idempotency_key: nil)
|
21
35
|
Responses::Base.new(
|
22
|
-
Client.put("/orders/%s/cancellation" % id)
|
36
|
+
Client.put("/orders/%s/cancellation" % id, idempotency_key: idempotency_key)
|
23
37
|
)
|
24
38
|
end
|
25
39
|
|
26
|
-
def create_payment(payload)
|
40
|
+
def create_payment(payload, idempotency_key: nil)
|
27
41
|
Responses::Base.new(
|
28
|
-
Client.post("/payments", params:{}, payload: Requests::Payment.new(payload).as_hash)
|
42
|
+
Client.post("/payments", params:{}, payload: Requests::Payment.new(payload).as_hash, idempotency_key: idempotency_key)
|
29
43
|
)
|
30
44
|
end
|
31
45
|
|
32
|
-
def capture(payload)
|
33
|
-
create_payment(payload)
|
46
|
+
def capture(payload, idempotency_key: nil)
|
47
|
+
create_payment(payload, idempotency_key: idempotency_key)
|
34
48
|
end
|
35
49
|
|
36
50
|
def get_payment(id, expand: '' )
|
37
51
|
Responses::Base.new(Client.get("/payments/%s" % id, params: { expand: expand }))
|
38
52
|
end
|
39
53
|
|
40
|
-
def create_refund(payload)
|
54
|
+
def create_refund(payload, idempotency_key: nil)
|
41
55
|
Responses::Base.new(
|
42
|
-
Client.post("/refunds", params:{}, payload: Requests::Refund.new(payload).as_hash)
|
56
|
+
Client.post("/refunds", params:{}, payload: Requests::Refund.new(payload).as_hash, idempotency_key: idempotency_key)
|
43
57
|
)
|
44
58
|
end
|
45
59
|
|
46
|
-
def refund(payload)
|
47
|
-
create_refund(payload)
|
60
|
+
def refund(payload, idempotency_key: nil)
|
61
|
+
create_refund(payload, idempotency_key: idempotency_key)
|
48
62
|
end
|
49
63
|
|
50
64
|
def get_refund(id, expand: '' )
|
51
65
|
Responses::Base.new(Client.get("/refunds/%s" % id, params: { expand: expand }))
|
52
66
|
end
|
53
67
|
|
68
|
+
def get_tokens(page_token: nil, max_results: nil)
|
69
|
+
Responses::Base.new(Client.get("/tokens", params: { pageToken: page_token, maxResults: max_results }))
|
70
|
+
end
|
71
|
+
|
72
|
+
def get_token(id)
|
73
|
+
Responses::Base.new(Client.get("/tokens/%s" % id))
|
74
|
+
end
|
75
|
+
|
76
|
+
def enable_token(id, idempotency_key: nil)
|
77
|
+
Responses::Base.new(Client.put("/tokens/%s/enable" % id, idempotency_key: idempotency_key))
|
78
|
+
end
|
79
|
+
|
80
|
+
def disable_token(id, idempotency_key: nil)
|
81
|
+
Responses::Base.new(Client.put("/tokens/%s/disable" % id, idempotency_key: idempotency_key))
|
82
|
+
end
|
83
|
+
|
84
|
+
def delete_token(id, idempotency_key: nil)
|
85
|
+
Responses::Base.new(Client.delete("/tokens/%s" % id, idempotency_key: idempotency_key))
|
86
|
+
end
|
54
87
|
end
|
55
88
|
end
|
56
89
|
end
|
data/lib/smartpay/client.rb
CHANGED
@@ -9,38 +9,58 @@ module Smartpay
|
|
9
9
|
class << self
|
10
10
|
def get(path, params: {})
|
11
11
|
request_params = default_params.merge(params)
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
with_retries(retry_options) do
|
13
|
+
RestClient::Request.execute(
|
14
|
+
method: :get,
|
15
|
+
url: api_url(path),
|
16
|
+
headers: headers.merge(params: request_params),
|
17
|
+
timeout: timeout
|
18
|
+
)
|
19
|
+
end
|
16
20
|
end
|
17
21
|
|
18
|
-
|
22
|
+
|
23
|
+
def post(path, params: {}, payload: {}, idempotency_key: nil)
|
19
24
|
request_params = default_params.merge(params)
|
20
25
|
request_payload = default_payload.merge(payload)
|
21
|
-
idempotency_key
|
22
|
-
|
23
|
-
RestClient::Request.execute(
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
26
|
+
idempotency_key ||= nonce
|
27
|
+
with_retries(retry_options) do
|
28
|
+
RestClient::Request.execute(
|
29
|
+
method: :post,
|
30
|
+
url: api_url(path),
|
31
|
+
headers: headers.merge({ Idempotency_Key: idempotency_key }).merge(params: request_params),
|
32
|
+
timeout: timeout,
|
33
|
+
payload: request_payload.to_json
|
34
|
+
)
|
28
35
|
end
|
29
|
-
JSON.parse(response.body, symbolize_names: true)
|
30
36
|
end
|
31
37
|
|
32
|
-
def put(path, params: {}, payload: {})
|
33
|
-
request_params = default_params.merge(params)
|
38
|
+
def put(path, params: {}, payload: {}, idempotency_key: nil)
|
39
|
+
request_params = default_params.merge(params)
|
34
40
|
request_payload = default_payload.merge(payload)
|
35
|
-
idempotency_key
|
36
|
-
|
37
|
-
RestClient::Request.execute(
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
41
|
+
idempotency_key ||= nonce
|
42
|
+
with_retries(retry_options) do
|
43
|
+
RestClient::Request.execute(
|
44
|
+
method: :put,
|
45
|
+
url: api_url(path),
|
46
|
+
headers: headers.merge({ Idempotency_Key: idempotency_key }).merge(params: request_params),
|
47
|
+
timeout: timeout,
|
48
|
+
payload: request_payload.to_json
|
49
|
+
)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def delete(path, params: {}, idempotency_key: nil)
|
54
|
+
request_params = default_params.merge(params)
|
55
|
+
idempotency_key ||= nonce
|
56
|
+
with_retries(retry_options) do
|
57
|
+
RestClient::Request.execute(
|
58
|
+
method: :delete,
|
59
|
+
url: api_url(path),
|
60
|
+
headers: headers.merge({ Idempotency_Key: idempotency_key }).merge(params: request_params),
|
61
|
+
timeout: timeout
|
62
|
+
)
|
42
63
|
end
|
43
|
-
JSON.parse(response.body, symbolize_names: true)
|
44
64
|
end
|
45
65
|
|
46
66
|
private
|
@@ -54,7 +74,7 @@ module Smartpay
|
|
54
74
|
end
|
55
75
|
|
56
76
|
def timeout
|
57
|
-
Smartpay.configuration.
|
77
|
+
Smartpay.configuration.request_timeout
|
58
78
|
end
|
59
79
|
|
60
80
|
def headers
|
@@ -76,6 +96,10 @@ module Smartpay
|
|
76
96
|
}.freeze
|
77
97
|
end
|
78
98
|
|
99
|
+
def retry_options
|
100
|
+
Smartpay.configuration.retry_options
|
101
|
+
end
|
102
|
+
|
79
103
|
def default_payload
|
80
104
|
{}.freeze
|
81
105
|
end
|
@@ -1,16 +1,25 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "rest-client"
|
4
|
+
|
3
5
|
module Smartpay
|
4
6
|
class Configuration
|
5
7
|
attr_accessor :public_key, :secret_key
|
6
|
-
attr_writer :
|
8
|
+
attr_writer :request_timeout, :api_url, :checkout_url, :retry_options
|
7
9
|
|
8
10
|
DEFAULT_TIMEOUT_SETTING = 30
|
9
11
|
DEFAULT_API_URL = "https://api.smartpay.co/v1"
|
10
12
|
DEFAULT_CHECKOUT_URL = "https://checkout.smartpay.co"
|
13
|
+
DEFAULT_RETRY_OPTIONS = {
|
14
|
+
max_tries: 1,
|
15
|
+
base_sleep_seconds: 0.5,
|
16
|
+
max_sleep_seconds: 1.0,
|
17
|
+
rescue: [RestClient::InternalServerError,RestClient::BadGateway,
|
18
|
+
RestClient::ServiceUnavailable, RestClient::GatewayTimeout]
|
19
|
+
}.freeze
|
11
20
|
|
12
21
|
def initialize
|
13
|
-
@
|
22
|
+
@request_timeout = DEFAULT_TIMEOUT_SETTING
|
14
23
|
@api_url = if in_development_mode?
|
15
24
|
ENV["SMARTPAY_API_PREFIX"].downcase || DEFAULT_API_URL
|
16
25
|
else
|
@@ -21,10 +30,11 @@ module Smartpay
|
|
21
30
|
else
|
22
31
|
DEFAULT_CHECKOUT_URL
|
23
32
|
end
|
33
|
+
@retry_options = DEFAULT_RETRY_OPTIONS
|
24
34
|
end
|
25
35
|
|
26
|
-
def
|
27
|
-
@
|
36
|
+
def request_timeout
|
37
|
+
@request_timeout || DEFAULT_TIMEOUT_SETTING
|
28
38
|
end
|
29
39
|
|
30
40
|
def api_url
|
@@ -39,6 +49,10 @@ module Smartpay
|
|
39
49
|
@checkout_url || DEFAULT_CHECKOUT_URL
|
40
50
|
end
|
41
51
|
|
52
|
+
def retry_options
|
53
|
+
@retry_options || DEFAULT_RETRY_OPTIONS
|
54
|
+
end
|
55
|
+
|
42
56
|
private
|
43
57
|
|
44
58
|
def in_development_mode?
|
@@ -1,145 +1,51 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "validator"
|
4
|
+
require_relative "normalizer"
|
5
|
+
|
3
6
|
module Smartpay
|
4
7
|
module Requests
|
8
|
+
# Request Object to create a CheckoutSession for order
|
5
9
|
class CheckoutSession
|
10
|
+
include Validator
|
11
|
+
include Normalizer
|
12
|
+
|
6
13
|
attr_accessor :payload
|
7
14
|
|
8
|
-
REQUIREMENT_KEY_NAME = [
|
9
|
-
LINE_ITEM_KINDS = %w[product tax discount].freeze
|
10
|
-
CAN_FALLBACK_KEYS = [:customer].freeze
|
15
|
+
REQUIREMENT_KEY_NAME = %i[successUrl cancelUrl customerInfo shippingInfo currency items].freeze
|
11
16
|
|
12
17
|
def initialize(raw_payload)
|
13
18
|
@payload = raw_payload.transform_keys(&:to_sym)
|
14
19
|
end
|
15
20
|
|
16
21
|
def as_hash
|
17
|
-
check_requirement!
|
22
|
+
check_requirement!(REQUIREMENT_KEY_NAME)
|
18
23
|
normalize_payload
|
19
24
|
end
|
20
25
|
|
21
26
|
private
|
22
27
|
|
23
|
-
def check_requirement!
|
24
|
-
REQUIREMENT_KEY_NAME.each do |key_name|
|
25
|
-
next if CAN_FALLBACK_KEYS.include?(key_name)
|
26
|
-
raise Errors::InvalidRequestPayloadError, key_name unless payload.include?(key_name)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
28
|
def normalize_payload
|
31
|
-
shipping_info = payload.dig(:shippingInfo) || normalize_shipping(payload.dig(:shipping))
|
32
|
-
if shipping_info && shipping_info[:feeCurrency].nil? && !(shipping_info[:feeAmount].nil?)
|
33
|
-
shipping_info[:feeCurrency] = payload.dig(:currency)
|
34
|
-
end
|
35
|
-
|
36
29
|
normalized = {
|
37
|
-
customerInfo: normalize_customer_info(payload
|
38
|
-
captureMethod: payload
|
39
|
-
currency: payload
|
40
|
-
description: payload
|
41
|
-
shippingInfo:
|
42
|
-
items: normalize_items(payload
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
30
|
+
customerInfo: normalize_customer_info(payload[:customerInfo] || {}),
|
31
|
+
captureMethod: payload[:captureMethod],
|
32
|
+
currency: payload[:currency],
|
33
|
+
description: payload[:description],
|
34
|
+
shippingInfo: normalize_shipping(payload[:shippingInfo], payload[:currency]),
|
35
|
+
items: normalize_items(payload[:items]),
|
36
|
+
locale: payload[:locale],
|
37
|
+
metadata: payload[:metadata] || {},
|
38
|
+
reference: payload[:reference],
|
39
|
+
successUrl: payload[:successUrl],
|
40
|
+
cancelUrl: payload[:cancelUrl]
|
47
41
|
}
|
48
42
|
|
49
43
|
normalized[:amount] = get_total_amount(normalized)
|
50
44
|
|
51
|
-
|
52
|
-
end
|
53
|
-
|
54
|
-
def normalize_customer_info(info)
|
55
|
-
return if info.nil?
|
56
|
-
customer = info.transform_keys(&:to_sym)
|
57
|
-
{
|
58
|
-
accountAge: customer.dig(:accountAge),
|
59
|
-
emailAddress: customer.dig(:emailAddress) || customer.dig(:email),
|
60
|
-
firstName: customer.dig(:firstName),
|
61
|
-
lastName: customer.dig(:lastName),
|
62
|
-
firstNameKana: customer.dig(:firstNameKana),
|
63
|
-
lastNameKana: customer.dig(:lastNameKana),
|
64
|
-
address: customer.dig(:address),
|
65
|
-
phoneNumber: customer.dig(:phoneNumber) || customer.dig(:phone),
|
66
|
-
dateOfBirth: customer.dig(:dateOfBirth),
|
67
|
-
legalGender: customer.dig(:legalGender) || customer.dig(:gender),
|
68
|
-
reference: customer.dig(:reference)
|
69
|
-
}
|
70
|
-
end
|
71
|
-
|
72
|
-
def normalize_shipping(shipping)
|
73
|
-
return if shipping.nil?
|
74
|
-
shipping= shipping.transform_keys(&:to_sym)
|
75
|
-
{
|
76
|
-
address: shipping.dig(:address) || {
|
77
|
-
line1: shipping.dig(:line1),
|
78
|
-
line2: shipping.dig(:line2),
|
79
|
-
line3: shipping.dig(:line3),
|
80
|
-
line4: shipping.dig(:line4),
|
81
|
-
line5: shipping.dig(:line5),
|
82
|
-
subLocality: shipping.dig(:subLocality),
|
83
|
-
locality: shipping.dig(:locality),
|
84
|
-
administrativeArea: shipping.dig(:administrativeArea),
|
85
|
-
postalCode: shipping.dig(:postalCode),
|
86
|
-
country: shipping.dig(:country),
|
87
|
-
},
|
88
|
-
addressType: shipping.dig(:addressType),
|
89
|
-
feeAmount: shipping.dig(:feeAmount),
|
90
|
-
feeCurrency: shipping.dig(:feeCurrency),
|
91
|
-
}
|
92
|
-
end
|
93
|
-
|
94
|
-
def normalize_items(data)
|
95
|
-
return [] if data.nil?
|
96
|
-
|
97
|
-
data.map do |item|
|
98
|
-
line_item = item.transform_keys(&:to_sym)
|
99
|
-
{
|
100
|
-
quantity: line_item.dig(:quantity),
|
101
|
-
label: line_item.dig(:label),
|
102
|
-
name: line_item.dig(:name),
|
103
|
-
amount: line_item.dig(:amount),
|
104
|
-
currency: line_item.dig(:currency),
|
105
|
-
brand: line_item.dig(:brand),
|
106
|
-
categories: line_item.dig(:categories),
|
107
|
-
gtin: line_item.dig(:gtin),
|
108
|
-
images: line_item.dig(:images),
|
109
|
-
reference: line_item.dig(:reference),
|
110
|
-
url: line_item.dig(:url),
|
111
|
-
description: line_item.dig(:description),
|
112
|
-
priceDescription: line_item.dig(:priceDescription),
|
113
|
-
productDescription: line_item.dig(:productDescription),
|
114
|
-
metadata: line_item.dig(:metadata),
|
115
|
-
productMetadata: line_item.dig(:productMetadata),
|
116
|
-
priceMetadata: line_item.dig(:priceMetadata),
|
117
|
-
kind: LINE_ITEM_KINDS.include?(line_item.dig(:kind)) ? line_item.dig(:kind) : nil
|
118
|
-
}
|
119
|
-
end
|
45
|
+
normalized
|
120
46
|
end
|
121
47
|
|
122
|
-
def get_total_amount(raw_payload = nil)
|
123
|
-
total_amount = raw_payload.dig(:amount) || raw_payload.dig("amount")
|
124
|
-
return total_amount if total_amount
|
125
48
|
|
126
|
-
items = raw_payload.dig(:items)
|
127
|
-
|
128
|
-
if !items.nil? && items.count.positive?
|
129
|
-
total_amount = items.inject(0) { |sum, item|
|
130
|
-
amount = item[:amount] || item["amount"] || 0
|
131
|
-
amount = -amount if item[:kind] == "discount"
|
132
|
-
sum + amount
|
133
|
-
}
|
134
|
-
end
|
135
|
-
|
136
|
-
shipping_fee = raw_payload.dig(:shippingInfo, :feeAmount) ||
|
137
|
-
raw_payload.dig(:shippingInfo, "feeAmount") ||
|
138
|
-
0
|
139
|
-
total_amount += shipping_fee
|
140
|
-
|
141
|
-
return total_amount
|
142
|
-
end
|
143
49
|
end
|
144
50
|
end
|
145
51
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "validator"
|
4
|
+
require_relative "normalizer"
|
5
|
+
|
6
|
+
module Smartpay
|
7
|
+
module Requests
|
8
|
+
# Request Object to create a CheckoutSession for token
|
9
|
+
class CheckoutSessionForToken
|
10
|
+
include Validator
|
11
|
+
include Normalizer
|
12
|
+
|
13
|
+
attr_accessor :payload
|
14
|
+
|
15
|
+
REQUIREMENT_KEY_NAME = %i[successUrl cancelUrl customerInfo mode].freeze
|
16
|
+
|
17
|
+
def initialize(raw_payload)
|
18
|
+
@payload = raw_payload.transform_keys(&:to_sym)
|
19
|
+
raise Errors::InvalidRequestPayloadError, "mode" unless payload[:mode] == "token"
|
20
|
+
end
|
21
|
+
|
22
|
+
def as_hash
|
23
|
+
check_requirement!(REQUIREMENT_KEY_NAME)
|
24
|
+
normalize_payload
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def normalize_payload
|
30
|
+
{
|
31
|
+
mode: payload[:mode],
|
32
|
+
customerInfo: normalize_customer_info(payload[:customerInfo] || {}),
|
33
|
+
metadata: payload[:metadata] || {},
|
34
|
+
locale: payload[:locale],
|
35
|
+
reference: payload[:reference],
|
36
|
+
successUrl: payload[:successUrl],
|
37
|
+
cancelUrl: payload[:cancelUrl]
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module Smartpay
|
2
|
+
module Requests
|
3
|
+
module Normalizer
|
4
|
+
|
5
|
+
LINE_ITEM_KINDS = %w[product tax discount].freeze
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def normalize_customer_info(info)
|
10
|
+
return if info.nil?
|
11
|
+
|
12
|
+
customer = info.transform_keys(&:to_sym)
|
13
|
+
{
|
14
|
+
accountAge: customer[:accountAge],
|
15
|
+
emailAddress: customer[:emailAddress] || customer[:email],
|
16
|
+
firstName: customer[:firstName],
|
17
|
+
lastName: customer[:lastName],
|
18
|
+
firstNameKana: customer[:firstNameKana],
|
19
|
+
lastNameKana: customer[:lastNameKana],
|
20
|
+
address: customer[:address],
|
21
|
+
phoneNumber: customer[:phoneNumber] || customer[:phone],
|
22
|
+
dateOfBirth: customer[:dateOfBirth],
|
23
|
+
legalGender: customer[:legalGender] || customer[:gender],
|
24
|
+
reference: customer[:reference]
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
def normalize_shipping(shipping, fallback_currency = nil)
|
29
|
+
return if shipping.nil?
|
30
|
+
|
31
|
+
shipping = shipping.transform_keys(&:to_sym)
|
32
|
+
normalized_shipping = {
|
33
|
+
address: shipping[:address] || {
|
34
|
+
line1: shipping[:line1],
|
35
|
+
line2: shipping[:line2],
|
36
|
+
line3: shipping[:line3],
|
37
|
+
line4: shipping[:line4],
|
38
|
+
line5: shipping[:line5],
|
39
|
+
subLocality: shipping[:subLocality],
|
40
|
+
locality: shipping[:locality],
|
41
|
+
administrativeArea: shipping[:administrativeArea],
|
42
|
+
postalCode: shipping[:postalCode],
|
43
|
+
country: shipping[:country]
|
44
|
+
},
|
45
|
+
addressType: shipping[:addressType],
|
46
|
+
feeAmount: shipping[:feeAmount],
|
47
|
+
feeCurrency: shipping[:feeCurrency]
|
48
|
+
}
|
49
|
+
|
50
|
+
if normalized_shipping && normalized_shipping[:feeCurrency].nil? && !(normalized_shipping[:feeAmount].nil?)
|
51
|
+
normalized_shipping[:feeCurrency] = fallback_currency
|
52
|
+
end
|
53
|
+
normalized_shipping
|
54
|
+
end
|
55
|
+
|
56
|
+
def normalize_items(data)
|
57
|
+
return [] if data.nil?
|
58
|
+
|
59
|
+
data.map do |item|
|
60
|
+
line_item = item.transform_keys(&:to_sym)
|
61
|
+
{
|
62
|
+
quantity: line_item[:quantity],
|
63
|
+
label: line_item[:label],
|
64
|
+
name: line_item[:name],
|
65
|
+
amount: line_item[:amount],
|
66
|
+
currency: line_item[:currency],
|
67
|
+
brand: line_item[:brand],
|
68
|
+
categories: line_item[:categories],
|
69
|
+
gtin: line_item[:gtin],
|
70
|
+
images: line_item[:images],
|
71
|
+
reference: line_item[:reference],
|
72
|
+
url: line_item[:url],
|
73
|
+
description: line_item[:description],
|
74
|
+
priceDescription: line_item[:priceDescription],
|
75
|
+
productDescription: line_item[:productDescription],
|
76
|
+
metadata: line_item[:metadata],
|
77
|
+
productMetadata: line_item[:productMetadata],
|
78
|
+
priceMetadata: line_item[:priceMetadata],
|
79
|
+
kind: LINE_ITEM_KINDS.include?(line_item[:kind]) ? line_item[:kind] : nil
|
80
|
+
}
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def get_total_amount(raw_payload = nil)
|
85
|
+
total_amount = raw_payload[:amount] || raw_payload["amount"]
|
86
|
+
return total_amount if total_amount
|
87
|
+
|
88
|
+
items = raw_payload[:items]
|
89
|
+
|
90
|
+
if !items.nil? && items.count.positive?
|
91
|
+
total_amount = items.inject(0) { |sum, item|
|
92
|
+
amount = item[:amount] || item["amount"] || 0
|
93
|
+
amount = -amount if item[:kind] == "discount"
|
94
|
+
sum + amount
|
95
|
+
}
|
96
|
+
end
|
97
|
+
|
98
|
+
shipping_fee = raw_payload.dig(:shippingInfo, :feeAmount) ||
|
99
|
+
raw_payload.dig(:shippingInfo, "feeAmount") ||
|
100
|
+
0
|
101
|
+
total_amount += shipping_fee
|
102
|
+
|
103
|
+
total_amount
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "validator"
|
4
|
+
require_relative "normalizer"
|
5
|
+
|
6
|
+
module Smartpay
|
7
|
+
module Requests
|
8
|
+
# Request Object to create a CheckoutSession for order
|
9
|
+
class Order
|
10
|
+
include Validator
|
11
|
+
include Normalizer
|
12
|
+
|
13
|
+
attr_accessor :payload
|
14
|
+
|
15
|
+
REQUIREMENT_KEY_NAME = %i[token customerInfo shippingInfo currency items].freeze
|
16
|
+
|
17
|
+
def initialize(raw_payload)
|
18
|
+
@payload = raw_payload.transform_keys(&:to_sym)
|
19
|
+
end
|
20
|
+
|
21
|
+
def as_hash
|
22
|
+
check_requirement!(REQUIREMENT_KEY_NAME)
|
23
|
+
normalize_payload
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def normalize_payload
|
29
|
+
normalized = {
|
30
|
+
token: payload[:token],
|
31
|
+
customerInfo: normalize_customer_info(payload[:customerInfo] || {}),
|
32
|
+
captureMethod: payload[:captureMethod],
|
33
|
+
currency: payload[:currency],
|
34
|
+
shippingInfo: normalize_shipping(payload[:shippingInfo], payload[:currency]),
|
35
|
+
items: normalize_items(payload[:items]),
|
36
|
+
metadata: payload[:metadata] || {},
|
37
|
+
reference: payload[:reference]
|
38
|
+
}
|
39
|
+
|
40
|
+
normalized[:amount] = get_total_amount(normalized)
|
41
|
+
|
42
|
+
normalized
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Smartpay
|
2
|
+
module Requests
|
3
|
+
module Validator
|
4
|
+
|
5
|
+
private
|
6
|
+
|
7
|
+
def check_requirement!(requirement_keys = [])
|
8
|
+
requirement_keys.each do |key_name|
|
9
|
+
raise Errors::InvalidRequestPayloadError, key_name unless payload.include?(key_name)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -5,8 +5,13 @@ module Smartpay
|
|
5
5
|
class Base
|
6
6
|
attr_reader :response
|
7
7
|
|
8
|
-
def initialize(
|
9
|
-
@
|
8
|
+
def initialize(raw_response)
|
9
|
+
@raw_response = raw_response
|
10
|
+
@response = begin
|
11
|
+
JSON.parse(@raw_response.body, symbolize_names: true)
|
12
|
+
rescue JSON::ParserError
|
13
|
+
{ body: @raw_response.body }
|
14
|
+
end if @raw_response
|
10
15
|
end
|
11
16
|
|
12
17
|
def as_hash
|
@@ -16,6 +21,10 @@ module Smartpay
|
|
16
21
|
def as_json
|
17
22
|
@response.to_json
|
18
23
|
end
|
24
|
+
|
25
|
+
def http_code
|
26
|
+
@raw_response.code
|
27
|
+
end
|
19
28
|
end
|
20
29
|
end
|
21
30
|
end
|
data/lib/smartpay/version.rb
CHANGED
data/lib/smartpay.rb
CHANGED
@@ -8,6 +8,8 @@ require_relative "smartpay/client"
|
|
8
8
|
require_relative "smartpay/api"
|
9
9
|
require_relative "smartpay/errors/invalid_request_payload_error"
|
10
10
|
require_relative "smartpay/requests/checkout_session"
|
11
|
+
require_relative "smartpay/requests/checkout_session_for_token"
|
12
|
+
require_relative "smartpay/requests/order"
|
11
13
|
require_relative "smartpay/requests/payment"
|
12
14
|
require_relative "smartpay/requests/refund"
|
13
15
|
require_relative "smartpay/responses/base"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: smartpay
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Smartpay
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-01-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rest-client
|
@@ -66,8 +66,12 @@ files:
|
|
66
66
|
- lib/smartpay/configuration.rb
|
67
67
|
- lib/smartpay/errors/invalid_request_payload_error.rb
|
68
68
|
- lib/smartpay/requests/checkout_session.rb
|
69
|
+
- lib/smartpay/requests/checkout_session_for_token.rb
|
70
|
+
- lib/smartpay/requests/normalizer.rb
|
71
|
+
- lib/smartpay/requests/order.rb
|
69
72
|
- lib/smartpay/requests/payment.rb
|
70
73
|
- lib/smartpay/requests/refund.rb
|
74
|
+
- lib/smartpay/requests/validator.rb
|
71
75
|
- lib/smartpay/responses/base.rb
|
72
76
|
- lib/smartpay/responses/checkout_session.rb
|
73
77
|
- lib/smartpay/version.rb
|