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 +7 -0
- data/lib/active_merchant/billing/gateways/flow.rb +182 -0
- data/lib/flowcommerce-activemerchant.rb +5 -0
- metadata +88 -0
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
|
+
|
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: []
|