activemerchant 1.32.0 → 1.33.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 (52) hide show
  1. data/CHANGELOG +50 -0
  2. data/CONTRIBUTORS +8 -0
  3. data/README.md +6 -4
  4. data/lib/active_merchant/billing/check.rb +4 -3
  5. data/lib/active_merchant/billing/credit_card.rb +7 -3
  6. data/lib/active_merchant/billing/gateways/authorize_net.rb +27 -7
  7. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +8 -1
  8. data/lib/active_merchant/billing/gateways/blue_pay.rb +201 -185
  9. data/lib/active_merchant/billing/gateways/bogus.rb +1 -1
  10. data/lib/active_merchant/billing/gateways/card_stream_modern.rb +155 -0
  11. data/lib/active_merchant/billing/gateways/cc5.rb +0 -4
  12. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +94 -12
  13. data/lib/active_merchant/billing/gateways/garanti.rb +0 -4
  14. data/lib/active_merchant/billing/gateways/litle.rb +41 -11
  15. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +27 -6
  16. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +2 -2
  17. data/lib/active_merchant/billing/gateways/net_registry.rb +8 -3
  18. data/lib/active_merchant/billing/gateways/netaxept.rb +65 -117
  19. data/lib/active_merchant/billing/gateways/orbital.rb +181 -48
  20. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +12 -10
  21. data/lib/active_merchant/billing/gateways/paymill.rb +27 -13
  22. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +11 -6
  23. data/lib/active_merchant/billing/gateways/paypal_express.rb +25 -7
  24. data/lib/active_merchant/billing/gateways/pin.rb +5 -5
  25. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +16 -11
  26. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +1 -1
  27. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +21 -16
  28. data/lib/active_merchant/billing/gateways/sage.rb +10 -5
  29. data/lib/active_merchant/billing/gateways/sage_pay.rb +1 -0
  30. data/lib/active_merchant/billing/gateways/transnational.rb +239 -0
  31. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +9 -4
  32. data/lib/active_merchant/billing/integrations/direc_pay/status.rb +1 -1
  33. data/lib/active_merchant/billing/integrations/direc_pay.rb +1 -1
  34. data/lib/active_merchant/billing/integrations/dwolla/common.rb +21 -0
  35. data/lib/active_merchant/billing/integrations/dwolla/helper.rb +15 -6
  36. data/lib/active_merchant/billing/integrations/dwolla/notification.rb +11 -6
  37. data/lib/active_merchant/billing/integrations/dwolla/return.rb +12 -4
  38. data/lib/active_merchant/billing/integrations/dwolla.rb +5 -12
  39. data/lib/active_merchant/billing/integrations/notification.rb +13 -8
  40. data/lib/active_merchant/billing/integrations/payflow_link/helper.rb +13 -1
  41. data/lib/active_merchant/billing/integrations/payu_in/helper.rb +74 -0
  42. data/lib/active_merchant/billing/integrations/payu_in/notification.rb +167 -0
  43. data/lib/active_merchant/billing/integrations/payu_in/return.rb +53 -0
  44. data/lib/active_merchant/billing/integrations/payu_in.rb +43 -0
  45. data/lib/active_merchant/billing/integrations/quickpay/notification.rb +68 -5
  46. data/lib/active_merchant/billing/integrations/rbkmoney/helper.rb +23 -0
  47. data/lib/active_merchant/billing/integrations/rbkmoney/notification.rb +91 -0
  48. data/lib/active_merchant/billing/integrations/rbkmoney.rb +17 -0
  49. data/lib/active_merchant/version.rb +1 -1
  50. data.tar.gz.sig +0 -0
  51. metadata +72 -62
  52. metadata.gz.sig +0 -0
