croipg 0.0.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.
- data/lib/croipg.rb +1 -0
- data/lib/web_teh_xml.rb +340 -0
- metadata +78 -0
data/lib/croipg.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "web_teh_xml.rb"
|
data/lib/web_teh_xml.rb
ADDED
@@ -0,0 +1,340 @@
|
|
1
|
+
# endcoding: utf-8
|
2
|
+
|
3
|
+
require "activemerchant"
|
4
|
+
|
5
|
+
module ActiveMerchant #:nodoc:
|
6
|
+
module Billing #:nodoc:
|
7
|
+
class WebTehXmlGateway < Gateway
|
8
|
+
self.test_url = 'https://ipgtest.webteh.hr'
|
9
|
+
|
10
|
+
# TODO: replace with production value
|
11
|
+
self.live_url = 'https://live.webteh.hr'
|
12
|
+
|
13
|
+
# The countries the gateway supports merchants from as 2 digit ISO country codes
|
14
|
+
self.supported_countries = ['HR']
|
15
|
+
|
16
|
+
# The card types supported by the payment gateway
|
17
|
+
self.supported_cardtypes = [ :american_express, :diners_club, :maestro, :master, :visa ]
|
18
|
+
|
19
|
+
# The homepage URL of the gateway
|
20
|
+
self.homepage_url = 'http://www.webteh.hr/'
|
21
|
+
|
22
|
+
# The name of the gateway
|
23
|
+
self.display_name = 'WebPay'
|
24
|
+
|
25
|
+
# Default currency
|
26
|
+
self.default_currency = 'HRK'
|
27
|
+
|
28
|
+
# Constants
|
29
|
+
REQUEST_APPROVED = "approved"
|
30
|
+
|
31
|
+
RESPONSE_TYPE = {
|
32
|
+
:secure_3d => "secure-message",
|
33
|
+
:error => "errors"
|
34
|
+
}
|
35
|
+
|
36
|
+
# ActiveMerchant::PostsData::ssl_strict
|
37
|
+
self.ssl_strict = false
|
38
|
+
|
39
|
+
# TODO: process response code in response message from authentification/purchase
|
40
|
+
|
41
|
+
def initialize(options = {})
|
42
|
+
requires!(options, :login, :password, :key, :auth_token)
|
43
|
+
@key = options[ :key ]
|
44
|
+
@auth_token = options[ :auth_token ]
|
45
|
+
|
46
|
+
super
|
47
|
+
end
|
48
|
+
|
49
|
+
def authorize(money, creditcard, options = {})
|
50
|
+
return transfer_funds( money, creditcard, options, "authorize" )
|
51
|
+
end
|
52
|
+
|
53
|
+
def purchase(money, creditcard, options = {})
|
54
|
+
return transfer_funds( money, creditcard, options, "purchase" )
|
55
|
+
end
|
56
|
+
|
57
|
+
def capture(money, authorization, options = {})
|
58
|
+
return settle_transfer( money, authorization, options, "capture" )
|
59
|
+
end
|
60
|
+
|
61
|
+
def refund(money, authorization, options = {})
|
62
|
+
return settle_transfer( money, authorization, options, "refund" )
|
63
|
+
end
|
64
|
+
|
65
|
+
def void(money, authorization, options = {})
|
66
|
+
return settle_transfer( money, authorization, options, "void" )
|
67
|
+
end
|
68
|
+
|
69
|
+
def complete_3ds( md, pares )
|
70
|
+
xml = generate_3ds_complete_request( md, pares )
|
71
|
+
|
72
|
+
return commit( "pares", xml )
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def transfer_funds( money, credit_card, options, action )
|
78
|
+
params = normalize_params( money, credit_card, options )
|
79
|
+
params[ :transaction_type ] = action
|
80
|
+
|
81
|
+
xml = generate_auth_request( params )
|
82
|
+
|
83
|
+
return commit('api', money, xml)
|
84
|
+
end
|
85
|
+
|
86
|
+
# |
|
87
|
+
# |--- money
|
88
|
+
# |--- authorization
|
89
|
+
# |--- options
|
90
|
+
# | |--- currency
|
91
|
+
def settle_transfer( money, authorization, options, action )
|
92
|
+
requires!( options, :currency )
|
93
|
+
|
94
|
+
# TODO: xml generation not implemented
|
95
|
+
xml = generate_settle_request( money, authorization, options[ :currency ] )
|
96
|
+
|
97
|
+
path = "transactions/#{authorization}/#{action}.xml"
|
98
|
+
|
99
|
+
commit( path, money, xml )
|
100
|
+
end
|
101
|
+
|
102
|
+
#**********************
|
103
|
+
# * XML docs *
|
104
|
+
# ***********
|
105
|
+
def generate_auth_request( params )
|
106
|
+
xml_out = ""
|
107
|
+
xml = Builder::XmlMarkup.new( :target => xml_out)
|
108
|
+
|
109
|
+
xml.instruct!( :xml, :version => "1.0", :encoding => "UTF-8" )
|
110
|
+
xml.transaction() do |transaction|
|
111
|
+
add_invoice( transaction, params )
|
112
|
+
end
|
113
|
+
|
114
|
+
return xml_out
|
115
|
+
end
|
116
|
+
|
117
|
+
def add_customer_data( parent, params )
|
118
|
+
parent.tag!( "ch-email", params[ :options ][ :email ] )
|
119
|
+
parent.tag!( "ch-full-name", full_name( params[ :credit_card ] ) )
|
120
|
+
parent.tag!( "ch-phone", params[ :options ][ :address ][ :phone ] )
|
121
|
+
end
|
122
|
+
|
123
|
+
def add_address( parent, params )
|
124
|
+
address = params[ :options ][ :address ]
|
125
|
+
|
126
|
+
parent.tag!( "ch-address", replace_diacritics( address[ :address1 ] ) )
|
127
|
+
parent.tag!( "ch-city", replace_diacritics( address[ :city ] ) )
|
128
|
+
parent.tag!( "ch-country", replace_diacritics( address[ :country ] ) )
|
129
|
+
add_customer_data( parent, params )
|
130
|
+
parent.tag!( "ch-zip", params[ :options ][ :address ][ :zip ] )
|
131
|
+
end
|
132
|
+
|
133
|
+
def add_invoice(parent, params)
|
134
|
+
signature_values = [
|
135
|
+
@key,
|
136
|
+
params[ :options ][ :order_id ],
|
137
|
+
params[ :amount ],
|
138
|
+
params[ :options ][ :currency ]
|
139
|
+
]
|
140
|
+
|
141
|
+
parent.tag!( "transaction-type", params[ :transaction_type ] )
|
142
|
+
parent.tag!( "amount", params[ :amount ] )
|
143
|
+
add_creditcard( parent, params )
|
144
|
+
parent.tag!( "ip", params[ :options ][ :ip ] )
|
145
|
+
parent.tag!( "order-info", replace_diacritics( params[ :options ][ :description ] ) )
|
146
|
+
add_address( parent, params )
|
147
|
+
parent.tag!( "currency", params[ :options ][ :currency ] )
|
148
|
+
parent.tag!( "digest", generate_signature( signature_values ) )
|
149
|
+
parent.tag!( "authenticity-token", @auth_token )
|
150
|
+
parent.tag!( "order-number", params[ :options ][ :order_id ] )
|
151
|
+
# TODO: language is not regular param in active merchant
|
152
|
+
parent.tag!( "language", "hr" )
|
153
|
+
end
|
154
|
+
|
155
|
+
def add_creditcard( parent, params )
|
156
|
+
credit_card = params[ :credit_card ]
|
157
|
+
parent.tag!( "expiration-date", format_expiry_date( credit_card ) )
|
158
|
+
parent.tag!( "cvv", credit_card.verification_value )
|
159
|
+
parent.tag!( "pan", credit_card.number )
|
160
|
+
end
|
161
|
+
|
162
|
+
def generate_settle_request( amount, authorization, currency )
|
163
|
+
xml_out = ""
|
164
|
+
xml = Builder::XmlMarkup.new( :target => xml_out )
|
165
|
+
|
166
|
+
signature_values = [ @key, authorization, amount, currency ]
|
167
|
+
|
168
|
+
xml.instruct!( :xml, :version => "1.0", :encoding => "UTF-8" )
|
169
|
+
xml.transaction() do |transaction|
|
170
|
+
xml.tag!( "amount", amount )
|
171
|
+
xml.tag!( "currency", currency )
|
172
|
+
xml.tag!( "digest", generate_signature( signature_values ) )
|
173
|
+
xml.tag!( "authenticity-token", @auth_token )
|
174
|
+
xml.tag!( "order-number", authorization )
|
175
|
+
end
|
176
|
+
|
177
|
+
return xml_out
|
178
|
+
end
|
179
|
+
|
180
|
+
def generate_3ds_complete_request( md, pares )
|
181
|
+
xml_out = ""
|
182
|
+
|
183
|
+
xml = Builder::XmlMarkup.new( :target => xml_out, :indent=> 2, :margin=> 4 )
|
184
|
+
|
185
|
+
xml.instruct!( :xml, :version => "1.0", :encoding => "UTF-8" )
|
186
|
+
xml.tag!( "secure-message" ) do |secure_message|
|
187
|
+
secure_message.tag!( "MD", md )
|
188
|
+
secure_message.tag!( "PaRes", pares )
|
189
|
+
end
|
190
|
+
|
191
|
+
return xml_out
|
192
|
+
end
|
193
|
+
|
194
|
+
def parse(body)
|
195
|
+
data = {}
|
196
|
+
xml = REXML::Document.new( body )
|
197
|
+
|
198
|
+
data[ "response-type" ] = xml.root().name
|
199
|
+
|
200
|
+
processed_nodes = {}
|
201
|
+
xml.root().elements.each() do |node|
|
202
|
+
if processed_nodes.has_key?( node.name )
|
203
|
+
processed_nodes[ node.name ] += 1
|
204
|
+
else
|
205
|
+
processed_nodes[ node.name ] = 0
|
206
|
+
end
|
207
|
+
node_repetition = processed_nodes[ node.name ]
|
208
|
+
node_name = node.name + ( node_repetition == 0 ? "" : node_repetition.to_s() )
|
209
|
+
data[ node_name ] = node.text
|
210
|
+
end
|
211
|
+
return data
|
212
|
+
end
|
213
|
+
|
214
|
+
def commit(action, money, xml)
|
215
|
+
url = "#{self.test_url}/#{action}"
|
216
|
+
|
217
|
+
begin
|
218
|
+
response_body = ssl_post( url, xml, { "Content-Type" => "application/xml" } )
|
219
|
+
rescue ActiveMerchant::ResponseError => error
|
220
|
+
response_body = error.response.body
|
221
|
+
end
|
222
|
+
response_data = parse( response_body )
|
223
|
+
|
224
|
+
return process_response_data( response_data )
|
225
|
+
end
|
226
|
+
|
227
|
+
def process_response_data( response_data )
|
228
|
+
# Authentification/Purchase response
|
229
|
+
if response_data[ "status" ]
|
230
|
+
return Response.new(
|
231
|
+
response_data[ "status" ] == REQUEST_APPROVED,
|
232
|
+
response_data[ "response-message" ],
|
233
|
+
response_data
|
234
|
+
)
|
235
|
+
# 3D Secure/Error
|
236
|
+
else
|
237
|
+
# 3D Secure
|
238
|
+
if response_data[ "response-type" ] == RESPONSE_TYPE[ :secure_3d ]
|
239
|
+
return Response.new(
|
240
|
+
false,
|
241
|
+
"3D secure enabled card. Additional authentication needed",
|
242
|
+
response_data
|
243
|
+
)
|
244
|
+
# Error
|
245
|
+
else
|
246
|
+
return Response.new(
|
247
|
+
false,
|
248
|
+
"Errors",
|
249
|
+
response_data
|
250
|
+
)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
def message_from(response)
|
256
|
+
end
|
257
|
+
|
258
|
+
def post_data(action, parameters = {})
|
259
|
+
end
|
260
|
+
|
261
|
+
# module WebTehCommons
|
262
|
+
|
263
|
+
CRO_DIACRITICS_MAP = {
|
264
|
+
[ 'Š' ] => 'S',
|
265
|
+
[ 'š' ] => 's',
|
266
|
+
[ 'Č', 'Ć' ] => 'C',
|
267
|
+
[ 'č', 'ć' ] => 'c',
|
268
|
+
[ 'Ž' ] => 'Z',
|
269
|
+
[ 'ž' ] => 'z',
|
270
|
+
[ 'Đ' ] => 'D',
|
271
|
+
[ 'đ' ] => 'd'
|
272
|
+
}
|
273
|
+
|
274
|
+
def replace_diacritics( input )
|
275
|
+
clear_text = input
|
276
|
+
|
277
|
+
CRO_DIACRITICS_MAP.each() do |diacritics, letter|
|
278
|
+
diacritics.each() do |diacritic|
|
279
|
+
clear_text = clear_text.gsub( diacritic, letter )
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
return clear_text
|
284
|
+
end
|
285
|
+
|
286
|
+
def generate_signature( values )
|
287
|
+
text = ""
|
288
|
+
values.each() { |value| text += "#{value}" }
|
289
|
+
|
290
|
+
signature = Digest::SHA1.hexdigest( text )
|
291
|
+
return signature
|
292
|
+
end
|
293
|
+
|
294
|
+
def format_expiry_date( credit_card )
|
295
|
+
return format( credit_card.year, :two_digits ) + format( credit_card.month, :two_digits )
|
296
|
+
end
|
297
|
+
|
298
|
+
def full_name( credit_card )
|
299
|
+
return replace_diacritics( credit_card.name )
|
300
|
+
end
|
301
|
+
|
302
|
+
=begin
|
303
|
+
params
|
304
|
+
|--- amount
|
305
|
+
|--- ? transaction_type => { authorize | purchase} sets invoked method
|
306
|
+
|--- credit_card
|
307
|
+
| |--- first_name
|
308
|
+
| |--- last_name
|
309
|
+
| |--- number
|
310
|
+
| |--- year
|
311
|
+
| |--- month
|
312
|
+
| |--- verification_value
|
313
|
+
|
|
314
|
+
|--- options
|
315
|
+
| |--- order_id
|
316
|
+
| |--- description
|
317
|
+
| |--- currency
|
318
|
+
| |--- email
|
319
|
+
| |--- ip
|
320
|
+
| |--- address
|
321
|
+
| | |--- address1
|
322
|
+
| | |--- city
|
323
|
+
| | |--- country
|
324
|
+
| | |--- zip
|
325
|
+
| | |--- phone
|
326
|
+
=end
|
327
|
+
def normalize_params( amount, credit_card, options )
|
328
|
+
requires!( options, :order_id, :description, :currency, :email, :ip, :address )
|
329
|
+
requires!( options[ :address ], :address1, :city, :country, :zip, :phone )
|
330
|
+
params = {
|
331
|
+
:amount => amount,
|
332
|
+
:credit_card => credit_card,
|
333
|
+
:options => options
|
334
|
+
}
|
335
|
+
|
336
|
+
return params
|
337
|
+
end
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: croipg
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ja Vrabac
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-03-01 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activemerchant
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '1.29'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.29'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: activemerchant
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '1.29'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '1.29'
|
46
|
+
description: Support for cro IPG's
|
47
|
+
email: ja@vrabac.com
|
48
|
+
executables: []
|
49
|
+
extensions: []
|
50
|
+
extra_rdoc_files: []
|
51
|
+
files:
|
52
|
+
- lib/croipg.rb
|
53
|
+
- lib/web_teh_xml.rb
|
54
|
+
homepage: http://www.example.com
|
55
|
+
licenses: []
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options: []
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ! '>='
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
requirements: []
|
73
|
+
rubyforge_project:
|
74
|
+
rubygems_version: 1.8.25
|
75
|
+
signing_key:
|
76
|
+
specification_version: 3
|
77
|
+
summary: Cro ActiveMerchant IPG
|
78
|
+
test_files: []
|