afterpay 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +24 -0
  3. data/.gitignore +13 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +5 -0
  6. data/.travis.yml +5 -0
  7. data/Gemfile +8 -0
  8. data/LICENSE +224 -0
  9. data/README.md +103 -0
  10. data/Rakefile +8 -0
  11. data/afterpay.gemspec +41 -0
  12. data/bin/console +15 -0
  13. data/bin/setup +8 -0
  14. data/lib/afterpay/api/base.rb +37 -0
  15. data/lib/afterpay/api/configuration/retrieve.rb +20 -0
  16. data/lib/afterpay/api/configuration.rb +9 -0
  17. data/lib/afterpay/api/order/create.rb +27 -0
  18. data/lib/afterpay/api/order.rb +9 -0
  19. data/lib/afterpay/api/payment/auth.rb +29 -0
  20. data/lib/afterpay/api/payment/capture.rb +29 -0
  21. data/lib/afterpay/api/payment/deferred_capture.rb +30 -0
  22. data/lib/afterpay/api/payment/find.rb +28 -0
  23. data/lib/afterpay/api/payment/refund.rb +30 -0
  24. data/lib/afterpay/api/payment/void.rb +30 -0
  25. data/lib/afterpay/api/payment.rb +9 -0
  26. data/lib/afterpay/callable.rb +11 -0
  27. data/lib/afterpay/components/base.rb +14 -0
  28. data/lib/afterpay/components/consumer.rb +27 -0
  29. data/lib/afterpay/components/contact.rb +52 -0
  30. data/lib/afterpay/components/courier.rb +27 -0
  31. data/lib/afterpay/components/discount.rb +17 -0
  32. data/lib/afterpay/components/item.rb +48 -0
  33. data/lib/afterpay/components/merchant.rb +17 -0
  34. data/lib/afterpay/components/money.rb +17 -0
  35. data/lib/afterpay/components/order.rb +67 -0
  36. data/lib/afterpay/components/payment.rb +22 -0
  37. data/lib/afterpay/components/payment_event.rb +17 -0
  38. data/lib/afterpay/components/refund.rb +29 -0
  39. data/lib/afterpay/error_handler.rb +38 -0
  40. data/lib/afterpay/errors.rb +31 -0
  41. data/lib/afterpay/http_service/request.rb +46 -0
  42. data/lib/afterpay/http_service/response.rb +34 -0
  43. data/lib/afterpay/http_service.rb +30 -0
  44. data/lib/afterpay/initializable.rb +27 -0
  45. data/lib/afterpay/representable.rb +47 -0
  46. data/lib/afterpay/version.rb +5 -0
  47. data/lib/afterpay.rb +66 -0
  48. metadata +311 -0
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Afterpay
4
+ module Components
5
+ class Courier < Base
6
+ # @attribute shipped_at
7
+ # @return [String]
8
+ # The time at which the order was shipped (ISO 8601 UTC/Zulu time).
9
+ attr_accessor :shipped_at
10
+
11
+ # @attribute name
12
+ # @return [String]
13
+ # The name of the courier.
14
+ attr_accessor :name
15
+
16
+ # @attribute tracking
17
+ # @return [String]
18
+ # The tracking number provided by the courier.
19
+ attr_accessor :tracking
20
+
21
+ # @attribute priority
22
+ # @return [String]
23
+ # The shipping priority. If provided, must be either 'STANDARD' or 'EXPRESS'.
24
+ attr_accessor :priority
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Afterpay
4
+ module Components
5
+ class Discount < Base
6
+ # @attribute display_name
7
+ # @return [String]
8
+ # A display name for the discount.
9
+ attr_accessor :display_name
10
+
11
+ # @attribute amount
12
+ # @return [Afterpay::Components::Money]
13
+ # The discount amount.
14
+ attr_accessor :amount
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Afterpay
4
+ module Components
5
+ class Item < Base
6
+ # @attribute name
7
+ # @return [String]
8
+ # Product's name
9
+ attr_accessor :name
10
+
11
+ # @attribute sku
12
+ # @return [String]
13
+ # Product's SKU
14
+ attr_accessor :sku
15
+
16
+ # @attribute page_url
17
+ # @return [String]
18
+ # The canonical URL for the item's Product Detail Page. Limited to 2048 characters.
19
+ attr_accessor :page_url
20
+
21
+ # @attribute image_url
22
+ # @return [String]
23
+ # A URL for a web-optimised photo of the item, suitable for use directly as the src attribute of an img tag. Limited to 2048 characters.
24
+ attr_accessor :image_url
25
+
26
+ # @attribute quantity
27
+ # @return [Integer]
28
+ # The quantity of the item.
29
+ attr_accessor :quantity
30
+
31
+ # @attribute price
32
+ # @return [Afterpay::Components::Money]
33
+ # The unit price of the individual item. Must be a positive value.
34
+ attr_accessor :price
35
+
36
+ # @attribute categories
37
+ # @return [Array]
38
+ # An array of arrays to accommodate multiple categories that apply to the item.
39
+ # Each array represents a hierarchical path to a category, with the left-most category being the top-level parent category.
40
+ attr_accessor :categories
41
+
42
+ # @attribute estimated_shipment_date
43
+ # @return [String]
44
+ # The estimated date when the order will be shipped, in YYYY-MM or YYYY-MM-DD format
45
+ attr_accessor :estimated_shipment_date
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Afterpay
4
+ module Components
5
+ class Merchant < Base
6
+ # @attribute redirect_confirm_url
7
+ # @return [String]
8
+ # The user is redirected to this URL on confirmation.
9
+ attr_accessor :redirect_confirm_url
10
+
11
+ # @attribute redirect_cancel_url
12
+ # @return [String]
13
+ # The user to redirected to this URL if the payment process is cancelled.
14
+ attr_accessor :redirect_cancel_url
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Afterpay
4
+ module Components
5
+ class Money < Base
6
+ # @attribute amount
7
+ # @return [String]
8
+ # The amount should be a string representation of a decimal number, rounded to 2 decimal places.
9
+ attr_accessor :amount
10
+
11
+ # @attribute currency
12
+ # @return [String]
13
+ # The currency is a ISO 4217 format value. Currently only USD is supported.
14
+ attr_accessor :currency
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Afterpay
4
+ module Components
5
+ class Order < Base
6
+ # @attribute amount
7
+ # @return [Afterpay::Components::Money]
8
+ # Total amount for order to be charged to consumer.
9
+ attr_accessor :amount
10
+
11
+ # @attribute consumer
12
+ # @return [Afterpay::Components::Consumer]
13
+ # The consumer requesting the order.
14
+ attr_accessor :consumer
15
+
16
+ # @attribute billing
17
+ # @return [Afterpay::Components::Contact]
18
+ # Billing address.
19
+ attr_accessor :billing
20
+
21
+ # @attribute shipping
22
+ # @return [Afterpay::Components::Contact]
23
+ # Shipping address.
24
+ attr_accessor :shipping
25
+
26
+ # @attribute courier
27
+ # @return [Afterpay::Components::Courier]
28
+ # Shipping Courier details.
29
+ attr_accessor :courier
30
+
31
+ # @attribute items
32
+ # @return [Array<Afterpay::Components::Item>]
33
+ # An array of order items.
34
+ attr_accessor :items
35
+
36
+ # @attribute discounts
37
+ # @return [Array<Afterpay::Components::Discount>]
38
+ # An array of discounts.
39
+ attr_accessor :discounts
40
+
41
+ # @attribute merchant
42
+ # @return [Afterpay::Components::Merchant]
43
+ # Merchant's redirection links..
44
+ attr_accessor :merchant
45
+
46
+ # @attribute payment_type
47
+ # @return [String]
48
+ # Supported payment types: 'PAY_BY_INSTALLMENT'. Default is 'PAY_BY_INSTALLMENT'.
49
+ attr_accessor :payment_type
50
+
51
+ # @attribute merchant_reference
52
+ # @return [String]
53
+ # The merchant's id / reference that this order corresponds to.
54
+ attr_accessor :merchant_reference
55
+
56
+ # @attribute tax_amount
57
+ # @return [Afterpay::Components::Money]
58
+ # The included tax amount after applying all discounts.
59
+ attr_accessor :tax_amount
60
+
61
+ # @attribute shipping_amount
62
+ # @return [Afterpay::Components::Money]
63
+ # The shipping amount.
64
+ attr_accessor :shipping_amount
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Afterpay
4
+ module Components
5
+ class Payment < Base
6
+ # @attribute token
7
+ # @return [String]
8
+ # The token returned in the order creation request.
9
+ attr_accessor :token
10
+
11
+ # @attribute merchant_reference
12
+ # @return [String]
13
+ # The merchant's order id / reference that this payment corresponds to
14
+ attr_accessor :merchant_reference
15
+
16
+ # @attribute amount
17
+ # @return [Afterpay::Components::Money]
18
+ # The refund amount.
19
+ attr_accessor :amount
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Afterpay
4
+ module Components
5
+ class PaymentEvent < Base
6
+ # @attribute created
7
+ # @return [String]
8
+ # The payment event creation time (ISO 8601 UTC/Zulu time).
9
+ attr_accessor :created
10
+
11
+ # @attribute type
12
+ # @return [String]
13
+ # The payment event type of {'AUTHORISE', 'CAPTURE', 'VOID'}
14
+ attr_accessor :type
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Afterpay
4
+ module Components
5
+ class Refund < Base
6
+ # @attribute request_id
7
+ # @return [String]
8
+ # A unique request ID, required for safe retries. It is recommended that the merchant generate a UUID for each
9
+ # unique refund.
10
+ attr_accessor :request_id
11
+
12
+ # @attribute merchant_reference
13
+ # @return [String]
14
+ # The merchant's refund id / reference that this refund corresponds to.
15
+ attr_accessor :merchant_reference
16
+
17
+ # @attribute refund_merchant_reference
18
+ # @return [String]
19
+ # A unique reference for the individual refund event. If provided, the value will appear in the daily settlement
20
+ # file as "Payment Event ID". Limited to 128 characters.
21
+ attr_accessor :refund_merchant_reference
22
+
23
+ # @attribute amount
24
+ # @return [Afterpay::Components::Money]
25
+ # The refund amount.
26
+ attr_accessor :amount
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'afterpay/errors'
4
+
5
+ module Afterpay
6
+ module ErrorHandler
7
+ class << self
8
+ # Returns a response if request was successful, raises an error otherwise
9
+ # @param [Afterpay::HTTPService::Response] response
10
+ # @return [Afterpay::HTTPService::Response] if request was successful
11
+ def inspect(response)
12
+ return response if response.ok?
13
+
14
+ raise ERRORS[response.status], response_message(response)
15
+ end
16
+
17
+ def response_message(response)
18
+ response.body.is_a?(String) ? JSON.parse(response.body)['message'] : response.message
19
+ end
20
+
21
+ ERRORS = {
22
+ 400 => BadRequestError,
23
+ 401 => UnathorizedError,
24
+ 402 => PaymentRequiredError,
25
+ 404 => NotFoundError,
26
+ 405 => MethodNotAllowedError,
27
+ 406 => NotAcceptableError,
28
+ 409 => ConflictError,
29
+ 410 => GoneError,
30
+ 412 => PreconditionFailedError,
31
+ 422 => UnprocessableEntityError,
32
+ 429 => TooManyRequestsError,
33
+ 500 => InternalServerError,
34
+ 503 => ServiceUnavailableError
35
+ }.freeze
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Afterpay
4
+ class BaseError < StandardError; end
5
+
6
+ class BadRequestError < BaseError; end
7
+
8
+ class UnathorizedError < BaseError; end
9
+
10
+ class PaymentRequiredError < BaseError; end
11
+
12
+ class NotFoundError < BaseError; end
13
+
14
+ class MethodNotAllowedError < BaseError; end
15
+
16
+ class NotAcceptableError < BaseError; end
17
+
18
+ class ConflictError < BaseError; end
19
+
20
+ class GoneError < BaseError; end
21
+
22
+ class PreconditionFailedError < BaseError; end
23
+
24
+ class UnprocessableEntityError < BaseError; end
25
+
26
+ class TooManyRequestsError < BaseError; end
27
+
28
+ class InternalServerError < BaseError; end
29
+
30
+ class ServiceUnavailableError < BaseError; end
31
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'faraday'
4
+
5
+ module Afterpay
6
+ module HTTPService
7
+ class Request
8
+ # @attribute middleware
9
+ # @return [Proc] A proc containing Faraday configuration
10
+ attr_reader :middleware
11
+
12
+ # @attribute server
13
+ # @return [String] an API endpoint
14
+ attr_reader :server
15
+
16
+ # Creates Afterpay::HTTPService::Request instance
17
+ # @param [Hash] params hash of parameters
18
+ # @return [Afterpay::HTTPService::Request] Request instance
19
+ def initialize(params = {})
20
+ @middleware = params[:middleware]
21
+ @server = params[:server]
22
+ end
23
+
24
+ # Performs an HTTP request to the specified endpoint with given body
25
+ # @param [Hash] params hash of parameters.
26
+ # @return [Farday::Response] Faraday::Response instance
27
+ def perform(params = {})
28
+ adapter.send(*params.values_at(:action, :endpoint, :body))
29
+ end
30
+
31
+ private
32
+
33
+ # Creates memoized Faraday::Connection instance
34
+ # @return [Faraday::Connection] Faraday::Connection instance
35
+ def adapter
36
+ @adapter ||= Faraday.new(server, faraday_options, &middleware)
37
+ end
38
+
39
+ def faraday_options
40
+ return {} unless ::Afterpay.user_agent
41
+
42
+ { "headers" => { "User-Agent" => ::Afterpay.user_agent } }
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Afterpay
4
+ module HTTPService
5
+ class Response
6
+ extend Forwardable
7
+ # @attribute status
8
+ # @return [Integer] HTTP response status
9
+ attr_reader :status
10
+
11
+ # @attribute body
12
+ # @return [Hash] HTTP response body
13
+ attr_reader :body
14
+
15
+ # @attribute headers
16
+ # @return [Hash] HTTP response headers
17
+ attr_reader :headers
18
+
19
+ def_delegators :body, :message
20
+ # Creates Afterpay::HTTPService::Response instance
21
+ # @param [Hash] params hash of parameters
22
+ # @return [Afterpay::HTTPService::Response] Response instance
23
+ def initialize(params = {})
24
+ @status = params[:status]
25
+ @body = params[:body]
26
+ @headers = params[:headers]
27
+ end
28
+
29
+ def ok?
30
+ (200..201).cover?(status.to_i)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'faraday'
4
+ require 'faraday_middleware'
5
+
6
+ module Afterpay
7
+ module HTTPService
8
+ class << self
9
+ # @return [Hash] default HTTPService configuration
10
+ def configuration
11
+ {
12
+ middleware: DEFAULT_MIDDLEWARE,
13
+ server: ::Afterpay.server
14
+ }
15
+ end
16
+ end
17
+
18
+ # Afterpay default middleware stack
19
+ DEFAULT_MIDDLEWARE = proc do |builder|
20
+ builder.request :json
21
+
22
+ builder.basic_auth(*::Afterpay.configuration.values)
23
+
24
+ builder.response :mashify
25
+ builder.response :json, content_type: /\bjson$/
26
+
27
+ builder.adapter Faraday.default_adapter
28
+ end
29
+ end
30
+ end