flowcommerce-activemerchant 0.0.5

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7122820398d8cc92b22fed56f30e950a8d01560a
4
+ data.tar.gz: c276caf8730bf2a863234241d11e24723c18a32b
5
+ SHA512:
6
+ metadata.gz: ffd6e645a8fca291d87302d35f166387d04ad2e79f95370ad2a935d63201fe7d0885e5625b9e2249ba0bb4ed737a221ef39f32286875dfad3bbf19d8ba1d1af3
7
+ data.tar.gz: d8fe9e0da80fd51b41ea1a751cd84733ae853b2ffe326242b69809582df639abd6a5c7e1d0211e5d98e22ba2b7a2af48d6fbd1d4fe0034d4782c732c7925d309
@@ -0,0 +1,182 @@
1
+ # @Flow.io (2017)
2
+ # Active Merchant adapter for Flow api
3
+
4
+ require 'flow-reference'
5
+
6
+ module ActiveMerchant
7
+ module Billing
8
+ class FlowGateway < Gateway
9
+ VERSION = '0.0.5' unless defined?(::ActiveMerchant::Billing::FlowGateway::VERSION)
10
+
11
+ self.display_name = 'Flow.io Pay'
12
+ self.homepage_url = 'https://www.flow.io/'
13
+ self.default_currency = 'USD'
14
+ self.supported_countries = Flow::Reference::Countries::ISO_3166_2
15
+ self.supported_cardtypes = Flow::Reference::PaymentMethods::SUPPORTED_CREDIT_CARDS
16
+
17
+ def initialize(options = {})
18
+ @flow_api_key = options[:api_key] || ENV['FLOW_API_KEY']
19
+ @flow_organization = options[:organization] || ENV['FLOW_ORGANIZATION']
20
+
21
+ raise ArgumentError, "Flow token is not defined (:api_key or ENV['FLOW_API_KEY'])" unless @flow_api_key
22
+ raise ArgumentError, "Flow organization is not defined (:organization or ENV['FLOW_ORGANIZATION'])" unless @flow_organization
23
+
24
+ super
25
+ end
26
+
27
+ # https://docs.flow.io/module/payment/resource/authorizations#post-organization-authorizations
28
+ def authorize(amount, payment_method, options={})
29
+ amount = assert_currency(options[:currency], amount)
30
+
31
+ get_flow_cc_token payment_method
32
+
33
+ data = {
34
+ token: @flow_cc_token,
35
+ amount: amount,
36
+ currency: options[:currency],
37
+ cvv: payment_method.verification_value,
38
+ customer: {
39
+ name: {
40
+ first: payment_method.first_name,
41
+ last: payment_method.last_name
42
+ }
43
+ }
44
+ }
45
+
46
+ begin
47
+ authorization_form = if options[:order_id]
48
+ # order_number allready present at flow
49
+ data[:order_number] = options[:order_id]
50
+ ::Io::Flow::V0::Models::MerchantOfRecordAuthorizationForm.new(data)
51
+ else
52
+ ::Io::Flow::V0::Models::DirectAuthorizationForm.new(data)
53
+ end
54
+ response = flow_instance.authorizations.post(@flow_organization, authorization_form)
55
+ rescue => exception
56
+ return Response.new(false, exception.message, { exception: exception })
57
+ end
58
+
59
+ options = { response: response }
60
+
61
+ if response.result.status.value == 'authorized'
62
+ store = {}
63
+ store[:authorization_id] = response.id
64
+ store[:currency] = response.currency
65
+ store[:amount] = response.amount
66
+ store[:key] = response.key
67
+
68
+ Response.new(true, 'Flow authorize - Success', options, { authorization: store })
69
+ else
70
+ Response.new(false, 'Flow authorize - Error', options)
71
+ end
72
+ end
73
+
74
+ # https://docs.flow.io/module/payment/resource/captures#post-organization-captures
75
+ def capture(_money, authorization, options={})
76
+ raise ArgumentError, 'No Authorization authorization, please authorize first' unless authorization
77
+
78
+ begin
79
+ capture_form = ::Io::Flow::V0::Models::CaptureForm.new(authorization)
80
+ response = flow_instance.captures.post(@flow_organization, capture_form)
81
+ rescue => exception
82
+ error_response(exception)
83
+ end
84
+
85
+ options = { response: response }
86
+
87
+ if response.id
88
+ Response.new(true, 'Flow capture - Success', options)
89
+ else
90
+ Response.new(false, 'Flow capture - Error', options)
91
+ end
92
+ end
93
+
94
+ def purchase(money, credit_card, options={})
95
+ response = authorize money, credit_card, options
96
+ capture money, response.authorization
97
+ end
98
+
99
+ # https://docs.flow.io/module/payment/resource/authorizations#delete-organization-authorizations-key
100
+ def void(money, authorization_key, options={})
101
+ response = flow_instance.authorizations.delete_by_key(@flow_organization, authorization_key)
102
+ Response.new(true, 'void success', { response: response })
103
+ rescue Io::Flow::V0::HttpClient::ServerError => exception
104
+ error_response(exception)
105
+ end
106
+
107
+ # https://docs.flow.io/module/payment/resource/refunds
108
+ # authorization_id - The Id of the authorization against which to issue the refund. If specified, we will look at all captures for this authorization, selecting 1 or more captures against which to issue the refund of the requested amount.
109
+ # capture_id - The Id of the capture against which to issue the refund. If specified, we will only consider this capture.
110
+ # order_number - The order number if specified during authorization. If specified, we will lookup all authorizations made against this order number, and then selecting 1 or more authorizations against which to issue the refund of the requested amount.
111
+ # key - Your unique identifier for this transaction, which if provided is used to implement idempotency. If not provided, we will assign.
112
+ # amount - The amount to refund, in the currency of the associated capture. Defaults to the value of the capture minus any prior refunds.
113
+ # currency - The ISO 4217-3 code for the currency. Required if amount is specified. Case insensitive. Note you will get an error if the currency does not match the related authrization's currency. See https://api.flow.io/reference/currencies
114
+ # rma_key - The RMA key, if available. If specified, this will udpate the RMA status as refunded.
115
+ def refund(amount, capture_id, options={})
116
+ refund_form = {}
117
+ refund_form[:amount] = amount if amount
118
+ refund_form[:capture_id] = capture_id if capture_id
119
+
120
+ [:authorization_id, :currency, :order_number, :key, :rma_key].each do |key|
121
+ refund_form[key] = options[key] if options[key]
122
+ end
123
+
124
+ if refund_form[:amount]
125
+ raise ArgumentError, 'Currency is required if amount is provided' unless refund_form[:currency]
126
+ refund_form[:amount] = assert_currency(refund_form[:currency], refund_form[:amount])
127
+ end
128
+
129
+ refund_form = ::Io::Flow::V0::Models::RefundForm.new(refund_form)
130
+ flow_instance.refunds.post(@flow_organization, refund_form)
131
+ end
132
+
133
+ # store credit card with flow and get reference token
134
+ def store(credit_card, options={})
135
+ token = get_flow_cc_token(credit_card)
136
+ Response.new(true, 'Credit card stored', { token: token })
137
+ rescue Io::Flow::V0::HttpClient::ServerError => exception
138
+ error_response(exception)
139
+ end
140
+
141
+ private
142
+
143
+ def flow_instance
144
+ FlowCommerce.instance(token: @flow_api_key)
145
+ end
146
+
147
+ def get_flow_cc_token(credit_card)
148
+ return if @flow_cc_token
149
+
150
+ data = {}
151
+ data[:number] = credit_card.number
152
+ data[:name] = '%s %s' % [credit_card.first_name, credit_card.last_name]
153
+ data[:cvv] = credit_card.verification_value
154
+ data[:expiration_year] = credit_card.year.to_i
155
+ data[:expiration_month] = credit_card.month.to_i
156
+
157
+ card_form = ::Io::Flow::V0::Models::CardForm.new(data)
158
+ result = flow_instance.cards.post(@flow_organization, card_form)
159
+
160
+ @flow_cc_token = result.token
161
+ end
162
+
163
+ def error_response(exception_object)
164
+ message = if exception_object.respond_to?(:body) && exception_object.body.length > 0
165
+ description = JSON.load(exception_object.body)['messages'].to_sentence
166
+ '%s: %s (%s)' % [exception_object.details, description, exception_object.code]
167
+ else
168
+ exception_object.message
169
+ end
170
+
171
+ Response.new(false, message, exception: exception_object)
172
+ end
173
+
174
+ def assert_currency(currency, amount)
175
+ raise ArgumentError, 'currency not provided' unless currency
176
+ currency_model = Flow::Reference::Currencies.find!(currency)
177
+ currency_model.to_cents(amount).to_f
178
+ end
179
+ end
180
+ end
181
+ end
182
+
@@ -0,0 +1,5 @@
1
+ # Flow 2017
2
+
3
+ require 'flowcommerce'
4
+ require 'active_merchant'
5
+ require_relative 'active_merchant/billing/gateways/flow'
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: flowcommerce-activemerchant
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.5
5
+ platform: ruby
6
+ authors:
7
+ - Dino Reic
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-04-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activemerchant
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.63'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.63'
27
+ - !ruby/object:Gem::Dependency
28
+ name: flowcommerce
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: flow-reference
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Flow.io is PCI compliant gateway which supports authorizations, captures,
56
+ refunds and tokenization of credit cards.
57
+ email: tech@flow.io
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - "./lib/active_merchant/billing/gateways/flow.rb"
63
+ - "./lib/flowcommerce-activemerchant.rb"
64
+ homepage: https://www.flow.io
65
+ licenses:
66
+ - MIT
67
+ metadata: {}
68
+ post_install_message:
69
+ rdoc_options: []
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ requirements: []
83
+ rubyforge_project:
84
+ rubygems_version: 2.6.10
85
+ signing_key:
86
+ specification_version: 4
87
+ summary: Adapter for Flow.io payment gateway
88
+ test_files: []