smartpay 0.6.0 → 0.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 446eb4c4c827e38b97a57ecbceee0b43a932d53cdb11a6bd22215250c5897583
4
- data.tar.gz: a6e513f1be63893df11793c7b74c66cea109e715423c2f0fbbb25c8869ed5089
3
+ metadata.gz: f015233da3625d9cb3178fb715f7885d9cd0680816dbb368a0ed4ab530577a37
4
+ data.tar.gz: 98909c98c67fd90c2bb66862edb643f54680b236bdb027e8f6ae6bf3fdd11e77
5
5
  SHA512:
6
- metadata.gz: a274f5a5917cb8bef8bdabe0360f284436be5bc8f8052f7db9b6233eb6f7a18cfd798f4d1a63bd3d0a57e8e8cae1defc8f477e7e7bfe388531f13384e59245ce
7
- data.tar.gz: 58c21a2d55b9fac38a560ac032d6af7f27f8bc2a61a6477fd1dcd2e884b2791d20f734c79dcd7be8c2b5b49f32eafec8f26604438cc55bf84313a46e5d864a3d
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
- "customerInfo": {
59
- "emailAddress": "success@smartpay.co",
60
- },
61
- "orderData": {
62
- "amount": 250,
63
- "currency": "JPY",
64
- "shippingInfo": {
65
- "address": {
66
- "line1": "line1",
67
- "locality": "locality",
68
- "postalCode": "123",
69
- "country": "JP"
70
- },
71
- },
72
- "lineItemData": [{
73
- "priceData": {
74
- "productData": {
75
- "name": "レブロン 18 LOW",
76
- },
77
- "amount": 250,
78
- "currency": "JPY",
79
- },
80
- "quantity": 1
81
- }]
82
- },
83
- "reference": "order_ref_1234567",
84
- "successUrl": "https://docs.smartpay.co/example-pages/checkout-successful",
85
- "cancelUrl": "https://docs.smartpay.co/example-pages/checkout-canceled"
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/[USERNAME]/smartpay. 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/[USERNAME]/smartpay/blob/master/CODE_OF_CONDUCT.md).
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/[USERNAME]/smartpay/blob/master/CODE_OF_CONDUCT.md).
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::CheckoutSession.new(payload).as_hash)
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
@@ -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
- response = RestClient::Request.execute(method: :get, url: api_url(path),
13
- headers: headers.merge(params: request_params),
14
- timeout: timeout)
15
- JSON.parse(response.body, symbolize_names: true)
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
- def post(path, params: {}, payload: {})
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 = nonce
22
- response = with_retries(:max_tries => 1, :rescue => [RestClient::BadRequest, RestClient::BadGateway, RestClient::ServiceUnavailable, RestClient::GatewayTimeout]) do
23
- RestClient::Request.execute(method: :post, url: api_url(path),
24
- params: request_params,
25
- headers: headers.merge({Idempotency_Key: idempotency_key}).merge(params: request_params),
26
- timeout: timeout,
27
- payload: request_payload.to_json)
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).merge({'Idempotency-Key': nonce})
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 = nonce
36
- response = with_retries(:max_tries => 1, :rescue => [RestClient::InternalServerError, RestClient::BadGateway, RestClient::ServiceUnavailable, RestClient::GatewayTimeout]) do
37
- RestClient::Request.execute(method: :put, url: api_url(path),
38
- params: request_params,
39
- headers: headers.merge({Idempotency_Key: idempotency_key}).merge(params: request_params),
40
- timeout: timeout,
41
- payload: request_payload.to_json)
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.post_timeout
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 :post_timeout, :api_url, :checkout_url
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
- @post_timeout = DEFAULT_TIMEOUT_SETTING
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 post_timeout
27
- @post_timeout || DEFAULT_TIMEOUT_SETTING
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 = [:successUrl, :cancelUrl, :customer, :currency, :items].freeze
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.dig(:customerInfo) || payload.dig(:customer) || {}),
38
- captureMethod: payload.dig(:captureMethod),
39
- currency: payload.dig(:currency),
40
- description: payload.dig(:description),
41
- shippingInfo: shipping_info,
42
- items: normalize_items(payload.dig(:items)),
43
- metadata: payload.dig(:metadata) || {},
44
- reference: payload.dig(:reference),
45
- successUrl: payload.dig(:successUrl),
46
- cancelUrl: payload.dig(:cancelUrl),
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
- return normalized
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(response)
9
- @response = response
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
@@ -12,7 +12,7 @@ module Smartpay
12
12
 
13
13
  return "#{url}#{qs}"
14
14
  end
15
-
15
+
16
16
  url
17
17
  end
18
18
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Smartpay
4
- VERSION = "0.6.0"
4
+ VERSION = "0.8.0"
5
5
  end
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.6.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: 2022-09-22 00:00:00.000000000 Z
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