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 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