@@ -0,0 +1,167 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ module Integrations #:nodoc:
4
+ module PayuIn
5
+ class Notification < ActiveMerchant::Billing::Integrations::Notification
6
+
7
+ def initialize(post, options = {})
8
+ super(post, options)
9
+ @merchant_id = options[:credential1]
10
+ @secret_key = options[:credential2]
11
+ end
12
+
13
+ def complete?
14
+ status == "success"
15
+ end
16
+
17
+ # Status of the transaction. List of possible values:
18
+ # <tt>invalid</tt>:: transaction id is not present
19
+ # <tt>tampered</tt>:: transaction data has been tampered
20
+ # <tt>success</tt>:: transaction successful
21
+ # <tt>pending</tt>:: transaction is pending for some approval
22
+ # <tt>failure</tt>:: transaction failure
23
+ def status
24
+ @status ||= if checksum_ok?
25
+ if transaction_id.blank?
26
+ 'invalid'
27
+ else
28
+ transaction_status.downcase
29
+ end
30
+ else
31
+ 'tampered'
32
+ end
33
+ end
34
+
35
+ def invoice_ok?( order_id )
36
+ order_id.to_s == invoice.to_s
37
+ end
38
+
39
+ # Order amount should be equal to gross - discount
40
+ def amount_ok?( order_amount, order_discount = BigDecimal.new( '0.0' ) )
41
+ BigDecimal.new( gross ) == order_amount && BigDecimal.new( discount ) == order_discount
42
+ end
43
+
44
+ # Status of transaction return from the PayU. List of possible values:
45
+ # <tt>SUCCESS</tt>::
46
+ # <tt>PENDING</tt>::
47
+ # <tt>FAILURE</tt>::
48
+ def transaction_status
49
+ params['status']
50
+ end
51
+
52
+ # ID of this transaction (PayU.in number)
53
+ def transaction_id
54
+ params['mihpayid']
55
+ end
56
+
57
+ # Mode of Payment
58
+ #
59
+ # 'CC' for credit-card
60
+ # 'NB' for net-banking
61
+ # 'CD' for cheque or DD
62
+ # 'CO' for Cash Pickup
63
+ def type
64
+ params['mode']
65
+ end
66
+
67
+ # What currency have we been dealing with
68
+ def currency
69
+ 'INR'
70
+ end
71
+
72
+ def item_id
73
+ params['txnid']
74
+ end
75
+
76
+ # This is the invoice which you passed to PayU.in
77
+ def invoice
78
+ params['txnid']
79
+ end
80
+
81
+ # Merchant Id provided by the PayU.in
82
+ def account
83
+ params['key']
84
+ end
85
+
86
+ # original amount send by merchant
87
+ def gross
88
+ params['amount']
89
+ end
90
+
91
+ # This is discount given to user - based on promotion set by merchants.
92
+ def discount
93
+ params['discount']
94
+ end
95
+
96
+ # Description offer for what PayU given the offer to user - based on promotion set by merchants.
97
+ def offer_description
98
+ params['offer']
99
+ end
100
+
101
+ # Information about the product as send by merchant
102
+ def product_info
103
+ params['productinfo']
104
+ end
105
+
106
+ # Email of the customer
107
+ def customer_email
108
+ params['email']
109
+ end
110
+
111
+ # Phone of the customer
112
+ def customer_phone
113
+ params['phone']
114
+ end
115
+
116
+ # Firstname of the customer
117
+ def customer_first_name
118
+ params['firstname']
119
+ end
120
+
121
+ # Lastname of the customer
122
+ def customer_last_name
123
+ params['lastname']
124
+ end
125
+
126
+ # Full address of the customer
127
+ def customer_address
128
+ { :address1 => params['address1'], :address2 => params['address2'],
129
+ :city => params['city'], :state => params['state'],
130
+ :country => params['country'], :zipcode => params['zipcode'] }
131
+ end
132
+
133
+ def user_defined
134
+ return @user_defined if @user_defined
135
+ @user_defined = []
136
+ 10.times{ |i| @user_defined.push( params[ "udf#{i+1}" ] ) }
137
+ @user_defined
138
+ end
139
+
140
+ def checksum
141
+ params['hash']
142
+ end
143
+
144
+ def message
145
+ @message || params['error']
146
+ end
147
+
148
+ def acknowledge
149
+ checksum_ok?
150
+ end
151
+
152
+ def checksum_ok?
153
+ fields = user_defined.dup.push( customer_email, customer_first_name, product_info, gross, invoice, :reverse => true )
154
+ fields.unshift( transaction_status )
155
+ unless PayuIn.checksum(@merchant_id, @secret_key, *fields ) == checksum
156
+ @message = 'Return checksum not matching the data provided'
157
+ return false
158
+ end
159
+ true
160
+ end
161
+
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end
167
+
@@ -0,0 +1,53 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ module Integrations #:nodoc:
4
+ module PayuIn
5
+ class Return < ActiveMerchant::Billing::Integrations::Return
6
+
7
+ def initialize(query_string, options = {})
8
+ super
9
+ @notification = Notification.new(query_string, options)
10
+ end
11
+
12
+ # PayU Transaction Id
13
+ #
14
+ def transaction_id
15
+ @notification.transaction_id
16
+ end
17
+
18
+ # Returns the status of the transaction as a string
19
+ # The status can be one of the following
20
+ #
21
+ # invalid - transaction id not present
22
+ # tampered - checksum does not mismatch
23
+ # mismatch - order id mismatch
24
+ # success - transaction success
25
+ # pending - transaction pending
26
+ # failure - transaction failure
27
+ #
28
+ # payu does not put the discount field in the checksum
29
+ # it can be easily forged by the attacker without detection
30
+ #
31
+ def status( order_id, order_amount )
32
+ if @notification.invoice_ok?( order_id ) && @notification.amount_ok?( BigDecimal.new(order_amount) )
33
+ @notification.status
34
+ else
35
+ 'mismatch'
36
+ end
37
+ end
38
+
39
+ # check success of the transaction
40
+ # check order_id and
41
+ def success?
42
+ status( @params['txnid'], @params['amount'] ) == 'success'
43
+ end
44
+
45
+ def message
46
+ @notification.message
47
+ end
48
+
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,43 @@
1
+ require 'digest/sha2'
2
+ require 'bigdecimal'
3
+
4
+ module ActiveMerchant #:nodoc:
5
+ module Billing #:nodoc:
6
+ module Integrations #:nodoc:
7
+ module PayuIn
8
+ autoload :Return, 'active_merchant/billing/integrations/payu_in/return.rb'
9
+ autoload :Helper, 'active_merchant/billing/integrations/payu_in/helper.rb'
10
+ autoload :Notification, 'active_merchant/billing/integrations/payu_in/notification.rb'
11
+
12
+ mattr_accessor :test_url
13
+ mattr_accessor :production_url
14
+
15
+ self.test_url = 'https://test.payu.in/_payment.php'
16
+ self.production_url = 'https://secure.payu.in/_payment.php'
17
+
18
+ def self.service_url
19
+ ActiveMerchant::Billing::Base.integration_mode == :production ? self.production_url : self.test_url
20
+ end
21
+
22
+ def self.notification(post, options = {})
23
+ Notification.new(post, options)
24
+ end
25
+
26
+ def self.return(post, options = {})
27
+ Return.new(post, options)
28
+ end
29
+
30
+ def self.checksum(merchant_id, secret_key, *payload_items )
31
+ options = payload_items.pop if Hash === payload_items.last
32
+ options ||= {}
33
+ payload = if options[:reverse] then
34
+ payload_items.dup.push( merchant_id || "" ).unshift( secret_key || "" ).collect{ |x| x.to_s }.join("|")
35
+ else
36
+ payload_items.dup.unshift( merchant_id || "" ).push( secret_key || "" ).collect{ |x| x.to_s }.join("|")
37
+ end
38
+ Digest::SHA512.hexdigest( payload )
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -41,17 +41,54 @@ module ActiveMerchant #:nodoc:
41
41
  end
