tamara 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +114 -0
  3. data/.rubocop_todo.yml +21 -0
  4. data/.ruby-version +1 -0
  5. data/CHANGELOG.md +5 -0
  6. data/Gemfile +22 -0
  7. data/Gemfile.lock +227 -0
  8. data/Guardfile +42 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +290 -0
  11. data/Rakefile +19 -0
  12. data/lib/generators/tamara/install_generator.rb +15 -0
  13. data/lib/generators/tamara/templates/tamara.rb +8 -0
  14. data/lib/tamara/api/api_token.rb +14 -0
  15. data/lib/tamara/api/application_service.rb +48 -0
  16. data/lib/tamara/api/orders/authorize.rb +26 -0
  17. data/lib/tamara/api/orders/cancel.rb +38 -0
  18. data/lib/tamara/api/orders/create.rb +71 -0
  19. data/lib/tamara/api/orders/details/merchant_order.rb +28 -0
  20. data/lib/tamara/api/orders/details/tamara_order.rb +28 -0
  21. data/lib/tamara/api/orders.rb +56 -0
  22. data/lib/tamara/api/payment_options/check.rb +34 -0
  23. data/lib/tamara/api/payment_options.rb +13 -0
  24. data/lib/tamara/api/payment_types.rb +23 -0
  25. data/lib/tamara/api/payments/capture.rb +40 -0
  26. data/lib/tamara/api/payments.rb +16 -0
  27. data/lib/tamara/api/request.rb +49 -0
  28. data/lib/tamara/api/signature.rb +25 -0
  29. data/lib/tamara/api/webhooks.rb +28 -0
  30. data/lib/tamara/configuration.rb +5 -0
  31. data/lib/tamara/errors.rb +67 -0
  32. data/lib/tamara/hmac.rb +20 -0
  33. data/lib/tamara/json_schemas/address.rb +23 -0
  34. data/lib/tamara/json_schemas/amount.rb +19 -0
  35. data/lib/tamara/json_schemas/checkout_optional_keys.rb +11 -0
  36. data/lib/tamara/json_schemas/consumer.rb +21 -0
  37. data/lib/tamara/json_schemas/discount.rb +17 -0
  38. data/lib/tamara/json_schemas/item.rb +41 -0
  39. data/lib/tamara/json_schemas/merchant_url.rb +19 -0
  40. data/lib/tamara/json_schemas/orders/cancel.rb +30 -0
  41. data/lib/tamara/json_schemas/orders/create.rb +61 -0
  42. data/lib/tamara/json_schemas/payment_options/check.rb +25 -0
  43. data/lib/tamara/json_schemas/payment_types.rb +21 -0
  44. data/lib/tamara/json_schemas/payments/capture.rb +38 -0
  45. data/lib/tamara/json_schemas/risk_assessment.rb +65 -0
  46. data/lib/tamara/json_schemas/types/boolean.rb +15 -0
  47. data/lib/tamara/json_schemas/types/date.rb +17 -0
  48. data/lib/tamara/json_schemas/types/enum.rb +15 -0
  49. data/lib/tamara/json_schemas/types/float.rb +16 -0
  50. data/lib/tamara/json_schemas/types/integer.rb +17 -0
  51. data/lib/tamara/json_schemas/types/string.rb +21 -0
  52. data/lib/tamara/json_schemas/types/url.rb +15 -0
  53. data/lib/tamara/json_schemas/types/uuid.rb +19 -0
  54. data/lib/tamara/json_schemas/validator.rb +66 -0
  55. data/lib/tamara/json_schemas/webhook.rb +33 -0
  56. data/lib/tamara/json_schemas/webhook_event.rb +37 -0
  57. data/lib/tamara/version.rb +3 -0
  58. data/lib/tamara.rb +101 -0
  59. data/sig/tamara.rbs +4 -0
  60. metadata +181 -0
