activemerchant 1.42.5 → 1.42.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/CHANGELOG +23 -0
  5. data/CONTRIBUTORS +12 -0
  6. data/README.md +4 -1
  7. data/lib/active_merchant.rb +5 -1
  8. data/lib/active_merchant/billing/gateways/authorize_net.rb +1 -11
  9. data/lib/active_merchant/billing/gateways/balanced.rb +23 -6
  10. data/lib/active_merchant/billing/gateways/cecabank.rb +225 -0
  11. data/lib/active_merchant/billing/gateways/conekta.rb +4 -3
  12. data/lib/active_merchant/billing/gateways/litle.rb +50 -44
  13. data/lib/active_merchant/billing/gateways/maxipago.rb +190 -0
  14. data/lib/active_merchant/billing/gateways/ogone.rb +2 -1
  15. data/lib/active_merchant/billing/gateways/openpay.rb +200 -0
  16. data/lib/active_merchant/billing/gateways/orbital.rb +24 -3
  17. data/lib/active_merchant/billing/gateways/orbital/cvv_result.rb +34 -0
  18. data/lib/active_merchant/billing/gateways/paymill.rb +2 -2
  19. data/lib/active_merchant/billing/gateways/sage_pay.rb +6 -1
  20. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +2 -1
  21. data/lib/active_merchant/billing/gateways/wirecard.rb +5 -1
  22. data/lib/active_merchant/billing/integrations/alipay.rb +18 -0
  23. data/lib/active_merchant/billing/integrations/alipay/helper.rb +34 -0
  24. data/lib/active_merchant/billing/integrations/alipay/notification.rb +101 -0
  25. data/lib/active_merchant/billing/integrations/paydollar.rb +59 -0
  26. data/lib/active_merchant/billing/integrations/paydollar/helper.rb +41 -0
  27. data/lib/active_merchant/billing/integrations/paydollar/notification.rb +60 -0
  28. data/lib/active_merchant/billing/integrations/paydollar/return.rb +15 -0
  29. data/lib/active_merchant/version.rb +1 -1
  30. metadata +13 -2
  31. metadata.gz.sig +0 -0
@@ -1,5 +1,6 @@
1
1
  require File.dirname(__FILE__) + '/orbital/orbital_soft_descriptors'
2
2
  require File.dirname(__FILE__) + '/orbital/avs_result'
3
+ require File.dirname(__FILE__) + '/orbital/cvv_result'
3
4
  require "rexml/document"
4
5
 
5
6
  module ActiveMerchant #:nodoc:
@@ -40,7 +41,27 @@ module ActiveMerchant #:nodoc:
40
41
  "Interface-Version" => "Ruby|ActiveMerchant|Proprietary Gateway"
41
42
  }
42
43
 
43
- SUCCESS, APPROVED = '0', '00'
44
+ SUCCESS = '0'
45
+
46
+ APPROVED = [
47
+ '00', # Approved
48
+ '08', # Approved authorization, honor with ID
49
+ '11', # Approved authorization, VIP approval
50
+ '24', # Validated
51
+ '26', # Pre-noted
52
+ '27', # No reason to decline
53
+ '28', # Received and stored
54
+ '29', # Provided authorization
55
+ '31', # Request received
56
+ '32', # BIN alert
57
+ '34', # Approved for partial
58
+ '91', # Approved low fraud
59
+ '92', # Approved medium fraud
60
+ '93', # Approved high fraud
61
+ '94', # Approved fraud service unavailable
62
+ 'E7', # Stored
63
+ 'PA' # Partial approval
64
+ ]
44
65
 
45
66
  class_attribute :secondary_test_url, :secondary_live_url
46
67
 
@@ -439,7 +460,7 @@ module ActiveMerchant #:nodoc:
439
460
  :authorization => authorization_string(response[:tx_ref_num], response[:order_id]),
440
461
  :test => self.test?,
441
462
  :avs_result => OrbitalGateway::AVSResult.new(response[:avs_resp_code]),
442
- :cvv_result => response[:cvv2_resp_code]
463
+ :cvv_result => OrbitalGateway::CVVResult.new(response[:cvv2_resp_code])
443
464
  }
444
465
  )
445
466
  end
@@ -459,7 +480,7 @@ module ActiveMerchant #:nodoc:
459
480
  response[:profile_proc_status] == SUCCESS
460
481
  else
461
482
  response[:proc_status] == SUCCESS &&
462
- response[:resp_code] == APPROVED
483
+ APPROVED.include?(response[:resp_code])
463
484
  end
464
485
  end
