better_offsite_payments 2.3.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 (66) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +76 -0
  4. data/lib/offsite_payments.rb +39 -0
  5. data/lib/offsite_payments/action_view_helper.rb +72 -0
  6. data/lib/offsite_payments/helper.rb +120 -0
  7. data/lib/offsite_payments/integrations.rb +14 -0
  8. data/lib/offsite_payments/integrations/a1agregator.rb +245 -0
  9. data/lib/offsite_payments/integrations/authorize_net_sim.rb +580 -0
  10. data/lib/offsite_payments/integrations/bit_pay.rb +150 -0
  11. data/lib/offsite_payments/integrations/bogus.rb +32 -0
  12. data/lib/offsite_payments/integrations/chronopay.rb +283 -0
  13. data/lib/offsite_payments/integrations/citrus.rb +227 -0
  14. data/lib/offsite_payments/integrations/coinbase.rb +172 -0
  15. data/lib/offsite_payments/integrations/direc_pay.rb +332 -0
  16. data/lib/offsite_payments/integrations/directebanking.rb +237 -0
  17. data/lib/offsite_payments/integrations/doku.rb +171 -0
  18. data/lib/offsite_payments/integrations/dotpay.rb +166 -0
  19. data/lib/offsite_payments/integrations/dwolla.rb +160 -0
  20. data/lib/offsite_payments/integrations/e_payment_plans.rb +146 -0
  21. data/lib/offsite_payments/integrations/easy_pay.rb +137 -0
  22. data/lib/offsite_payments/integrations/epay.rb +161 -0
  23. data/lib/offsite_payments/integrations/first_data.rb +133 -0
  24. data/lib/offsite_payments/integrations/gestpay.rb +205 -0
  25. data/lib/offsite_payments/integrations/hi_trust.rb +179 -0
  26. data/lib/offsite_payments/integrations/ipay88.rb +251 -0
  27. data/lib/offsite_payments/integrations/klarna.rb +275 -0
  28. data/lib/offsite_payments/integrations/liqpay.rb +216 -0
  29. data/lib/offsite_payments/integrations/maksuturva.rb +231 -0
  30. data/lib/offsite_payments/integrations/megakassa.rb +184 -0
  31. data/lib/offsite_payments/integrations/mollie.rb +32 -0
  32. data/lib/offsite_payments/integrations/mollie_ideal.rb +194 -0
  33. data/lib/offsite_payments/integrations/mollie_mistercash.rb +143 -0
  34. data/lib/offsite_payments/integrations/molpay.rb +193 -0
  35. data/lib/offsite_payments/integrations/moneybookers.rb +199 -0
  36. data/lib/offsite_payments/integrations/nochex.rb +228 -0
  37. data/lib/offsite_payments/integrations/pag_seguro.rb +268 -0
  38. data/lib/offsite_payments/integrations/paxum.rb +114 -0
  39. data/lib/offsite_payments/integrations/pay_fast.rb +269 -0
  40. data/lib/offsite_payments/integrations/paydollar.rb +142 -0
  41. data/lib/offsite_payments/integrations/payflow_link.rb +194 -0
  42. data/lib/offsite_payments/integrations/paypal.rb +362 -0
  43. data/lib/offsite_payments/integrations/paypal_payments_advanced.rb +23 -0
  44. data/lib/offsite_payments/integrations/paysbuy.rb +71 -0
  45. data/lib/offsite_payments/integrations/payu_in.rb +276 -0
  46. data/lib/offsite_payments/integrations/payu_in_paisa.rb +46 -0
  47. data/lib/offsite_payments/integrations/platron.rb +153 -0
  48. data/lib/offsite_payments/integrations/pxpay.rb +273 -0
  49. data/lib/offsite_payments/integrations/quickpay.rb +232 -0
  50. data/lib/offsite_payments/integrations/rbkmoney.rb +110 -0
  51. data/lib/offsite_payments/integrations/realex_offsite.rb +317 -0
  52. data/lib/offsite_payments/integrations/robokassa.rb +154 -0
  53. data/lib/offsite_payments/integrations/sage_pay_form.rb +431 -0
  54. data/lib/offsite_payments/integrations/two_checkout.rb +329 -0
  55. data/lib/offsite_payments/integrations/universal.rb +190 -0
  56. data/lib/offsite_payments/integrations/valitor.rb +200 -0
  57. data/lib/offsite_payments/integrations/verkkomaksut.rb +143 -0
  58. data/lib/offsite_payments/integrations/web_pay.rb +186 -0
  59. data/lib/offsite_payments/integrations/webmoney.rb +119 -0
  60. data/lib/offsite_payments/integrations/wirecard_checkout_page.rb +359 -0
  61. data/lib/offsite_payments/integrations/world_pay.rb +280 -0
  62. data/lib/offsite_payments/integrations/yandex_money.rb +175 -0
  63. data/lib/offsite_payments/notification.rb +71 -0
  64. data/lib/offsite_payments/return.rb +37 -0
  65. data/lib/offsite_payments/version.rb +3 -0
  66. metadata +297 -0