@@ -0,0 +1,23 @@
1
+ module Tamara
2
+ class PaymentTypes < ApplicationService
3
+ include Tamara::JsonSchemas::PaymentTypes
4
+
5
+ def self.list(country: "SA", order_value: 1, opts: {})
6
+ new(country: country, order_value: order_value, opts: opts).call
7
+ end
8
+
9
+ def call_api
10
+ ::Faraday.get(url, api_params, headers)
11
+ end
12
+
13
+ private
14
+
15
+ def url
16
+ "#{Tamara.checkout_uri}/payment-types"
17
+ end
18
+
19
+ def api_params
20
+ @api_params ||= { country: @params[:country], order_value: @params[:order_value] }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,40 @@
1
+ module Tamara
2
+ module Payments
3
+ class Capture < ApplicationService
4
+ include Tamara::JsonSchemas::Payments::Capture
5
+
6
+ def self.call(order_id:, total_amount:, shipping_info:, items: [], shipping_amount: nil, tax_amount: nil, discount_amount: nil, opts: {})
7
+ new(order_id: order_id,
8
+ total_amount: total_amount,
9
+ shipping_info: shipping_info,
10
+ items: items,
11
+ shipping_amount: shipping_amount,
12
+ tax_amount: tax_amount,
13
+ discount_amount: discount_amount,
14
+ opts: opts).call
15
+ end
16
+
17
+ def call_api
18
+ ::Faraday.post(url, api_params.to_json, headers)
19
+ end
20
+
21
+ private
22
+
23
+ def url
24
+ "#{Tamara.payments_uri}/capture"
25
+ end
26
+
27
+ def api_params
28
+ @api_params ||= {
29
+ order_id: @params[:order_id],
30
+ total_amount: @params[:total_amount],
31
+ shipping_info: @params[:shipping_info],
32
+ items: @params[:items],
33
+ shipping_amount: @params[:shipping_amount],
34
+ tax_amount: @params[:tax_amount],
35
+ discount_amount: @params[:discount_amount]
36
+ }
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,16 @@
1
+ module Tamara
2
+ module Payments
3
+ def self.capture(order_id:, total_amount:, shipping_info:, items: [], shipping_amount: nil, tax_amount: nil, discount_amount: nil, opts: {})
4
+ Tamara::Payments::Capture.call(
5
+ order_id: order_id,
6
+ total_amount: total_amount,
7
+ shipping_info: shipping_info,
8
+ shipping_amount: shipping_amount,
9
+ tax_amount: tax_amount,
10
+ discount_amount: discount_amount,
11
+ items: items,
12
+ opts: opts
13
+ )
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,49 @@
1
+ module Tamara
2
+ module Request
3
+ def headers
4
+ @headers = {
5
+ "Content-Type": "application/json",
6
+ Authorization: "Bearer #{api_token}"
7
+ }
8
+ end
9
+
10
+ def api_token
11
+ @opts[:api_token] || Tamara.api_token || Tamara.configuration.api_token
12
+ end
13
+
14
+ def parsed_response
15
+ @parsed_response ||= begin
16
+ JSON.parse(@response.body)
17
+ rescue StandardError
18
+ {}
19
+ end
20
+ end
21
+
22
+ def error_message
23
+ @error_message = parsed_response[:message]
24
+ end
25
+
26
+ def response_status
27
+ @response_status = @response.status
28
+ end
29
+
30
+ def response_body
31
+ @response_body = @response.body
32
+ end
33
+
34
+ # rubocop:disable Metrics/AbcSize
35
+ def handle_response_error
36
+ case response_status
37
+ when 400
38
+ raise InvalidRequestError.new(error_message, parsed_response.dig(:errors, 0, :error_code), http_status: response_status, http_body: response_body)
39
+ when 401
40
+ raise AuthenticationError.new("Invalid API key", http_status: response_status, http_body: response_body)
41
+ when 404
42
+ raise APIError.new("Resource not found", http_status: response_status, http_body: response_body)
43
+ when (400..599)
44
+ raise APIError.new(error_message, http_status: response_status, http_body: response_body)
45
+ end
46
+ end
47
+ # rubocop:enable Metrics/AbcSize
48
+ end
49
+ end
@@ -0,0 +1,25 @@
1
+ require "jwt"
2
+
3
+ module Tamara
4
+ class Signature < ApplicationService
5
+ def self.verify(token, opts: {})
6
+ new(token: token, opts: opts).call
7
+ end
8
+
9
+ def call
10
+ begin
11
+ decoded = ::JWT.decode(@params[:token], notification_token, true, { algorithm: "HS256" })
12
+ rescue StandardError => e
13
+ return failure(e.message)
14
+ end
15
+
16
+ success(decoded)
17
+ end
18
+
19
+ private
20
+
21
+ def notification_token
22
+ @opts[:notification_token] || Tamara.notification_token || Tamara.configuration.notification_token
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,28 @@
1
+ module Tamara
2
+ class Webhooks < ApplicationService
3
+ include Tamara::JsonSchemas::Webhook
4
+
5
+ def self.register(type:, events:, url:, headers: {}, opts: {})
6
+ new(type: type, events: events, url: url, headers: headers, opts: opts).call
7
+ end
8
+
9
+ def call_api
10
+ ::Faraday.post(url, api_params.to_json, headers)
11
+ end
12
+
13
+ def url
14
+ Tamara.webhooks_uri
15
+ end
16
+
17
+ private
18
+
19
+ def api_params
20
+ @api_params ||= {
21
+ type: @params[:type],
22
+ events: @params[:events],
23
+ url: @params[:url],
24
+ headers: @params[:headers]
25
+ }
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,5 @@
1
+ module Tamara
2
+ class Configuration
3
+ attr_accessor :api_token, :notification_token, :public_key, :checkout_optional_keys
4
+ end
5
+ end
@@ -0,0 +1,67 @@
1
+ module Tamara
2
+ # TamaraError is the base error from which all other more specific Tamara
3
+ # errors derive.
4
+ class TamaraError < StandardError
5
+ attr_reader :message, :error, :http_body, :http_headers, :http_status, :json_body
6
+
7
+ # Initializes a TamaraError.
8
+ def initialize(message = nil, http_status: nil, http_body: nil)
9
+ @message = message || http_body
10
+ @http_status = http_status
11
+ @http_body = http_body
12
+ begin
13
+ @json_body = JSON.parse(http_body)
14
+ rescue StandardError
15
+ @json_body = nil
16
+ end
17
+ end
18
+
19
+ def to_s
20
+ status_string = @http_status.nil? ? "" : "(Status #{@http_status}) "
21
+ "#{status_string}#{@message}"
22
+ end
23
+ end
24
+
25
+ # ConfigurationMissingError is raised when a configuration is missing
26
+ class ConfigurationMissingError < StandardError; end
27
+
28
+ # AuthenticationError is raised when invalid credentials are used to connect
29
+ # to Tamara's servers.
30
+ class AuthenticationError < TamaraError
31
+ end
32
+
33
+ # APIConnectionError is raised in the event that the SDK can't connect to
34
+ # Tamara's servers. That can be for a variety of different reasons from a
35
+ # downed network to a bad TLS certificate.
36
+ class APIConnectionError < TamaraError
37
+ end
38
+
39
+ # APIError is a generic error that may be raised in cases where none of the
40
+ # other named errors cover the problem. It could also be raised in the case
41
+ # that a new error has been introduced in the API, but this version of the
42
+ # Ruby SDK doesn't know how to handle it.
43
+ class APIError < TamaraError
44
+ end
45
+
46
+ # InvalidRequestError is raised when a request is initiated with invalid
47
+ # parameters.
48
+ class InvalidRequestError < TamaraError
49
+ attr_accessor :param
50
+
51
+ def initialize(message, param, http_status: nil, http_body: nil)
52
+ super(message, http_status: http_status, http_body: http_body)
53
+ @param = param
54
+ end
55
+ end
56
+
57
+ # SignatureVerificationError is raised when the signature verification for a
58
+ # webhook fails
59
+ class SignatureVerificationError < TamaraError
60
+ attr_accessor :sig_header
61
+
62
+ def initialize(message, sig_header, http_body: nil)
63
+ super(message, http_body: http_body)
64
+ @sig_header = sig_header
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,20 @@
1
+ module Tamara
2
+ module Hmac
3
+ FILTERED_TRANSACTION_KEYS = %w[amount_cents created_at currency error_occured has_parent_transaction id
4
+ integration_id is_3d_secure is_auth is_capture is_refunded is_standalone_payment
5
+ is_voided order.id owner pending
6
+ source_data.pansource_data.sub_type source_data.type success].freeze
7
+
8
+ class << self
9
+ def valid_signature?(tamara_response)
10
+ digest = ::OpenSSL::Digest.new("sha512")
11
+
12
+ concatenated_str = FILTERED_TRANSACTION_KEYS.map do |element|
13
+ tamara_response.dig("obj", *element.split("."))
14
+ end.join
15
+ secure_hash = ::OpenSSL::HMAC.hexdigest(digest, Tamara.hmac_key, concatenated_str)
16
+ secure_hash == tamara_response["hmac"]
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,23 @@
1
+ module Tamara
2
+ module JsonSchemas
3
+ module Address
4
+ def self.schema(allows_null: false)
5
+ {
6
+ "$schema": "http://json-schema.org/draft-06/schema",
7
+ type: ["object", (allows_null ? "null" : nil)].compact,
8
+ properties: {
9
+ city: Types::String.schema,
10
+ country_code: Types::Enum.schema(values: COUNTRY_CODES, default: "SA"),
11
+ first_name: Types::String.schema,
12
+ last_name: Types::String.schema,
13
+ line1: Types::String.schema,
14
+ line2: Types::String.schema(allows_null: true),
15
+ phone_number: Types::String.schema(allows_null: true),
16
+ region: Types::String.schema(allows_null: true)
17
+ },
18
+ required: %w[city country_code first_name last_name line1]
19
+ }
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,19 @@
1
+ module Tamara
2
+ module JsonSchemas
3
+ module Amount
4
+ CURRENCIES = %w[SAR AED BHD KWD OMR].freeze
5
+
6
+ def self.schema(allows_null: false)
7
+ {
8
+ "$schema": "http://json-schema.org/draft-06/schema",
9
+ type: ["object", (allows_null ? "null" : nil)].compact,
10
+ properties: {
11
+ amount: Types::Float.schema(min: 0.1),
12
+ currency: Types::Enum.schema(values: CURRENCIES, default: "SAR")
13
+ },
14
+ required: %w[amount currency]
15
+ }
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,11 @@
1
+ module Tamara
2
+ module JsonSchemas
3
+ module CheckoutOptionalKeys
4
+ def checkout_optional_keys
5
+ @params ||= {}
6
+ checkout_optional_keys = @params.dig(:opts, :checkout_optional_keys) || Tamara.configuration.checkout_optional_keys
7
+ checkout_optional_keys.is_a?(Hash) ? checkout_optional_keys : {}
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,21 @@
1
+ module Tamara
2
+ module JsonSchemas
3
+ module Consumer
4
+ def self.schema(allows_null: false)
5
+ {
6
+ "$schema": "http://json-schema.org/draft-06/schema",
7
+ type: ["object", (allows_null ? "null" : nil)].compact,
8
+ properties: {
9
+ first_name: Types::String.schema,
10
+ last_name: Types::String.schema,
11
+ email: {
12
+ pattern: URI::MailTo::EMAIL_REGEXP
13
+ },
14
+ phone_number: Types::String.schema
15
+ },
16
+ required: %w[first_name last_name email phone_number]
17
+ }
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,17 @@
1
+ module Tamara
2
+ module JsonSchemas
3
+ module Discount
4
+ def self.schema(allows_null: false)
5
+ {
6
+ "$schema": "http://json-schema.org/draft-06/schema",
7
+ type: ["object", (allows_null ? "null" : nil)].compact,
8
+ properties: {
9
+ name: Types::String.schema,
10
+ amount: Amount.schema
11
+ },
12
+ required: %w[name amount]
13
+ }
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,41 @@
1
+ module Tamara
2
+ module JsonSchemas
3
+ module Item
4
+ extend CheckoutOptionalKeys
5
+
6
+ REQUIRED_KEYS = %w[name quantity reference_id type sku total_amount].freeze
7
+
8
+ # rubocop:disable Metrics/AbcSize
9
+ def self.schema(params = nil)
10
+ @params = params
11
+ {
12
+ "$schema": "http://json-schema.org/draft-06/schema",
13
+ type: "object",
14
+ properties: {
15
+ name: Types::String.schema(allows_null: filtered_keys.exclude?("name")),
16
+ quantity: Types::Integer.schema(min: 1, allows_null: filtered_keys.exclude?("quantity")),
17
+ reference_id: Types::String.schema(allows_null: filtered_keys.exclude?("reference_id")),
18
+ type: Types::String.schema(allows_null: filtered_keys.exclude?("type")),
19
+ sku: Types::String.schema(max_length: 128, allows_null: filtered_keys.exclude?("sku")),
20
+ item_url: Types::Url.schema(allows_null: filtered_keys.exclude?("item_url")),
21
+ image_url: Types::Url.schema(allows_null: filtered_keys.exclude?("image_url")),
22
+ unit_price: Amount.schema(allows_null: filtered_keys.exclude?("unit_price")),
23
+ tax_amount: Amount.schema(allows_null: filtered_keys.exclude?("tax_amount")),
24
+ discount_amount: Amount.schema(allows_null: filtered_keys.exclude?("discount_amount")),
25
+ total_amount: Amount.schema(allows_null: filtered_keys.exclude?("total_amount"))
26
+ },
27
+ required: filtered_keys
28
+ }
29
+ end
30
+ # rubocop:enable Metrics/AbcSize
31
+
32
+ def self.filtered_keys
33
+ @filtered_keys ||= begin
34
+ optional_keys = (checkout_optional_keys[:items] || []).map(&:to_s)
35
+
36
+ REQUIRED_KEYS - optional_keys
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,19 @@
1
+ module Tamara
2
+ module JsonSchemas
3
+ module MerchantUrl
4
+ def self.schema(allows_null: false)
5
+ {
6
+ "$schema": "http://json-schema.org/draft-06/schema",
7
+ type: ["object", (allows_null ? "null" : nil)].compact,
8
+ properties: {
9
+ cancel: Types::Url.schema,
10
+ failure: Types::Url.schema,
11
+ success: Types::Url.schema,
12
+ notification: Types::Url.schema(allows_null: true)
13
+ },
14
+ required: %w[cancel failure success]
15
+ }
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,30 @@
1
+ module Tamara
2
+ module JsonSchemas
3
+ module Orders
4
+ module Cancel
5
+ include Validator
6
+
7
+ private
8
+
9
+ def schema
10
+ {
11
+ "$schema": "http://json-schema.org/draft-06/schema",
12
+ type: "object",
13
+ properties: {
14
+ order_id: Types::Uuid.schema,
15
+ total_amount: Amount.schema,
16
+ shipping_amount: Amount.schema(allows_null: true),
17
+ tax_amount: Amount.schema(allows_null: true),
18
+ discount_amount: Amount.schema(allows_null: true),
19
+ items: {
20
+ type: "array",
21
+ items: Item.schema
22
+ }
23
+ },
24
+ required: %w[order_id total_amount]
25
+ }
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,61 @@
1
+ module Tamara
2
+ module JsonSchemas
3
+ module Orders
4
+ module Create
5
+ include CheckoutOptionalKeys
6
+ include Validator
7
+
8
+ PAYMENT_TYPES = %w[PAY_BY_INSTALMENTS PAY_NOW].freeze
9
+ LOCALES = %w[ar_SA en_US].freeze
10
+
11
+ REQUIRED_KEYS = %w[order_reference_id country_code description total_amount shipping_amount tax_amount
12
+ consumer items merchant_url shipping_address payment_type instalments risk_assessment].freeze
13
+
14
+ private
15
+
16
+ # rubocop:disable Metrics/AbcSize
17
+ def schema
18
+ {
19
+ "$schema": "http://json-schema.org/draft-06/schema",
20
+ type: "object",
21
+ properties: {
22
+ order_reference_id: Types::String.schema(allows_null: filtered_keys.exclude?("order_reference_id")),
23
+ country_code: Types::Enum.schema(values: COUNTRY_CODES, default: "SA"),
24
+ description: Types::String.schema(max_length: 256, allows_null: filtered_keys.exclude?("description")),
25
+ total_amount: Amount.schema(allows_null: filtered_keys.exclude?("total_amount")),
26
+ shipping_amount: Amount.schema(allows_null: filtered_keys.exclude?("shipping_amount")),
27
+ tax_amount: Amount.schema(allows_null: filtered_keys.exclude?("tax_amount")),
28
+ consumer: Consumer.schema(allows_null: filtered_keys.exclude?("consumer")),
29
+ items: {
30
+ type: "array",
31
+ minItems: 1,
32
+ items: Item.schema(@params)
33
+ },
34
+ merchant_url: MerchantUrl.schema(allows_null: filtered_keys.exclude?("merchant_url")),
35
+ shipping_address: Address.schema(allows_null: filtered_keys.exclude?("shipping_address")),
36
+ payment_type: Types::Enum.schema(values: PAYMENT_TYPES, default: "PAY_BY_INSTALMENTS"),
37
+ instalments: Types::Integer.schema(min: 1, default: 3),
38
+ order_number: Types::String.schema(allows_null: filtered_keys.exclude?("order_number")),
39
+ discount: Discount.schema(allows_null: true),
40
+ billing_address: Address.schema(allows_null: true),
41
+ platform: Types::String.schema(allows_null: true),
42
+ is_mobile: Types::Boolean.schema(default: false),
43
+ locale: Types::Enum.schema(values: LOCALES, default: "ar_SA"),
44
+ expires_in_minutes: Types::Integer.schema(min: 5, max: 1440, default: 30),
45
+ risk_assessment: RiskAssessment.schema(allows_null: filtered_keys.exclude?("risk_assessment"), params: @params)
46
+ },
47
+ required: filtered_keys
48
+ }
49
+ end
50
+ # rubocop:enable Metrics/AbcSize
51
+
52
+ def filtered_keys
53
+ @filtered_keys ||= begin
54
+ optional_keys = checkout_optional_keys.select { |_k, v| v.empty? }.keys.map(&:to_s)
55
+ REQUIRED_KEYS - optional_keys
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,25 @@
1
+ module Tamara
2
+ module JsonSchemas
3
+ module PaymentOptions
4
+ module Check
5
+ include Validator
6
+
7
+ private
8
+
9
+ def schema
10
+ {
11
+ "$schema": "http://json-schema.org/draft-06/schema",
12
+ type: "object",
13
+ properties: {
14
+ country: Types::Enum.schema(values: COUNTRY_CODES, default: "SA"),
15
+ phone_number: Types::String.schema,
16
+ order_value: Amount.schema,
17
+ is_vip: Types::Boolean.schema(default: false)
18
+ },
19
+ required: %w[country phone_number order_value]
20
+ }
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,21 @@
1
+ module Tamara
2
+ module JsonSchemas
3
+ module PaymentTypes
4
+ include Validator
5
+
6
+ private
7
+
8
+ def schema
9
+ {
10
+ "$schema": "http://json-schema.org/draft-06/schema",
11
+ type: "object",
12
+ properties: {
13
+ country: Types::Enum.schema(values: COUNTRY_CODES, default: "SA"),
14
+ order_value: Types::Float.schema(min: 0.1)
15
+ },
16
+ required: %w[country order_value]
17
+ }
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,38 @@
1
+ module Tamara
2
+ module JsonSchemas
3
+ module Payments
4
+ module Capture
5
+ include Validator
6
+
7
+ private
8
+
9
+ def schema
10
+ {
11
+ "$schema": "http://json-schema.org/draft-06/schema",
12
+ type: "object",
13
+ properties: {
14
+ order_id: Types::Uuid.schema,
15
+ total_amount: Amount.schema,
16
+ shipping_info: {
17
+ type: "object",
18
+ properties: {
19
+ shipped_at: Types::String.schema,
20
+ shipping_company: Types::String.schema
21
+ },
22
+ required: %w[shipped_at shipping_company]
23
+ },
24
+ items: {
25
+ type: "array",
26
+ items: Item.schema
27
+ },
28
+ shipping_amount: Amount.schema(allows_null: true),
29
+ tax_amount: Amount.schema(allows_null: true),
30
+ discount_amount: Amount.schema(allows_null: true)
31
+ },
32
+ required: %w[order_id total_amount shipping_info]
33
+ }
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end