465
486
 
@@ -0,0 +1,34 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class OrbitalGateway < Gateway
4
+ # Unfortunately, Orbital uses their own special codes for CVV responses
5
+ # that are different than the standard codes defined in
6
+ # <tt>ActiveMerchant::Billing::CVVResult</tt>.
7
+ #
8
+ # This class encapsulates the response codes shown on page 255 of their spec:
9
+ # http://download.chasepaymentech.com/docs/orbital/orbital_gateway_xml_specification.pdf
10
+ #
11
+ class CVVResult < ActiveMerchant::Billing::CVVResult
12
+ MESSAGES = {
13
+ 'M' => 'Match',
14
+ 'N' => 'No match',
15
+ 'P' => 'Not processed',
16
+ 'S' => 'Should have been present',
17
+ 'U' => 'Unsupported by issuer/Issuer unable to process request',
18
+ 'I' => 'Invalid',
19
+ 'Y' => 'Invalid',
20
+ '' => 'Not applicable'
21
+ }
22
+
23
+ def self.messages
24
+ MESSAGES
25
+ end
26
+
27
+ def initialize(code)
28
+ @code = code.blank? ? '' : code.upcase
29
+ @message = MESSAGES[@code]
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -2,8 +2,8 @@ module ActiveMerchant #:nodoc:
2
2
  module Billing #:nodoc:
3
3
  class PaymillGateway < Gateway
4
4
  self.supported_countries = %w(AD AT BE BG CH CY CZ DE DK EE ES FI FO FR GB
5
- GI GR HU IE IL IS IT LI LT LU LV MT NL NO PL
6
- PT RO SE SI SK TR VA)
5
+ GI GR HR HU IE IL IM IS IT LI LT LU LV MC MT
6
+ NL NO PL PT RO SE SI SK TR VA)
7
7
 
8
8
  self.supported_cardtypes = [:visa, :master]
9
9
  self.homepage_url = 'https://paymill.com'
@@ -191,7 +191,7 @@ module ActiveMerchant #:nodoc:
191
191
 
192
192
  def add_invoice(post, options)
193
193
  add_pair(post, :VendorTxCode, sanitize_order_id(options[:order_id]), :required => true)
194
- add_pair(post, :Description, options[:description] || options[:order_id])
194
+ add_pair(post, :Description, truncate_description(options[:description] || options[:order_id]))
195
195
  end
196
196
 
197
197
  def add_credit_card(post, credit_card)
@@ -213,6 +213,11 @@ module ActiveMerchant #:nodoc:
213
213
  order_id.to_s.gsub(/[^-a-zA-Z0-9._]/, '')
214
214
  end
215
215
 
216
+ def truncate_description(description)
217
+ return nil unless description
218
+ description[0, 100]
219
+ end
220
+
216
221
  def map_card_type(credit_card)
217
222
  raise ArgumentError, "The credit card type must be provided" if card_brand(credit_card).blank?
218
223
 
@@ -124,7 +124,8 @@ module ActiveMerchant #:nodoc:
124
124
  :merchant_receipt => [:boolean, 'MerchReceipt'],
125
125
  :merchant_email => [:boolean, 'MerchReceiptEmail'],
126
126
  :merchant_template => [:boolean, 'MerchReceiptName'],
127
- :verification_value => [:boolean, 'isRecurring'],
127
+ :recurring => [:boolean, 'isRecurring'],
128
+ :verification_value => [:string, 'CardCode'],
128
129
  :software => [:string, 'Software']
129
130
  } #:nodoc:
130
131
 
@@ -71,6 +71,10 @@ module ActiveMerchant #:nodoc:
71
71
 
72
72
 
73
73
  private
74
+ def clean_description(description)
75
+ description.to_s.slice(0,32).encode("US-ASCII", invalid: :replace, undef: :replace, replace: '?')
76
+ end
77
+
74
78
  def prepare_options_hash(options)
75
79
  result = @options.merge(options)
76
80
  setup_address_hash!(result)
@@ -139,7 +143,7 @@ module ActiveMerchant #:nodoc:
139
143
  options[:order_id] ||= generate_unique_id
140
144
 
141
145
  xml.tag! "FNC_CC_#{options[:action].to_s.upcase}" do
142
- xml.tag! 'FunctionID', options[:description].to_s.slice(0,32)
146
+ xml.tag! 'FunctionID', clean_description(options[:description])
143
147
  xml.tag! 'CC_TRANSACTION' do
144
148
  xml.tag! 'TransactionID', options[:order_id]
145
149
  case options[:action]