@@ -0,0 +1,133 @@
1
+ module OffsitePayments #:nodoc:
2
+ module Integrations #:nodoc:
3
+ module FirstData
4
+ # Overwrite this if you want to change the ANS test url
5
+ mattr_accessor :test_url
6
+ self.test_url = 'https://demo.globalgatewaye4.firstdata.com/payment'
7
+
8
+ # Overwrite this if you want to change the ANS production url
9
+ mattr_accessor :production_url
10
+ self.production_url = 'https://checkout.globalgatewaye4.firstdata.com/payment'
11
+
12
+ def self.service_url
13
+ mode = OffsitePayments.mode
14
+ case mode
15
+ when :production
16
+ self.production_url
17
+ when :test
18
+ self.test_url
19
+ else
20
+ raise StandardError, "Integration mode set to an invalid value: #{mode}"
21
+ end
22
+ end
23
+
24
+ def self.notification(post)
25
+ Notification.new(post)
26
+ end
27
+
28
+ def self.return(query_string)
29
+ Return.new(query_string)
30
+ end
31
+
32
+ # First Data payment pages emulates the Authorize.Net SIM API. See
33
+ # OffsitePayments::Integrations::AuthorizeNetSim::Helper for
34
+ # more details.
35
+ #
36
+ # An example. Note the username as a parameter and transaction key you
37
+ # will want to use later.
38
+ #
39
+ # payment_service_for('order_id', 'first_data_payment_page_id', :service => :first_data, :amount => 157.0) do |service|
40
+ #
41
+ # # You must call setup_hash and invoice
42
+ #
43
+ # service.setup_hash :transaction_key => '8CP6zJ7uD875J6tY',
44
+ # :order_timestamp => 1206836763
45
+ # service.customer_id 8
46
+ # service.customer :first_name => 'g',
47
+ # :last_name => 'g',
48
+ # :email => 'g@g.com',
49
+ # :phone => '3'
50
+ # service.billing_address :zip => 'g',
51
+ # :country => 'United States of America',
52
+ # :address => 'g'
53
+ #
54
+ # service.ship_to_address :first_name => 'g',
55
+ # :last_name => 'g',
56
+ # :city => '',
57
+ # :address => 'g',
58
+ # :address2 => '',
59
+ # :state => address.state,
60
+ # :country => 'United States of America',
61
+ # :zip => 'g'
62
+ #
63
+ # service.invoice "516428355" # your invoice number
64
+ # # The end-user is presented with the HTML produced by the notify_url
65
+ # # (using the First Data Receipt Link feature).
66
+ # service.return_url "http://mysite/first_data_receipt_generator_page"
67
+ # service.payment_header 'My store name'
68
+ # service.add_line_item :name => 'item name', :quantity => 1, :unit_price => 0
69
+ # service.test_request 'true' # only if it's just a test
70
+ # service.shipping '25.0'
71
+ # # Tell it to display a "0" line item for shipping, with the price in
72
+ # # the name, otherwise it isn't shown at all, leaving the end user to
73
+ # # wonder why the total is different than the sum of the line items.
74
+ # service.add_shipping_as_line_item
75
+ # server.add_tax_as_line_item # same with tax
76
+ # # See the helper.rb file for various custom fields
77
+ # end
78
+ class Helper < OffsitePayments::Integrations::AuthorizeNetSim::Helper
79
+ # Configure notify_url to use the "Relay Response" feature
80
+ mapping :notify_url, 'x_relay_url'
81
+
82
+ # Configure return_url to use the "Receipt Link" feature
83
+ mapping :return_url, 'x_receipt_link_url'
84
+ end
85
+
86
+ # First Data payment pages emulates the Authorize.Net SIM API. See
87
+ # OffsitePayments::Integrations::FirstData::Notification for
88
+ # more details.
89
+ #
90
+ # # Example:
91
+ # parser = FirstData::Notification.new(request.raw_post)
92
+ # passed = parser.complete?
93
+ #
94
+ # order = Order.find_by_order_number(parser.invoice_num)
95
+ #
96
+ # unless order
97
+ # @message = 'Error--unable to find your transaction! Please contact us directly.'
98
+ # return render :partial => 'first_data_payment_response'
99
+ # end
100
+ #
101
+ # if order.total != parser.gross.to_f
102
+ # logger.error "First Data said they paid for #{parser.gross} and it should have been #{order.total}!"
103
+ # passed = false
104
+ # end
105
+ #
106
+ # # Theoretically, First Data will *never* pass us the same transaction
107
+ # # ID twice, but we can double check that... by using
108
+ # # parser.transaction_id, and checking against previous orders' transaction
109
+ # # id's (which you can save when the order is completed)....
110
+ # unless parser.acknowledge FIRST_DATA_TRANSACTION_KEY, FIRST_DATA_RESPONSE_KEY
111
+ # passed = false
112
+ # logger.error "ALERT POSSIBLE FRAUD ATTEMPT"
113
+ # end
114
+ #
115
+ # unless parser.cavv_matches? and parser.avs_code_matches?
116
+ # logger.error 'Warning--non matching CC!' + params.inspect
117
+ # # Could fail them here, as well (recommended)...
118
+ # end
119
+ #
120
+ # if passed
121
+ # # Set up your session, and render something that will redirect them to
122
+ # # your site, most likely.
123
+ # else
124
+ # # Render failure or redirect them to your site where you will render failure
125
+ # end
126
+ class Notification < OffsitePayments::Integrations::AuthorizeNetSim::Notification
127
+ def acknowledge(response_key, payment_page_id)
128
+ Digest::MD5.hexdigest(response_key + payment_page_id + params['x_trans_id'] + sprintf('%.2f', gross)) == params['x_MD5_Hash'].downcase
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,205 @@
1
+ # With help from Giovanni Intini and his code for RGestPay - http://medlar.it/it/progetti/rgestpay
2
+
3
+ module OffsitePayments #:nodoc:
4
+ module Integrations #:nodoc:
5
+ module Gestpay
6
+ mattr_accessor :service_url
7
+ self.service_url = 'https://ecomm.sella.it/gestpay/pagam.asp'
8
+
9
+ def self.notification(post, options = {})
10
+ Notification.new(post)
11
+ end
12
+
13
+ def self.return(query_string, options = {})
14
+ Return.new(query_string)
15
+ end
16
+
17
+ module Common
18
+ GestpayEncryptionResponseError = Class.new(StandardError)
19
+
20
+ VERSION = "2.0"
21
+ ENCRYPTION_PATH = "/CryptHTTPS/Encrypt.asp"
22
+ DECRYPTION_PATH = "/CryptHTTPS/Decrypt.asp"
23
+ DELIMITER = '*P1*'
24
+
25
+ CURRENCY_MAPPING = {
26
+ 'EUR' => '242',
27
+ 'ITL' => '18',
28
+ 'BRL' => '234',
29
+ 'USD' => '1',
30
+ 'JPY' => '71',
31
+ 'HKD' => '103'
32
+ }
33
+
34
+
35
+
36
+ def parse_response(response)
37
+ case response
38
+ when /#cryptstring#(.*)#\/cryptstring#/, /#decryptstring#(.*)#\/decryptstring#/
39
+ $1
40
+ when /#error#(.*)#\/error#/
41
+ raise GestpayEncryptionResponseError, "An error occurred retrieving the encrypted string from GestPay: #{$1}"
42
+ else
43
+ raise GestpayEncryptionResponseError, "No response was received by GestPay"
44
+ end
45
+ end
46
+
47
+ def ssl_get(url, path)
48
+ uri = URI.parse(url)
49
+ site = Net::HTTP.new(uri.host, uri.port)
50
+ site.use_ssl = true
51
+ site.verify_mode = OpenSSL::SSL::VERIFY_NONE
52
+ site.get(path).body
53
+ rescue Timeout::Error, Errno::ECONNRESET, Errno::ETIMEDOUT
54
+ raise ActionViewHelperError, "Error occured while contacting payment gateway. Please try again."
55
+ end
56
+ end
57
+
58
+ class Helper < OffsitePayments::Helper
59
+ include Common
60
+ # Valid language codes
61
+ # Italian => 1
62
+ # English => 2
63
+ # Spanish => 3
64
+ # French => 4
65
+ # Tedesco => 5
66
+ def initialize(order, account, options = {})
67
+ super
68
+ add_field('PAY1_IDLANGUAGE', 2)
69
+ end
70
+
71
+ mapping :account, 'ShopLogin'
72
+
73
+ mapping :amount, 'PAY1_AMOUNT'
74
+ mapping :currency, 'PAY1_UICCODE'
75
+
76
+ mapping :order, 'PAY1_SHOPTRANSACTIONID'
77
+
78
+ # Buyer name PAY1_CHNAME
79
+ mapping :customer, :email => 'PAY1_CHEMAIL'
80
+
81
+ mapping :credit_card, :number => 'PAY1_CARDNUMBER',
82
+ :expiry_month => 'PAY1_EXPMONTH',
83
+ :expiry_year => 'PAY1_EXPYEAR',
84
+ :verification_value => 'PAY1_CVV'
85
+
86
+ def customer(params = {})
87
+ add_field(mappings[:customer][:email], params[:email])
88
+ add_field('PAY1_CHNAME', "#{params[:first_name]} #{params[:last_name]}")
89
+ end
90
+
91
+ def currency=(currency_code)
92
+ code = CURRENCY_MAPPING[currency_code]
93
+ raise ActionViewHelperError, "Invalid currency code #{currency_code} specified" if code.nil?
94
+
95
+ add_field(mappings[:currency], code)
96
+ end
97
+
98
+ def form_fields
99
+ @encrypted_data ||= get_encrypted_string
100
+
101
+ {
102
+ 'a' => @fields['ShopLogin'],
103
+ 'b' => @encrypted_data
104
+ }
105
+ end
106
+
107
+ def get_encrypted_string
108
+ response = ssl_get(Gestpay.service_url, encryption_query_string)
109
+ parse_response(response)
110
+ rescue GestpayEncryptionResponseError => e
111
+ raise ActionViewHelperError.new(e)
112
+ end
113
+
114
+ def encryption_query_string
115
+ fields = ['PAY1_AMOUNT', 'PAY1_SHOPTRANSACTIONID', 'PAY1_UICCODE']
116
+
117
+ encoded_params = fields.collect{ |field| "#{field}=#{CGI.escape(@fields[field])}" }.join(DELIMITER)
118
+
119
+ "#{ENCRYPTION_PATH}?a=" + CGI.escape(@fields['ShopLogin']) + "&b=" + encoded_params + "&c=" + CGI.escape(VERSION)
120
+ end
121
+ end
122
+
123
+ class Notification < OffsitePayments::Notification
124
+ include Common
125
+
126
+ def complete?
127
+ status == 'Completed'
128
+ end
129
+
130
+ # The important param
131
+ def item_id
132
+ params['PAY1_SHOPTRANSACTIONID']
133
+ end
134
+
135
+ def transaction_id
136
+ params['PAY1_BANKTRANSACTIONID']
137
+ end
138
+
139
+ # the money amount we received in X.2 decimal.
140
+ def gross
141
+ params['PAY1_AMOUNT']
142
+ end
143
+
144
+ def currency
145
+ # Ruby 1.9 compat
146
+ method = CURRENCY_MAPPING.respond_to?(:key) ? :key : :index
147
+ CURRENCY_MAPPING.send(method, params['PAY1_UICCODE'])
148
+ end
149
+
150
+ def test?
151
+ false
152
+ end
153
+
154
+ def status
155
+ case params['PAY1_TRANSACTIONRESULT']
156
+ when 'OK'
157
+ 'Completed'
158
+ else
159
+ 'Failed'
160
+ end
161
+ end
162
+
163
+ def acknowledge(authcode = nil)
164
+ true
165
+ end
166
+
167
+ private
168
+ # Take the posted data and move the relevant data into a hash
169
+ def parse(query_string)
170
+ @raw = query_string
171
+
172
+ return if query_string.blank?
173
+ encrypted_params = parse_delimited_string(query_string)
174
+
175
+ return if encrypted_params['a'].blank? || encrypted_params['b'].blank?
176
+ @params = decrypt_data(encrypted_params['a'], encrypted_params['b'])
177
+ end
178
+
179
+ def parse_delimited_string(string, delimiter = '&', unencode_cgi = false)
180
+ result = {}
181
+ for line in string.split(delimiter)
182
+ key, value = *line.scan( %r{^(\w+)\=(.*)$} ).flatten
183
+ result[key] = unencode_cgi ? CGI.unescape(value) : value
184
+ end
185
+ result
186
+ end
187
+
188
+ def decrypt_data(shop_login, encrypted_string)
189
+ response = ssl_get(Gestpay.service_url, decryption_query_string(shop_login, encrypted_string))
190
+ encoded_response = parse_response(response)
191
+ parse_delimited_string(encoded_response, DELIMITER, true)
192
+ rescue GestpayEncryptionResponseError => e
193
+ { 'PAY1_TRANSACTIONRESULT' => 'Error' }
194
+ end
195
+
196
+ def decryption_query_string(shop_login, encrypted_string)
197
+ "#{DECRYPTION_PATH}?a=" + CGI.escape(shop_login) + "&b=" + encrypted_string + "&c=" + CGI.escape(VERSION)
198
+ end
199
+ end
200
+
201
+ class Return < OffsitePayments::Return
202
+ end
203
+ end
204
+ end
205
+ end
@@ -0,0 +1,179 @@
1
+ module OffsitePayments #:nodoc:
2
+ module Integrations #:nodoc:
3
+ module HiTrust
4
+ TEST_URL = 'https://testtrustlink.hitrust.com.tw/TrustLink/TrxReqForJava'
5
+ LIVE_URL = 'https://trustlink.hitrust.com.tw/TrustLink/TrxReqForJava'
6
+
7
+ def self.service_url
8
+ OffsitePayments.mode == :test ? TEST_URL : LIVE_URL
9
+ end
10
+
11
+ def self.notification(post, options = {})
12
+ Notification.new(post)
13
+ end
14
+
15
+ def self.return(query_string, options = {})
16
+ Return.new(query_string)
17
+ end
18
+
19
+ class Helper < OffsitePayments::Helper
20
+ # Transaction types
21
+ # * Auth
22
+ # * AuthRe
23
+ # * Capture
24
+ # * CaptureRe
25
+ # * Refund
26
+ # * RefundRe
27
+ # * Query
28
+ def initialize(order, account, options = {})
29
+ super
30
+ # Perform an authorization by default
31
+ add_field('Type', 'Auth')
32
+
33
+ # Capture the payment right away
34
+ add_field('depositflag', '1')
35
+
36
+ # Disable auto query - who knows what it does?
37
+ add_field('queryflag', '1')
38
+
39
+ add_field('orderdesc', 'Store purchase')
40
+ end
41
+
42
+ mapping :account, 'storeid'
43
+ mapping :amount, 'amount'
44
+
45
+ def amount=(money)
46
+ cents = money.respond_to?(:cents) ? money.cents : money
47
+ raise ArgumentError, "amount must be a Money object or an integer" if money.is_a?(String)
48
+ raise ActionViewHelperError, "amount must be greater than $0.00" if cents.to_i <= 0
49
+
50
+ add_field(mappings[:amount], cents)
51
+ end
52
+ # Supported currencies include:
53
+ # * CNY:Chinese Yuan (Renminbi)
54
+ # * TWD:New Taiwan Dollar
55
+ # * HKD:Hong Kong Dollar
56
+ # * USD:US Dollar
57
+ # * AUD:Austrian Dollar
58
+ mapping :currency, 'currency'
59
+
60
+ mapping :order, 'ordernumber'
61
+ mapping :description, 'orderdesc'
62
+
63
+ mapping :notify_url, 'merUpdateURL'
64
+ mapping :return_url, 'returnURL'
65
+ end
66
+
67
+ class Notification < OffsitePayments::Notification
68
+ SUCCESS = '00'
69
+
70
+ self.production_ips = [ '203.75.242.8' ]
71
+
72
+ def complete?
73
+ status == 'Completed'
74
+ end
75
+
76
+ def transaction_id
77
+ params['authRRN']
78
+ end
79
+
80
+ def item_id
81
+ params['ordernumber']
82
+ end
83
+
84
+ def received_at
85
+ Time.parse(params['orderdate']) rescue nil
86
+ end
87
+
88
+ def currency
89
+ params['currency']
90
+ end
91
+
92
+ def gross
93
+ sprintf("%.2f", gross_cents.to_f / 100)
94
+ end
95
+
96
+ def gross_cents
97
+ params['approveamount'].to_i
98
+ end
99
+
100
+ def account
101
+ params['storeid']
102
+ end
103
+
104
+ def status
105
+ params['retcode'] == SUCCESS ? 'Completed' : 'Failed'
106
+ end
107
+
108
+ def test?
109
+ OffsitePayments.mode == :test
110
+ end
111
+
112
+ def acknowledge
113
+ true
114
+ end
115
+ end
116
+
117
+ class Return < OffsitePayments::Return
118
+ SUCCESS = "00"
119
+ CODES = { "00" => "Operation completed successfully",
120
+ "-1" => "Unable to initialize winsock dll.",
121
+ "-2" => "Can't create stream socket.",
122
+ "-3" => "No Request Message.",
123
+ "-4" => "Can't connect to server.",
124
+ "-5" => "Send socket error.",
125
+ "-6" => "Couldn't receive data.",
126
+ "-7" => "Receive Broken message.",
127
+ "-8" => "Unable to initialize Envirnment.",
128
+ "-9" => "Can't Read Server RSA File.",
129
+ "-10" => "Can't Read Client RSA File.",
130
+ "-11" => "Web Server error.",
131
+ "-12" => "Receive Message type error.",
132
+ "-13" => "No Request Message.",
133
+ "-14" => "No Response Content.",
134
+ "-18" => "Merchant Update URL not found.",
135
+ "-19" => "Server URL not find Domain or IP.",
136
+ "-20" => "Server URL only can fill http or https.",
137
+ "-21" => "Server Config File open error.",
138
+ "-22" => "Server RSA Key File open error.",
139
+ "-23" => "Server RSA Key File read error.",
140
+ "-24" => "Server Config File have some errors, Please to check it.",
141
+ "-25" => "Merchant Config File open error.",
142
+ "-26" => "Merchant RSA Key File open error.",
143
+ "-27" => "Merchant RSA Key File read error.",
144
+ "-28" => "Merchant Config File has some errors, Please to check it.",
145
+ "-29" => "Server Type is unknown.",
146
+ "-30" => "Comm Type is unknown.",
147
+ "-31" => "Input Parameter [ORDERNO] is null or empty.",
148
+ "-32" => "Input Parameter [STOREID] is null or empty.",
149
+ "-33" => "Input Parameter [ORDERDESC] is null or empty.",
150
+ "-34" => "Input Parameter [CURRENCY] is null or empty.",
151
+ "-35" => "Input Parameter [AMOUNT] is null or empty.",
152
+ "-36" => "Input Parameter [ORDERURL] is null or empty.",
153
+ "-37" => "Input Parameter [RETURNURL] is null or empty.",
154
+ "-38" => "Input Parameter [DEPOSIT] is null or empty.",
155
+ "-39" => "Input Parameter [QUERYFLAG] is null or empty.",
156
+ "-40" => "Input Parameter [UPDATEURL] is null or empty.",
157
+ "-41" => "Input Parameter [MERUPDATEURL] is null or empty.",
158
+ "-42" => "Input Parameter [KEY] is null or empty.",
159
+ "-43" => "Input Parameter [MAC] is null or empty.",
160
+ "-44" => "Input Parameter [CIPHER] is null or empty.",
161
+ "-45" => "Input Parameter [TrxType] is wrong.",
162
+ "-100" => "TrustLink Server is closed. Or Merchant Server IP is not consistent with TrustLink Server setting.",
163
+ "-101" => "TrustLink Server receives NULL.",
164
+ "-308" => "Order Number already exists.",
165
+ "positive" => "Response from Bank. Please contact with Acquirer Bank Service or HiTRUST Call Center."
166
+ }
167
+
168
+ def success?
169
+ params['retcode'] == SUCCESS
170
+ end
171
+
172
+ def message
173
+ return CODES["positive"] if params['retcode'].to_i > 0
174
+ CODES[ params['retcode'] ]
175
+ end
176
+ end
177
+ end
178
+ end
179
+ end