42
42
 
43
43
  # Provide access to raw fields from quickpay
44
- %w(msgtype ordernumber state chstat chstatmsg qpstat qpstatmsg merchant merchantemail cardtype cardnumber splitpayment fraudprobability fraudremarks fraudreport fee).each do |attr|
44
+ %w(
45
+ msgtype
46
+ ordernumber
47
+ state
48
+ chstat
49
+ chstatmsg
50
+ qpstat
51
+ qpstatmsg
52
+ merchant
53
+ merchantemail
54
+ cardtype
55
+ cardnumber
56
+ cardhash
57
+ cardexpire
58
+ splitpayment
59
+ fraudprobability
60
+ fraudremarks
61
+ fraudreport
62
+ fee
63
+ ).each do |attr|
45
64
  define_method(attr) do
46
65
  params[attr]
47
66
  end
48
67
  end
49
68
 
50
69
  MD5_CHECK_FIELDS = [
51
- :msgtype, :ordernumber, :amount, :currency, :time, :state,
52
- :qpstat, :qpstatmsg, :chstat, :chstatmsg, :merchant, :merchantemail,
53
- :transaction, :cardtype, :cardnumber, :splitpayment, :fraudprobability,
54
- :fraudremarks, :fraudreport, :fee
70
+ :msgtype,
71
+ :ordernumber,
72
+ :amount,
73
+ :currency,
74
+ :time,
75
+ :state,
76
+ :qpstat,
77
+ :qpstatmsg,
78
+ :chstat,
79
+ :chstatmsg,
80
+ :merchant,
81
+ :merchantemail,
82
+ :transaction,
83
+ :cardtype,
84
+ :cardnumber,
85
+ :cardhash,
86
+ :cardexpire,
87
+ :splitpayment,
88
+ :fraudprobability,
89
+ :fraudremarks,
90
+ :fraudreport,
91
+ :fee
55
92
  ]
56
93
 
57
94
  def generate_md5string
@@ -67,6 +104,32 @@ module ActiveMerchant #:nodoc:
67
104
  def acknowledge
68
105
  generate_md5check == params['md5check']
69
106
  end