@@ -0,0 +1,18 @@
1
+ require File.dirname(__FILE__) + '/alipay/helper.rb'
2
+ require File.dirname(__FILE__) + '/alipay/notification.rb'
3
+
4
+ module ActiveMerchant #:nodoc:
5
+ module Billing #:nodoc:
6
+ module Integrations #:nodoc:
7
+ module Alipay
8
+
9
+ mattr_accessor :service_url
10
+ self.service_url = 'https://www.example.com'
11
+
12
+ def self.notification(post)
13
+ Notification.new(post)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,34 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ module Integrations #:nodoc:
4
+ module Alipay
5
+ class Helper < ActiveMerchant::Billing::Integrations::Helper
6
+ # Replace with the real mapping
7
+ mapping :account, ''
8
+ mapping :amount, ''
9
+
10
+ mapping :order, ''
11
+
12
+ mapping :customer, :first_name => '',
13
+ :last_name => '',
14
+ :email => '',
15
+ :phone => ''
16
+
17
+ mapping :billing_address, :city => '',
18
+ :address1 => '',
19
+ :address2 => '',
20
+ :state => '',
21
+ :zip => '',
22
+ :country => ''
23
+
24
+ mapping :notify_url, ''
25
+ mapping :return_url, ''
26
+ mapping :cancel_return_url, ''
27
+ mapping :description, ''
28
+ mapping :tax, ''
29
+ mapping :shipping, ''
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,101 @@
1
+ require 'net/http'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ module Integrations #:nodoc:
6
+ module Alipay
7
+ class Notification < ActiveMerchant::Billing::Integrations::Notification
8
+ def complete?
9
+ params['']
10
+ end
11
+
12
+ def item_id
13
+ params['']
14
+ end
15
+
16
+ def transaction_id
17
+ params['']
18
+ end
19
+
20
+ # When was this payment received by the client.
21
+ def received_at
22
+ params['']
23
+ end
24
+
25
+ def payer_email
26
+ params['']
27
+ end
28
+
29
+ def receiver_email
30
+ params['']
31
+ end
32
+
33
+ def security_key
34
+ params['']
35
+ end
36
+
37
+ # the money amount we received in X.2 decimal.
38
+ def gross
39
+ params['']
40
+ end
41
+
42
+ # Was this a test transaction?
43
+ def test?
44
+ params[''] == 'test'
45
+ end
46
+
47
+ def status
48
+ params['']
49
+ end
50
+
51
+ # Acknowledge the transaction to Alipay. This method has to be called after a new
52
+ # apc arrives. Alipay will verify that all the information we received are correct and will return a
53
+ # ok or a fail.
54
+ #
55
+ # Example:
56
+ #
57
+ # def ipn
58
+ # notify = AlipayNotification.new(request.raw_post)
59
+ #
60
+ # if notify.acknowledge
61
+ # ... process order ... if notify.complete?
62
+ # else
63
+ # ... log possible hacking attempt ...
64
+ # end
65
+ def acknowledge(authcode = nil)
66
+ payload = raw
67
+
68
+ uri = URI.parse(Alipay.notification_confirmation_url)
69
+
70
+ request = Net::HTTP::Post.new(uri.path)
71
+
72
+ request['Content-Length'] = "#{payload.size}"
73
+ request['User-Agent'] = "Active Merchant -- http://home.leetsoft.com/am"
74
+ request['Content-Type'] = "application/x-www-form-urlencoded"
75
+
76
+ http = Net::HTTP.new(uri.host, uri.port)
77
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE unless @ssl_strict
78
+ http.use_ssl = true
79
+
80
+ response = http.request(request, payload)
81
+
82
+ # Replace with the appropriate codes
83
+ raise StandardError.new("Faulty Alipay result: #{response.body}") unless ["AUTHORISED", "DECLINED"].include?(response.body)
84
+ response.body == "AUTHORISED"
85
+ end
86
+
87
+ private
88
+
89
+ # Take the posted data and move the relevant data into a hash
90
+ def parse(post)
91
+ @raw = post.to_s
92
+ for line in @raw.split('&')
93
+ key, value = *line.scan( %r{^([A-Za-z0-9_.-]+)\=(.*)$} ).flatten
94
+ params[key] = CGI.unescape(value.to_s) if key.present?
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,59 @@
1
+ require File.dirname(__FILE__) + '/paydollar/helper.rb'
2
+ require File.dirname(__FILE__) + '/paydollar/notification.rb'
3
+ require File.dirname(__FILE__) + '/paydollar/return.rb'
4
+
5
+ module ActiveMerchant #:nodoc:
6
+ module Billing #:nodoc:
7
+ module Integrations #:nodoc:
8
+ module Paydollar
9
+
10
+ CURRENCY_MAP = {
11
+ 'AED' => '784',
12
+ 'AUD' => '036',
13
+ 'BND' => '096',
14
+ 'CAD' => '124',
15
+ 'CNY' => '156',
16
+ 'EUR' => '978',
17
+ 'GBP' => '826',
18
+ 'HKD' => '344',
19
+ 'IDR' => '360',
20
+ 'JPY' => '392',
21
+ 'KRW' => '410',
22
+ 'MOP' => '446',
23
+ 'MYR' => '458',
24
+ 'NZD' => '554',
25
+ 'PHP' => '608',
26
+ 'SAR' => '682',
27
+ 'SGD' => '702',
28
+ 'THB' => '764',
29
+ 'TWD' => '901',
30
+ 'USD' => '840',
31
+ }
32
+
33
+ def self.service_url
34
+ case ActiveMerchant::Billing::Base.integration_mode
35
+ when :production
36
+ 'https://www.paydollar.com/b2c2/eng/payment/payForm.jsp'
37
+ when :test
38
+ 'https://test.paydollar.com/b2cDemo/eng/payment/payForm.jsp'
39
+ else
40
+ raise StandardError, "Integration mode set to an invalid value: #{mode}"
41
+ end
42
+ end
43
+
44
+ def self.notification(post, options = {})
45
+ Notification.new(post, options)
46
+ end
47
+
48
+ def self.return(query_string, options = {})
49
+ Return.new(query_string, options)
50
+ end
51
+
52
+ def self.sign(fields, secret)
53
+ Digest::SHA1.hexdigest(fields.push(secret).join('|'))
54
+ end
55
+
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,41 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ module Integrations #:nodoc:
4
+ module Paydollar
5
+ class Helper < ActiveMerchant::Billing::Integrations::Helper
6
+
7
+ def initialize(order, account, options = {})
8
+ super
9
+ add_field('payType', 'N') # normal sale and not just auth
10
+ @secret = options[:credential2]
11
+ end
12
+
13
+ def form_fields
14
+ @fields.merge('secureHash' => generate_secure_hash)
15
+ end
16
+
17
+ def generate_secure_hash
18
+ fields = [@fields[mappings[:account]],
19
+ @fields[mappings[:order]],
20
+ @fields[mappings[:currency]],
21
+ @fields[mappings[:amount]],
22
+ @fields['payType']]
23
+ Paydollar.sign(fields, @secret)
24
+ end
25
+
26
+ def currency=(currency_code)
27
+ add_field(mappings[:currency], CURRENCY_MAP[currency_code])
28
+ end
29
+
30
+ mapping :account, 'merchantId'
31
+ mapping :amount, 'amount'
32
+ mapping :order, 'orderRef'
33
+ mapping :currency, 'currCode'
34
+ mapping :return_url, 'successUrl'
35
+ mapping :cancel_return_url, ['cancelUrl','failUrl']
36
+
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,60 @@
1
+ require 'net/http'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ module Integrations #:nodoc:
6
+ module Paydollar
7
+
8
+ class Notification < ActiveMerchant::Billing::Integrations::Notification
9
+
10
+ def complete?
11
+ status == 'Completed'
12
+ end
13
+
14
+ def item_id
15
+ @params['Ref']
16
+ end
17
+
18
+ def currency
19
+ CURRENCY_MAP.key(@params['Cur'])
20
+ end
21
+
22
+ def gross
23
+ @params['Amt']
24
+ end
25
+
26
+ def transaction_id
27
+ @params['PayRef']
28
+ end
29
+
30
+ def status
31
+ case @params['successcode']
32
+ when '0' then 'Completed'
33
+ else 'Failed'
34
+ end
35
+ end
36
+
37
+ def acknowledge(authcode = nil)
38
+ # paydollar supports multiple signature keys, therefore we need to check if any
39
+ # of their signatures matches ours
40
+ @params['secureHash'].split(',').include? generate_secure_hash
41
+ end
42
+
43
+ private
44
+ def generate_secure_hash
45
+ fields = [@params['src'],
46
+ @params['prc'],
47
+ @params['successcode'],
48
+ @params['Ref'],
49
+ @params['PayRef'],
50
+ @params['Cur'],
51
+ @params['Amt'],
52
+ @params['payerAuth']]
53
+ Paydollar.sign(fields, @options[:credential2])
54
+ end
55
+
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end