flowcommerce-activemerchant 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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: []