107
+
108
+ # Take the posted data and move the relevant data into a hash
109
+ def parse(post)
110
+ # 30 + 12
111
+ #------------------------------8a827a0e6829
112
+ #Content-Disposition: form-data; name="msgtype"
113
+ #
114
+ #subscribe
115
+ #------------------------------8a827a0e6829
116
+ #Content-Disposition: form-data; name="ordernumber"
117
+ #
118
+ #BILP94406
119
+
120
+ if post =~ /-{20,40}\w{6,24}/
121
+ @raw = post.to_s
122
+ post.split(/-{20,40}\w{6,24}[\n\r]*/m).each do |part|
123
+ part.scan(/([^\n\r]+)[\n\r]+([^\n\r]*)/m) do |header, value|
124
+ if header.match(/name=["'](.*)["']/)
125
+ params[$1] = value.strip
126
+ end
127
+ end
128
+ end
129
+ else
130
+ super
131
+ end
132
+ end
70
133
  end
71
134
  end
72
135
  end
@@ -0,0 +1,23 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ module Integrations #:nodoc:
4
+ module Rbkmoney
5
+ class Helper < ActiveMerchant::Billing::Integrations::Helper
6
+ mapping :account, 'eshopId'
7
+ mapping :amount, 'recipientAmount'
8
+
9
+ # NOTE: rbkmoney uses outdated currency code 'RUR'
10
+ mapping :currency, 'recipientCurrency'
11
+
12
+ mapping :order, 'orderId'
13
+
14
+ mapping :customer, :email => 'user_email'
15
+
16
+ mapping :credential2, 'serviceName'
17
+ mapping :credential3, 'successUrl'
18
+ mapping :credential4, 'failUrl'
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,91 @@
1
+ require 'net/http'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ module Integrations #:nodoc:
6
+ module Rbkmoney
7
+ class Notification < ActiveMerchant::Billing::Integrations::Notification
8
+ %w(
9
+ eshopId
10
+ paymentId
11
+ orderId
12
+ eshopAccount
13
+ serviceName
14
+ recipientAmount
15
+ recipientCurrency
16
+ paymentStatus
17
+ userName
18
+ userEmail
19
+ paymentData
20
+ secretKey
21
+ hash
22
+ ).each do |param_name|
23
+ define_method(param_name.underscore){ params[param_name] }
24
+ end
25
+
26
+ def complete?
27
+ (payment_status == '5')
28
+ end
29
+
30
+ def test?
31
+ false
32
+ end
33
+
34
+ def status
35
+ case payment_status
36
+ when '3'
37
+ 'pending'
38
+ when '5'
39
+ 'completed'
40
+ else 'unknown'
41
+ end
42
+ end
43
+
44
+ def user_fields
45
+ params.inject({}) do |fields, (k,v)|
46
+ if /\AuserField_[\d+]\z/.match(k)
47
+ fields[k] = v
48
+ end
49
+ fields
50
+ end
51
+ end
52
+
53
+ alias_method :client_id, :eshop_id
54
+ alias_method :item_id, :order_id
55
+ alias_method :transaction_id, :payment_id
56
+ alias_method :received_at, :payment_data
57
+ alias_method :payer_email, :user_email
58
+ alias_method :gross, :recipient_amount
59
+ alias_method :currency, :recipient_currency
60
+
61
+ def acknowledge
62
+ string = [
63
+ eshop_id,
64
+ order_id,
65
+ service_name,
66
+ eshop_account,
67
+ recipient_amount,
68
+ recipient_currency,
69
+ payment_status,
70
+ user_name,
71
+ user_email,
72
+ payment_data,
73
+ @options[:secret]
74
+ ].join '::'
75
+
76
+ signature = case hash.to_s.length
77
+ when 32
78
+ Digest::MD5.hexdigest(string)
79
+ when 128
80
+ Digest::SHA512.hexdigest(string)
81
+ else
82
+ return false
83
+ end
84
+
85
+ signature == hash
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,17 @@
1
+ require File.dirname(__FILE__) + '/rbkmoney/helper.rb'
2
+ require File.dirname(__FILE__) + '/rbkmoney/notification.rb'
3
+
4
+ module ActiveMerchant #:nodoc:
5
+ module Billing #:nodoc:
6
+ module Integrations #:nodoc:
7
+ module Rbkmoney
8
+ mattr_accessor :service_url
9
+ self.service_url = 'https://rbkmoney.ru/acceptpurchase.aspx'
10
+
11
+ def self.notification(*args)
12
+ Notification.new(*args)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -1,3 +1,3 @@
1
1
  module ActiveMerchant
2
- VERSION = "1.32.0"
2
+ VERSION = "1.33.0"
3
3
  end
data.tar.gz.sig CHANGED
Binary file