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.
Files changed (3) hide show
  1. data/lib/croipg.rb +1 -0
  2. data/lib/web_teh_xml.rb +340 -0
  3. metadata +78 -0
data/lib/croipg.rb ADDED
@@ -0,0 +1 @@
1
+ require "web_teh_xml.rb"
@@ -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: []