diff --git a/.travis.yml b/.travis.yml
index 0872ce675..377ed0f38 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,15 +1,39 @@
language: ruby
script: "bundle exec rake test:units"
sudo: false
+cache: bundler
rvm:
-- "2.2"
-- "2.1"
-- "2.0"
-- "1.9"
+- 2.4.0
+- 2.3.3
+- 2.2.3
+- 2.1
gemfile:
- Gemfile.rails32
- Gemfile.rails40
- Gemfile.rails41
- Gemfile.rails42
+- Gemfile.rails50
+- Gemfile.rails51
+
+matrix:
+ exclude:
+ - rvm: 2.1
+ gemfile: Gemfile.rails50
+ - rvm: 2.1
+ gemfile: Gemfile.rails51
+ - rvm: 2.4.0
+ gemfile: Gemfile.rails32
+ - rvm: 2.4.0
+ gemfile: Gemfile.rails40
+ - rvm: 2.4.0
+ gemfile: Gemfile.rails41
+ - rvm: 2.4.0
+ gemfile: Gemfile.rails42
+ include:
+ - rvm: 2.3.3
+ gemfile: Gemfile.shopify
+
+before_install:
+ - gem update bundler
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 33cbcb4ea..1fdfbfb85 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,47 @@
# Offsite Payments CHANGELOG
+### Version 2.6.4 (Jan 8, 2018)
+- Use multiple address fields for WorldPay instead of concatenating them [joshnuss] #270
+
+### Version 2.6.3 (Nov 7, 2017)
+- Fix nil coercion to BigDecimal zero in PayuIn [aman-dureja] #265
+
+### Version 2.6.2 (Oct 30, 2017)
+- Fix ArgumentError in PayuIn with BigDecimal v1.3.2 [aman-dureja] #264
+- Fix molpay and citrus tests [aman-dureja] #264
+
+### Version 2.6.1 (Sep 7, 2017)
+- Fix PayTM checksum generation [christianblais] #262
+
+### Version 2.6.0 (Aug 29, 2017)
+- Rails 5.1 compatibility [eitoball, patientdev] #245
+- Update paydollar URLs [SimonLeungAPHK] #228
+- Fixed compatibility between RubyMoney/money and Shopify/money gems [elfassy] #246
+- Fixed calling Mollie with extra parameters [edwinv] #247
+- Stop hiding JSON parse errors for Bitpay [bdewater] #251
+- Do not send locale parameter to Sagepay [pi3r] #258
+- Updats Skrill URL [sergey-alekseev ] #259
+- Changed PayTM integration [Mohit-Aggarwal1] #260
+
+### Version 2.5.0 (April 12, 2017)
+- corrected zip parameter to from zip to zipcode
+- [Realex] guard against nil when extracting AVS code
+- only use fields that start with `x_` to generate the signature
+- bump active_utils version 3.3.0
+
+### Version 2.4.0 (March 7, 2017)
+- Fixed use of decimal instead of float
+- Fixed use Money gem
+- Fixed sanitize of the phone field for payu_in
+- Added Paytm
+- Updated dependency on nokogiri 1.6
+
+### Version 2.3.0 (February 8, 2016)
+- Release 2.3.0
+
+### Version 2.2.0 (October 14, 2015)
+- Bump active_utils dependency. [lucasuyezu]
+
### Version 2.1.0 (January 16, 2015)
- **Change:** network exceptions now use ActiveUtils instead of ActiveMerchant as namespace,
diff --git a/Gemfile b/Gemfile
index 854e63716..2937fecc3 100644
--- a/Gemfile
+++ b/Gemfile
@@ -2,7 +2,6 @@ source 'https://rubygems.org'
gemspec
gem 'jruby-openssl', :platforms => :jruby
-gem 'money', '~> 5.0'
group :remote_test do
gem 'mechanize'
diff --git a/Gemfile.rails32 b/Gemfile.rails32
index 1d9063613..1b496d649 100644
--- a/Gemfile.rails32
+++ b/Gemfile.rails32
@@ -2,7 +2,6 @@ source 'https://rubygems.org'
gemspec
gem 'jruby-openssl', :platforms => :jruby
-gem 'money', '~> 5.0'
group :remote_test do
gem 'mechanize'
@@ -10,5 +9,4 @@ group :remote_test do
gem 'mongrel', '1.2.0.pre2', :platforms => :ruby
end
-
-gem 'rails', '~> 3.2.0'
+gem 'actionpack', '~> 3.2.0'
diff --git a/Gemfile.rails40 b/Gemfile.rails40
index 4dc6e9402..b68bbb259 100644
--- a/Gemfile.rails40
+++ b/Gemfile.rails40
@@ -2,7 +2,6 @@ source 'https://rubygems.org'
gemspec
gem 'jruby-openssl', :platforms => :jruby
-gem 'money', '~> 5.0'
group :remote_test do
gem 'mechanize'
@@ -10,5 +9,4 @@ group :remote_test do
gem 'mongrel', '1.2.0.pre2', :platforms => :ruby
end
-
-gem 'rails', '~> 4.0.0'
+gem 'actionpack', '~> 4.0.0'
diff --git a/Gemfile.rails41 b/Gemfile.rails41
index f33b2a4b7..a9e82bbf8 100644
--- a/Gemfile.rails41
+++ b/Gemfile.rails41
@@ -2,7 +2,6 @@ source 'https://rubygems.org'
gemspec
gem 'jruby-openssl', :platforms => :jruby
-gem 'money', '~> 5.0'
group :remote_test do
gem 'mechanize'
@@ -10,5 +9,4 @@ group :remote_test do
gem 'mongrel', '1.2.0.pre2', :platforms => :ruby
end
-
-gem 'rails', '~> 4.1.0'
+gem 'actionpack', '~> 4.1.0'
diff --git a/Gemfile.rails42 b/Gemfile.rails42
index 86c335d87..2d18a40a5 100644
--- a/Gemfile.rails42
+++ b/Gemfile.rails42
@@ -2,7 +2,6 @@ source 'https://rubygems.org'
gemspec
gem 'jruby-openssl', :platforms => :jruby
-gem 'money', '~> 5.0'
group :remote_test do
gem 'mechanize'
@@ -10,4 +9,4 @@ group :remote_test do
gem 'mongrel', '1.2.0.pre2', :platforms => :ruby
end
-gem 'rails', '~> 4.2.0'
+gem 'actionpack', '~> 4.2.0'
diff --git a/Gemfile.rails50 b/Gemfile.rails50
new file mode 100644
index 000000000..c77643271
--- /dev/null
+++ b/Gemfile.rails50
@@ -0,0 +1,12 @@
+source 'https://rubygems.org'
+gemspec
+
+gem 'jruby-openssl', :platforms => :jruby
+
+group :remote_test do
+ gem 'mechanize'
+ gem 'launchy'
+ gem 'mongrel', '1.2.0.pre2', :platforms => :ruby
+end
+
+gem 'actionpack', '~> 5.0.0'
diff --git a/Gemfile.rails51 b/Gemfile.rails51
new file mode 100644
index 000000000..ddffe52eb
--- /dev/null
+++ b/Gemfile.rails51
@@ -0,0 +1,12 @@
+source 'https://rubygems.org'
+gemspec
+
+gem 'jruby-openssl', :platforms => :jruby
+
+group :remote_test do
+ gem 'mechanize'
+ gem 'launchy'
+ gem 'mongrel', '1.2.0.pre2', :platforms => :ruby
+end
+
+gem 'actionpack', '~> 5.1.0'
diff --git a/Gemfile.shopify b/Gemfile.shopify
new file mode 100644
index 000000000..363557596
--- /dev/null
+++ b/Gemfile.shopify
@@ -0,0 +1,13 @@
+source 'https://rubygems.org'
+gemspec
+
+gem 'jruby-openssl', :platforms => :jruby
+
+group :remote_test do
+ gem 'mechanize'
+ gem 'launchy'
+ gem 'mongrel', '1.2.0.pre2', :platforms => :ruby
+end
+
+gem 'actionpack', '~> 5.0.0'
+gem 'money', git: 'https://github.com/Shopify/money.git'
diff --git a/README.md b/README.md
index bcdf2cfa5..710390258 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# Offsite Payments
-[![Build Status](https://travis-ci.org/activemerchant/offsite_payments.png?branch=master)](https://travis-ci.org/activemerchant/offsite_payments)
-[![Code Climate](https://codeclimate.com/github/activemerchant/offsite_payments.png)](https://codeclimate.com/github/activemerchant/offsite_payments)
+[![Build Status](https://travis-ci.org/activemerchant/offsite_payments.svg?branch=master)](https://travis-ci.org/activemerchant/offsite_payments)
+[![Code Climate](https://codeclimate.com/github/activemerchant/offsite_payments/badges/gpa.svg)](https://codeclimate.com/github/activemerchant/offsite_payments)
Offsite Payments is an extraction from the ecommerce system [Shopify](http://www.shopify.com). Shopify's requirements for a simple and unified API to handle dozens of different offsite payment pages (often called hosted payment pages) with very different exposed APIs was the chief principle in designing the library.
diff --git a/bin/console b/bin/console
new file mode 100755
index 000000000..3885bfa4a
--- /dev/null
+++ b/bin/console
@@ -0,0 +1,14 @@
+#!/usr/bin/env ruby
+
+require "bundler/setup"
+require "offsite_payments"
+
+# You can add fixtures and/or initialization code here to make experimenting
+# with your gem easier. You can also use a different console, if you like.
+
+# (If you use this, don't forget to add pry to your Gemfile!)
+# require "pry"
+# Pry.start
+
+require "irb"
+IRB.start(__FILE__)
diff --git a/bin/setup b/bin/setup
new file mode 100755
index 000000000..dce67d860
--- /dev/null
+++ b/bin/setup
@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+set -euo pipefail
+IFS=$'\n\t'
+set -vx
+
+bundle install
+
+# Do any other automated setup that you need to do here
diff --git a/generators/templates/notification_test.rb b/generators/templates/notification_test.rb
index 9045d3b8c..150b67072 100644
--- a/generators/templates/notification_test.rb
+++ b/generators/templates/notification_test.rb
@@ -19,7 +19,7 @@ def test_accessors
end
def test_compositions
- assert_equal Money.new(3166, 'USD'), @<%= identifier %>.amount
+ assert_equal Money.from_amount(31.66, 'USD'), @<%= identifier %>.amount
end
# Replace with real successful acknowledgement code
diff --git a/lib/offsite_payments.rb b/lib/offsite_payments.rb
index 7870341f8..25b08702c 100644
--- a/lib/offsite_payments.rb
+++ b/lib/offsite_payments.rb
@@ -2,8 +2,8 @@
require 'cgi'
require "timeout"
require "socket"
-
-require 'active_support/core_ext/class/delegating_attributes'
+require 'bigdecimal'
+require 'bigdecimal/util'
require 'active_utils'
diff --git a/lib/offsite_payments/helper.rb b/lib/offsite_payments/helper.rb
index c339019e9..fe99e189a 100644
--- a/lib/offsite_payments/helper.rb
+++ b/lib/offsite_payments/helper.rb
@@ -16,7 +16,7 @@ def self.inherited(subclass)
end
def initialize(order, account, options = {})
- options.assert_valid_keys([:amount, :currency, :test, :credential2, :credential3, :credential4, :country, :account_name, :description, :transaction_type, :authcode, :notify_url, :return_url, :redirect_param, :forward_url, :checkout_token, :deposit_flag])
+ options.assert_valid_keys([:amount, :currency, :test, :credential2, :credential3, :credential4, :country, :account_name, :description, :transaction_type, :authcode, :notify_url, :return_url, :redirect_param, :forward_url, :checkout_token])
@fields = {}
@raw_html_fields = []
@test = options[:test]
diff --git a/lib/offsite_payments/integrations/bit_pay.rb b/lib/offsite_payments/integrations/bit_pay.rb
index 11f4bcee4..f8a40de77 100644
--- a/lib/offsite_payments/integrations/bit_pay.rb
+++ b/lib/offsite_payments/integrations/bit_pay.rb
@@ -89,7 +89,6 @@ def transaction_id
def item_id
JSON.parse(params['posData'])['orderId']
- rescue JSON::ParserError
end
def status
@@ -132,14 +131,12 @@ def acknowledge(authcode = nil)
retrieved_json = JSON.parse(@raw).tap { |j| j.delete('currentTime') }
posted_json == retrieved_json
- rescue JSON::ParserError
end
private
def parse(body)
@raw = body
@params = JSON.parse(@raw)
- rescue JSON::ParserError
end
end
diff --git a/lib/offsite_payments/integrations/checkout_finland.rb b/lib/offsite_payments/integrations/checkout_finland.rb
new file mode 100644
index 000000000..e0777d511
--- /dev/null
+++ b/lib/offsite_payments/integrations/checkout_finland.rb
@@ -0,0 +1,166 @@
+module OffsitePayments #:nodoc:
+ module Integrations #:nodoc:
+ module CheckoutFinland
+
+ mattr_accessor :service_url
+ self.service_url = 'https://payment.checkout.fi/'
+
+ def self.notification(post)
+ Notification.new(post)
+ end
+
+ class Helper < OffsitePayments::Helper
+ include ActiveUtils::PostsData
+ self.country_format = :alpha3
+
+ def initialize(order, account, options = {})
+ md5secret options.delete(:credential2)
+ super
+
+ # Add default fields
+ add_field("VERSION", "0001") # API version
+ add_field("ALGORITHM", "3") # Return MAC version (3 is HMAC-SHA256)
+ add_field("TYPE", "0")
+ add_field("DEVICE", "1") # Offsite payment by default
+ end
+
+ def md5secret(value)
+ @md5secret = value
+ end
+
+ # Add MAC to form fields
+ def form_fields
+ @fields.merge("MAC" => generate_md5string)
+ end
+
+ # Apply parameter length limitations recommended by Checkout.fi
+ def add_field(name, value)
+ return if name.blank? || value.blank?
+ @fields[name.to_s] = check_param_length(name_to_s, value.to_s)
+ end
+
+ # API parameter length limitations specified by Checkout.fi
+ # Parameters longer than this cause the HTTP POST to fail
+ def check_param_length(name, value)
+ # Soft limitations, fields that can be clipped
+ max_length_substring = { "FIRSTNAME" => 40, "FAMILYNAME" => 40, "ADDRESS" => 40, "POSTCODE" => 14, "POSTOFFICE" => 18, "MESSAGE" => 1000, "EMAIL" => 200, "PHONE" => 30 }
+ # Hard limitations, fields that cannot be clipped
+ max_length_exception = { "RETURN" => 300, "CANCEL" => 300, "REJECT" => 300, "DELAYED" => 300, "STAMP" => 20, "AMOUNT" => 8, "REFERENCE" => 20, "CONTENT" => 2, "LANGUAGE" => 2, "MERCHANT" => 20, "COUNTRY" => 3, "CURRENCY" => 3, "DELIVERY_DATE" => 8 }
+ if max_length_substring.include? name
+ return value.to_s[0, max_length_substring[name]]
+ end
+ if max_length_exception.include? name
+ if value.to_s.length > max_length_exception[name]
+ raise ArgumentError, "Field #{name} length #{value.length} is longer than permitted by provider API. Maximum length #{max_length_exception[name]}."
+ else
+ return value
+ end
+ end
+ value
+ end
+
+ # Calculate MAC
+ def generate_md5string
+ fields = [@fields["VERSION"], @fields["STAMP"], @fields["AMOUNT"], @fields["REFERENCE"],
+ @fields["MESSAGE"], @fields["LANGUAGE"], @fields["MERCHANT"], @fields["RETURN"],
+ @fields["CANCEL"], @fields["REJECT"], @fields["DELAYED"], @fields["COUNTRY"],
+ @fields["CURRENCY"], @fields["DEVICE"], @fields["CONTENT"], @fields["TYPE"],
+ @fields["ALGORITHM"], @fields["DELIVERY_DATE"], @fields["FIRSTNAME"], @fields["FAMILYNAME"],
+ @fields["ADDRESS"], @fields["POSTCODE"], @fields["POSTOFFICE"], @md5secret]
+ fields = fields.join("+")
+ Digest::MD5.hexdigest(fields).upcase
+ end
+
+ # Mappings
+ mapping :order, 'STAMP' # Unique order number for each payment
+ mapping :account, 'MERCHANT' # Checkout Merchant ID
+ mapping :amount, 'AMOUNT' # Amount in cents
+ mapping :reference, 'REFERENCE' # Reference for bank statement
+ mapping :language, 'LANGUAGE' # "FI" / "SE" / "EN"
+ mapping :currency, 'CURRENCY' # "EUR" currently only
+ mapping :device, 'DEVICE' # "1" = HTML / "10" = XML
+ mapping :content, 'CONTENT' # "1" = NORMAL "2" = ADULT CONTENT
+ mapping :delivery_date, 'DELIVERY_DATE' # "YYYYMMDD"
+ mapping :description, 'MESSAGE' # Description of the order
+
+ # Optional customer data supported by API (not mandatory)
+ mapping :customer, :first_name => 'FIRSTNAME',
+ :last_name => 'FAMILYNAME',
+ :email => 'EMAIL',
+ :phone => 'PHONE'
+
+ # Optional fields supported by API (not mandatory)
+ mapping :billing_address, :city => 'POSTOFFICE',
+ :address1 => 'ADDRESS',
+ :zip => 'POSTCODE',
+ :country => 'COUNTRY'
+
+ mapping :notify_url, 'DELAYED' # Delayed payment URL (mandatory)
+ mapping :reject_url, 'REJECT' # Rejected payment URL (mandatory)
+ mapping :return_url, 'RETURN' # Payment URL (optional)
+ mapping :cancel_return_url, 'CANCEL' # Cancelled payment URL (optional)
+ end
+
+ class Notification < OffsitePayments::Notification
+ # Payment can be market complete with the following status codes
+ def complete?
+ ["2", "5", "6", "8", "9", "10"].include? params["STATUS"]
+ end
+
+ # Did the customer choose delayed payment method
+ def delayed?
+ params['STATUS'] == "3"
+ end
+
+ # Did the customer cancel the payment
+ def cancelled?
+ params['STATUS'] == "-1"
+ end
+
+ # Payment requires manual activation (fraud check etc)
+ def activation?
+ params['STATUS'] == "7"
+ end
+
+ # Reference specified by the client when sending payment
+ def reference
+ params['REFERENCE']
+ end
+
+ # Unique ID assigned by Checkout
+ def transaction_id
+ params['PAYMENT']
+ end
+
+ # Unique ID assigned by customer
+ def stamp
+ params['STAMP']
+ end
+
+ # Returned Message Authentication Code
+ def mac
+ params['MAC']
+ end
+
+ def status
+ params['STATUS']
+ end
+
+ # Verify authenticity of returned data
+ def acknowledge(authcode = nil)
+ return_authcode = [params["VERSION"], params["STAMP"], params["REFERENCE"], params["PAYMENT"], params["STATUS"], params["ALGORITHM"]].join("&")
+ OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), authcode, return_authcode).upcase == params["MAC"]
+ end
+
+ private
+
+ # Take the posted data and move the data into params
+ def parse(post)
+ post.each do |key, value|
+ params[key] = value
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/offsite_payments/integrations/citrus.rb b/lib/offsite_payments/integrations/citrus.rb
index 610428405..302472160 100644
--- a/lib/offsite_payments/integrations/citrus.rb
+++ b/lib/offsite_payments/integrations/citrus.rb
@@ -96,8 +96,8 @@ def invoice_ok?( order_id )
order_id.to_s == invoice.to_s
end
- def amount_ok?( order_amount )
- BigDecimal.new( amount ) == order_amount
+ def amount_ok?(order_amount)
+ amount == Money.from_amount(order_amount, currency)
end
def item_id
@@ -120,7 +120,7 @@ def gross
end
def amount
- gross
+ Money.from_amount(BigDecimal.new(gross), currency)
end
def transaction_id
@@ -182,7 +182,7 @@ def acknowledge(authcode = nil)
end
def checksum_ok?
- fields = [invoice, transaction_status, amount.to_s, transaction_id, issuerrefno, authidcode, customer_first_name, customer_last_name, pgrespcode, customer_address[:zip]].join
+ fields = [invoice, transaction_status, sprintf('%.2f', amount), transaction_id, issuerrefno, authidcode, customer_first_name, customer_last_name, pgrespcode, customer_address[:zip]].join
unless Citrus.checksum(@secret_key, fields ) == checksum
@message = 'checksum mismatch...'
diff --git a/lib/offsite_payments/integrations/coinbase.rb b/lib/offsite_payments/integrations/coinbase.rb
index f1f3f3bdc..5f4ef14a2 100755
--- a/lib/offsite_payments/integrations/coinbase.rb
+++ b/lib/offsite_payments/integrations/coinbase.rb
@@ -105,7 +105,6 @@ def status
# apc arrives. Coinbase will verify that all the information we received are correct
# and will return a ok or a fail.
def acknowledge(authcode = {})
-
uri = URI.parse(Coinbase.notification_confirmation_url % transaction_id)
response = Coinbase.do_request(uri, @options[:credential1], @options[:credential2])
@@ -114,6 +113,7 @@ def acknowledge(authcode = {})
posted_order = @params
parse(response)
+ return false unless @params
%w(id custom total_native status).all? { |param| posted_order[param] == @params[param] }
end
diff --git a/lib/offsite_payments/integrations/diamond_mind.rb b/lib/offsite_payments/integrations/diamond_mind.rb
new file mode 100644
index 000000000..2a93d7d3d
--- /dev/null
+++ b/lib/offsite_payments/integrations/diamond_mind.rb
@@ -0,0 +1,170 @@
+module OffsitePayments #:nodoc:
+ module Integrations #:nodoc:
+ module DiamondMind
+ mattr_accessor :production_url
+ mattr_accessor :test_url
+ self.production_url = 'https://secure.networkmerchants.com/api/v2/three-step'
+ self.test_url = 'https://secure.networkmerchants.com/api/v2/three-step'
+
+ def self.helper(order, account, options={})
+ Helper.new(order, account, options)
+ end
+
+ def self.notification(query_string, options={})
+ Notification.new(query_string, options)
+ end
+
+ def self.return(query_string, options={})
+ Return.new(query_string, options)
+ end
+
+ def self.service_url
+ mode = OffsitePayments.mode
+ case mode
+ when :production
+ self.production_url
+ when :test
+ self.test_url
+ else
+ raise StandardError, "Integration mode set to an invalid value: #{mode}"
+ end
+ end
+
+ module Common
+ CURRENCY_SPECIAL_MINOR_UNITS = {
+ 'BIF' => 0,
+ 'BYR' => 0,
+ 'CLF' => 0,
+ 'CLP' => 0,
+ 'CVE' => 0,
+ 'DJF' => 0,
+ 'GNF' => 0,
+ 'HUF' => 0,
+ 'ISK' => 0,
+ 'JPY' => 0,
+ 'KMF' => 0,
+ 'KRW' => 0,
+ 'PYG' => 0,
+ 'RWF' => 0,
+ 'UGX' => 0,
+ 'UYI' => 0,
+ 'VND' => 0,
+ 'VUV' => 0,
+ 'XAF' => 0,
+ 'XOF' => 0,
+ 'XPF' => 0,
+ 'BHD' => 3,
+ 'IQD' => 3,
+ 'JOD' => 3,
+ 'KWD' => 3,
+ 'LYD' => 3,
+ 'OMR' => 3,
+ 'TND' => 3,
+ 'COU' => 4
+ }
+
+ def create_signature(fields, secret)
+ data = fields.join('.')
+ digest = Digest::SHA1.hexdigest(data)
+ signed = "#{digest}.#{secret}"
+ Digest::SHA1.hexdigest(signed)
+ end
+
+ def format_amount(amount, currency)
+ if amount.is_a? Float
+ units = CURRENCY_SPECIAL_MINOR_UNITS[currency] || 2
+ multiple = 10**units
+ return (amount.to_f * multiple.to_f).to_i
+ else
+ return amount
+ end
+ end
+
+ # Realex returns currency amount as an integer
+ def format_amount_as_float(amount, currency)
+ units = CURRENCY_SPECIAL_MINOR_UNITS[currency] || 2
+ divisor = 10**units
+ return (amount.to_f / divisor.to_f)
+ end
+
+ def extract_digits(value)
+ value.scan(/\d+/).join('')
+ end
+
+ def extract_avs_code(params={})
+ [extract_digits(params[:zip]), extract_digits(params[:address1])].join('|')
+ end
+ end
+
+ class Helper < OffsitePayments::Helper
+ include Common
+
+ def initialize(order, account, options = {})
+ @timestamp = Time.now.strftime('%Y%m%d%H%M%S')
+ @currency = options[:currency]
+ @merchant_id = account
+ @sub_account = options[:credential2]
+ @secret = options[:credential3]
+ super
+ add_field 'currency', @currency
+ end
+
+ def form_fields
+ {'api-toke' => @merchant_id, 'amount' => :amount}
+ end
+
+ def amount=(amount)
+ add_field 'amount', format_amount(amount, @currency)
+ end
+
+ def billing_address(params={})
+ add_field(mappings[:billing_address][:zip], extract_avs_code(params))
+ add_field(mappings[:billing_address][:country], lookup_country_code(params[:country]))
+ end
+
+ def shipping_address(params={})
+ add_field(mappings[:shipping_address][:zip], extract_avs_code(params))
+ add_field(mappings[:shipping_address][:country], lookup_country_code(params[:country]))
+ end
+
+ mapping :currency, 'currency'
+ mapping :order, 'order-id'
+ mapping :amount, 'amount'
+ mapping :return_url, 'redirect-url,'
+ mapping :customer, :email => 'email'
+ mapping :shipping_address, :zip => 'postal',
+ :country => 'country'
+ mapping :billing_address, :zip => 'postal',
+ :country => 'country'
+ end
+
+ class Notification < OffsitePayments::Notification
+ include Common
+ def initialize(post, options={})
+ super
+ @secret = options[:credential3]
+ end
+ end
+
+ class Return < OffsitePayments::Return
+ def initialize(data, options)
+ super
+ @notification = Notification.new(data, options)
+ end
+
+ def success?
+ notification.complete?
+ end
+
+ # TODO: realex does not provide a separate cancelled endpoint
+ def cancelled?
+ false
+ end
+
+ def message
+ notification.message
+ end
+ end
+ end
+ end
+end
diff --git a/lib/offsite_payments/integrations/easy_pay.rb b/lib/offsite_payments/integrations/easy_pay.rb
index cbd19874e..bf0169225 100644
--- a/lib/offsite_payments/integrations/easy_pay.rb
+++ b/lib/offsite_payments/integrations/easy_pay.rb
@@ -101,7 +101,7 @@ def complete?
end
def amount
- BigDecimal.new(gross)
+ Money.from_amount(BigDecimal.new(gross), currency)
end
def item_id
@@ -131,6 +131,10 @@ def acknowledge(authcode = nil)
def success_response(*args)
{ :nothing => true }
end
+
+ def currency
+ 'BYR'
+ end
end
end
end
diff --git a/lib/offsite_payments/integrations/epay.rb b/lib/offsite_payments/integrations/epay.rb
index 220407a2d..2c0f1a5bd 100644
--- a/lib/offsite_payments/integrations/epay.rb
+++ b/lib/offsite_payments/integrations/epay.rb
@@ -125,7 +125,7 @@ def test?
return false
end
- %w(txnid orderid amount currency date time hash fraud payercountry issuercountry txnfee subscriptionid paymenttype cardno).each do |attr|
+ %w(txnid orderid currency date time hash fraud payercountry issuercountry txnfee subscriptionid paymenttype cardno).each do |attr|
define_method(attr) do
params[attr]
end
@@ -135,10 +135,6 @@ def currency
CURRENCY_CODES.invert[params['currency']].to_s
end
- def amount
- Money.new(params['amount'].to_i, currency)
- end
-
def generate_md5string
md5string = String.new
for line in @raw.split('&')
diff --git a/lib/offsite_payments/integrations/hi_trust.rb b/lib/offsite_payments/integrations/hi_trust.rb
index 71b414d8e..bb64cb204 100644
--- a/lib/offsite_payments/integrations/hi_trust.rb
+++ b/lib/offsite_payments/integrations/hi_trust.rb
@@ -31,7 +31,7 @@ def initialize(order, account, options = {})
add_field('Type', 'Auth')
# Capture the payment right away
- add_field('depositflag', options[:deposit_flag] || '0')
+ add_field('depositflag', '1')
# Disable auto query - who knows what it does?
add_field('queryflag', '1')
diff --git a/lib/offsite_payments/integrations/liqpay.rb b/lib/offsite_payments/integrations/liqpay.rb
index 7a785b76c..e9331fbee 100644
--- a/lib/offsite_payments/integrations/liqpay.rb
+++ b/lib/offsite_payments/integrations/liqpay.rb
@@ -80,7 +80,7 @@ def account
end
def amount
- BigDecimal.new(gross)
+ Money.from_amount(BigDecimal.new(gross), currency)
end
def item_id
diff --git a/lib/offsite_payments/integrations/migs.rb b/lib/offsite_payments/integrations/migs.rb
new file mode 100644
index 000000000..c9b53bd1e
--- /dev/null
+++ b/lib/offsite_payments/integrations/migs.rb
@@ -0,0 +1,292 @@
+require 'openssl'
+require 'base64'
+
+module OffsitePayments
+ module Integrations #:nodoc:
+ module Migs
+
+ # Overwrite this if you want to change the ANS production url
+ mattr_accessor :production_url
+ self.production_url = 'https://migs.mastercard.com.au/vpcpay'
+
+ HASH_ALGORITHM = 'SHA256'.freeze
+
+ def self.service_url
+ mode = OffsitePayments.mode
+ case mode
+ when :production
+ self.production_url
+ # There is no test URL
+ when :test
+ self.production_url
+ else
+ raise StandardError, "Integration mode set to an invalid value: #{mode}"
+ end
+ end
+
+ def self.return(query_string, options = {})
+ Return.new(query_string, options)
+ end
+
+ class Helper < OffsitePayments::Helper
+ ELECTRON = /^(424519|42496[23]|450875|48440[6-8]|4844[1-5][1-5]|4917[3-5][0-9]|491880)\d{10}(\d{3})?$/
+
+ # WARNING
+ #
+ # From reading most of the tests for various integrations,
+ # including the more popular ones (Authorize.net), it seems
+ # that the amount field is provided using dollars, not cents
+ # like the Gateway classes. The currency for transactions is
+ # dictated by the merchant account. Thus, the user will need
+ # to determine the correct amount. It seems that cents are
+ # used for USD and INR at the very least.
+
+ # The MiGS merchant id should be passed as the account parameter.
+ #
+ # Options must include:
+ #
+ # - :locale
+ # - :access_code => Migs access code
+ # - :secret => Migs secure secret
+ # - :amount => price in cents
+ #
+ # Also, the method add_secure_hash should be called at the very end
+ # of the block passed to payment_service_for.
+ def initialize(order, account, options = {})
+ requires!(options, :amount, :locale, :secret, :access_code)
+
+ # The following elements need to be removed from params to not
+ # trigger an error, but can't be added to the object yet since
+ # the @fields Hash has not been set up yet via super()
+ locale = options.delete(:locale)
+ access_code = options.delete(:access_code)
+ # For generating the secure hash
+ secret = options.delete(:secret)
+
+ super
+
+ add_field('vpc_gateway', 'ssl')
+ add_field('vpc_Command', 'pay')
+ add_field('vpc_Version', '1')
+ add_field('vpc_VirtualPaymentClientURL', 'https://migs.mastercard.com.au/vpcpay')
+
+ self.locale = locale
+ self.access_code = access_code
+ @secret = secret
+ end
+
+ # A custom handler for credit cards to extract the card type
+ # since Migs wants that passed with the data
+ def credit_card(params = {})
+ brand = params[:brand].to_sym
+ params.delete(:brand)
+
+ exp_month = sprintf("%.2i", Integer(params[:expiry_month], 10))
+ exp_year = sprintf("%.4i", Integer(params[:expiry_year], 10))
+ params.delete(:expiry_month)
+ params.delete(:expiry_year)
+
+ method_missing(:credit_card, params)
+
+ # The expiration data needs to be combined together
+ exp = "#{exp_year[-2..-1]}#{exp_month}"
+ add_field(mappings[:credit_card][:expiry_month], exp)
+
+ # Map the card type to what Migs is expecting
+ if params[:number] =~ ELECTRON
+ brand_name = 'VisaDebit'
+ else
+ brand_name = {
+ :visa => 'Visa',
+ :master => 'Mastercard',
+ :american_express => 'Amex',
+ :diners_club => 'Dinersclub',
+ :jcb => 'JCB',
+ :solo => 'Solo'
+ }[brand]
+ end
+
+ add_field(mappings[:credit_card][:brand], brand_name)
+ end
+
+ # Make sure the order id and attempt number are combined into
+ # the appropriate fields in the form. The transaction reference
+ # is constructed as:
+ #
+ # order-attempt_number
+ #
+ # The order info is constructed as:
+ #
+ # order-attempt_number/description
+
+ def order=(value)
+ # Both of these fields include the order id
+ {'vpc_MerchTxnRef' => 40, 'vpc_OrderInfo' => 34}.each do |field, max_length|
+ existing_value = @fields[field] || ""
+
+ # Inserts the description as (/description) into any existing variation of "order-attempt/description"
+ new_value = existing_value.gsub(/^(\d+)?(-\d+)?(\/.*)?$/, "#{value}\\2\\3")
+
+ add_field(field, new_value[0...max_length])
+ end
+ end
+
+ def attempt_number(value)
+ # Both of these fields include the atempt_number
+ {'vpc_MerchTxnRef' => 40, 'vpc_OrderInfo' => 34}.each do |field, max_length|
+ existing_value = @fields[field] || ""
+
+ # Inserts the attempt number as (-\d) into any existing variation of "order-attempt/description"
+ new_value = existing_value.gsub(/^(\d+)?(-\d+)?(\/.*)?$/, "\\1-#{value}\\3")
+
+ add_field(field, new_value[0...max_length])
+ end
+ end
+
+ def description(value)
+ field = 'vpc_OrderInfo'
+ max_length = 34
+ existing_value = @fields[field] || ""
+
+ # Inserts the description as (/description) into any existing variation of "order-attempt/description"
+ value = existing_value.gsub(/^(\d+)?(-\d+)?(\/.*)?$/, "\\1\\2/#{value}")
+
+ add_field(field, value[0...max_length])
+ end
+
+ # This must be called at the end after all other fields have been added
+ def add_secure_hash
+ # Per MIGS requirements we must stringify, sort fields alphabetically
+ # minus the 'vpc_' prefix, add back the 'vpc_' prefix after sorting,
+ # then join all fields as a query string separated by '&'.
+ sorted_values = @fields.stringify_keys
+ .map { |(k, v)| [k.gsub('vpc_', ''), v] }
+ .sort
+ .map { |i| "vpc_#{i[0]}=#{i[1]}" }
+ .join('&')
+ hash = OpenSSL::HMAC.hexdigest(HASH_ALGORITHM, [@secret].pack('H*'), sorted_values).upcase
+ add_field('vpc_SecureHash', hash)
+ add_field('vpc_SecureHashType', 'SHA256')
+ end
+
+ mapping :account, 'vpc_Merchant'
+ mapping :access_code, 'vpc_AccessCode'
+ mapping :locale, 'vpc_Locale'
+ mapping :return_url, 'vpc_ReturnURL'
+ mapping :amount, 'vpc_Amount'
+
+ mapping :billing_address, :city => 'vpc_AVS_City',
+ :address1 => 'vpc_AVS_Street_01',
+ :state => 'vpc_AVS_StateProv',
+ :zip => 'vpc_AVS_PostCode',
+ :country => 'vpc_AVS_Country'
+
+ mapping :credit_card, :number => 'vpc_CardNum',
+ :expiry_month => 'vpc_CardExp',
+ :expiry_year => 'vpc_CardExp',
+ :verification_value => 'vpc_CardSecurityCode',
+ :brand => 'vpc_card'
+ end
+
+ class Return < OffsitePayments::Return
+ def initialize(query_string, options = {})
+ super
+ @valid = secure_hash_matches?
+ end
+
+ def message
+ return 'Response from MiGS could not be validated' unless @valid
+ params['vpc_Message']
+ end
+
+ def command
+ params['vpc_Command']
+ end
+
+ def transaction_id
+ params['vpc_TransactionNo']
+ end
+
+ def authorization_code
+ params['vpc_AuthorizeId']
+ end
+
+ def description
+ params['vpc_OrderInfo'].gsub(/^.*\//, '')
+ end
+
+ def order
+ params['vpc_MerchTxnRef'].gsub(/-\d+$/, '')
+ end
+
+ def attempt_number
+ params['vpc_MerchTxnRef'].gsub(/^\d+-/, '')
+ end
+
+ def response_code
+ params['vpc_TxnResponseCode']
+ end
+
+ def merchant
+ params['vpc_Merchant']
+ end
+
+ def receipt_number
+ params['vpc_ReceiptNo']
+ end
+
+ def amount
+ params['vpc_Amount'].to_i
+ end
+
+ def success?
+ return false if not @valid
+ params['vpc_TxnResponseCode'] == '0'
+ end
+
+ def cancelled?
+ params['vpc_TxnResponseCode'] != '0'
+ end
+
+ def secure_hash
+ params['vpc_SecureHash']
+ end
+
+ def avs_code
+ params['vpc_AVSResultCode']
+ end
+
+ def cvv_code
+ params['vpc_CSCResultCode']
+ end
+
+ def secure_hash_matches?
+ return false unless params['vpc_SecureHash']
+ response = params.clone
+ response.delete('vpc_SecureHash')
+ response.delete('vpc_SecureHashType')
+ sorted_values = response.stringify_keys
+ .map { |(k, v)| [k.gsub('vpc_', ''), v] }
+ .sort.map { |i| "vpc_#{i[0]}=#{i[1]}" }
+ .join('&')
+ hash = OpenSSL::HMAC.hexdigest(HASH_ALGORITHM, [@options[:secret]].pack('H*'), sorted_values).upcase
+ hash == secure_hash
+ end
+
+ # Returns true if one of the following is true:
+ #
+ # - address and 9-digit zip matches
+ # - address and 5-digit zip matches
+ # - 5-digit zip matches, address not checked
+ def avs_code_matches?
+ return ['Y', 'X', 'P'].include? avs_code
+ end
+
+ def cvv_code_matches?
+ return ['M'].include? cvv_code
+ end
+ end
+
+ end
+ end
+end
diff --git a/lib/offsite_payments/integrations/mollie.rb b/lib/offsite_payments/integrations/mollie.rb
index 4d1ce4054..75fc36357 100644
--- a/lib/offsite_payments/integrations/mollie.rb
+++ b/lib/offsite_payments/integrations/mollie.rb
@@ -14,7 +14,7 @@ def initialize(token)
def get_request(resource, params = nil)
uri = URI.parse(MOLLIE_API_V1_URI + resource)
- uri.query = params.map { |k,v| "#{CGI.escape(k)}=#{CGI.escape(v)}}"}.join('&') if params
+ uri.query = params.map { |k,v| "#{CGI.escape(k)}=#{CGI.escape(v)}"}.join('&') if params
headers = { "Authorization" => "Bearer #{token}", "Content-Type" => "application/json" }
JSON.parse(ssl_get(uri.to_s, headers))
end
@@ -29,4 +29,4 @@ def post_request(resource, params = nil)
end
end
-end
\ No newline at end of file
+end
diff --git a/lib/offsite_payments/integrations/mollie_ideal.rb b/lib/offsite_payments/integrations/mollie_ideal.rb
index 8ae4d1525..1fe4eacd0 100644
--- a/lib/offsite_payments/integrations/mollie_ideal.rb
+++ b/lib/offsite_payments/integrations/mollie_ideal.rb
@@ -7,7 +7,7 @@ module MollieIdeal
self.live_issuers = [
["ABN AMRO", "ideal_ABNANL2A"],
["ASN Bank", "ideal_ASNBNL21"],
- ["Friesland Bank", "ideal_FRBKNL2L"],
+ ["Bunq", "ideal_BUNQNL2A"],
["ING", "ideal_INGBNL2A"],
["Knab", "ideal_KNABNL2H"],
["Rabobank", "ideal_RABONL2U"],
diff --git a/lib/offsite_payments/integrations/molpay.rb b/lib/offsite_payments/integrations/molpay.rb
index e90e68123..68cb85f4c 100644
--- a/lib/offsite_payments/integrations/molpay.rb
+++ b/lib/offsite_payments/integrations/molpay.rb
@@ -4,8 +4,8 @@ module Molpay
mattr_accessor :acknowledge_url
self.acknowledge_url = 'https://www.onlinepayment.com.my/MOLPay/API/chkstat/returnipn.php'
- def self.notification(post)
- Notification.new(post)
+ def self.notification(post, options = {})
+ Notification.new(post, options)
end
def self.return(query_string, options={})
@@ -24,19 +24,20 @@ class Helper < OffsitePayments::Helper
SERVICE_URL = 'https://www.onlinepayment.com.my/MOLPay/pay/'.freeze
- mapping :account, 'merchantid'
- mapping :amount, 'amount'
- mapping :order, 'orderid'
- mapping :customer, :name => 'bill_name',
- :email => 'bill_email',
- :phone => 'bill_mobile'
-
- mapping :description, 'bill_desc'
- mapping :language, 'langcode'
- mapping :country, 'country'
- mapping :currency, 'cur'
- mapping :return_url, 'returnurl'
- mapping :signature, 'vcode'
+ mapping :account, 'merchantid'
+ mapping :amount, 'amount'
+ mapping :order, 'orderid'
+ mapping :customer, :name => 'bill_name',
+ :email => 'bill_email',
+ :phone => 'bill_mobile'
+
+ mapping :description, 'bill_desc'
+ mapping :language, 'langcode'
+ mapping :country, 'country'
+ mapping :currency, 'cur'
+ mapping :return_url, 'returnurl'
+ mapping :notify_url, 'callbackurl'
+ mapping :signature, 'vcode'
attr_reader :amount_in_cents, :verify_key, :channel
@@ -86,6 +87,17 @@ def signature
class Notification < OffsitePayments::Notification
include ActiveUtils::PostsData
+ def status
+ case params['status']
+ when '00'
+ 'Completed'
+ when '11'
+ 'Failed'
+ when '22'
+ 'Pending'
+ end
+ end
+
def complete?
status == 'Completed'
end
@@ -144,10 +156,6 @@ def status_orig
params['status']
end
- def status
- params['status'] == '00' ? 'Completed' : 'Failed'
- end
-
def acknowledge(authcode = nil)
payload = raw + '&treq=1'
ssl_post(Molpay.acknowledge_url, payload,
@@ -175,6 +183,10 @@ def initialize(query_string, options = {})
def success?
@notification.acknowledge
end
+
+ def pending?
+ @notification.status == 'Pending'
+ end
end
end
end
diff --git a/lib/offsite_payments/integrations/moneybookers.rb b/lib/offsite_payments/integrations/moneybookers.rb
index c997b65ce..82c24a0e8 100644
--- a/lib/offsite_payments/integrations/moneybookers.rb
+++ b/lib/offsite_payments/integrations/moneybookers.rb
@@ -2,7 +2,7 @@ module OffsitePayments #:nodoc:
module Integrations #:nodoc:
module Moneybookers
mattr_accessor :production_url
- self.production_url = 'https://www.moneybookers.com/app/payment.pl'
+ self.production_url = 'https://pay.skrill.com'
def self.service_url
self.production_url
diff --git a/lib/offsite_payments/integrations/network_merchants_offsite.rb b/lib/offsite_payments/integrations/network_merchants_offsite.rb
new file mode 100644
index 000000000..e7bbae998
--- /dev/null
+++ b/lib/offsite_payments/integrations/network_merchants_offsite.rb
@@ -0,0 +1,176 @@
+module OffsitePayments #:nodoc:
+ module Integrations #:nodoc:
+ module NetworkMerchantsOffsite
+ mattr_accessor :production_url
+ mattr_accessor :test_url
+ self.production_url = 'https://secure.networkmerchants.com/api/v2/three-step'
+ self.test_url = 'https://secure.networkmerchants.com/api/v2/three-step'
+
+ def self.helper(order, account, options={})
+ Helper.new(order, account, options)
+ end
+
+ def self.notification(query_string, options={})
+ Notification.new(query_string, options)
+ end
+
+ def self.return(query_string, options={})
+ Return.new(query_string, options)
+ end
+
+ def self.service_url
+ mode = OffsitePayments.mode
+ case mode
+ when :production
+ self.production_url
+ when :test
+ self.test_url
+ else
+ raise StandardError, "Integration mode set to an invalid value: #{mode}"
+ end
+ end
+
+ module Common
+ CURRENCY_SPECIAL_MINOR_UNITS = {
+ 'BIF' => 0,
+ 'BYR' => 0,
+ 'CLF' => 0,
+ 'CLP' => 0,
+ 'CVE' => 0,
+ 'DJF' => 0,
+ 'GNF' => 0,
+ 'HUF' => 0,
+ 'ISK' => 0,
+ 'JPY' => 0,
+ 'KMF' => 0,
+ 'KRW' => 0,
+ 'PYG' => 0,
+ 'RWF' => 0,
+ 'UGX' => 0,
+ 'UYI' => 0,
+ 'VND' => 0,
+ 'VUV' => 0,
+ 'XAF' => 0,
+ 'XOF' => 0,
+ 'XPF' => 0,
+ 'BHD' => 3,
+ 'IQD' => 3,
+ 'JOD' => 3,
+ 'KWD' => 3,
+ 'LYD' => 3,
+ 'OMR' => 3,
+ 'TND' => 3,
+ 'COU' => 4
+ }
+
+ def create_signature(fields, secret)
+ data = fields.join('.')
+ digest = Digest::SHA1.hexdigest(data)
+ signed = "#{digest}.#{secret}"
+ Digest::SHA1.hexdigest(signed)
+ end
+
+ # Realex accepts currency amounts as an integer in the lowest value
+ # e.g.
+ # format_amount(110.56, 'GBP')
+ # => 11056
+ def format_amount(amount, currency)
+ if amount.is_a? Float
+ units = CURRENCY_SPECIAL_MINOR_UNITS[currency] || 2
+ multiple = 10**units
+ return (amount.to_f * multiple.to_f).to_i
+ else
+ return amount
+ end
+ end
+
+ # Realex returns currency amount as an integer
+ def format_amount_as_float(amount, currency)
+ units = CURRENCY_SPECIAL_MINOR_UNITS[currency] || 2
+ divisor = 10**units
+ return (amount.to_f / divisor.to_f)
+ end
+
+ def extract_digits(value)
+ value.scan(/\d+/).join('')
+ end
+
+ def extract_avs_code(params={})
+ [extract_digits(params[:zip]), extract_digits(params[:address1])].join('|')
+ end
+
+ end
+
+ class Helper < OffsitePayments::Helper
+ include Common
+
+ def initialize(order, account, options = {})
+ @timestamp = Time.now.strftime('%Y%m%d%H%M%S')
+ @currency = options[:currency]
+ @merchant_id = account
+ @sub_account = options[:credential2]
+ @secret = options[:credential3]
+ super
+ add_field 'currency', @currency
+ end
+
+ def form_fields
+ {'api-toke' => @merchant_id, 'amount' => :amount}
+ end
+
+ def amount=(amount)
+ add_field 'amount', format_amount(amount, @currency)
+ end
+
+ def billing_address(params={})
+ add_field(mappings[:billing_address][:zip], extract_avs_code(params))
+ add_field(mappings[:billing_address][:country], lookup_country_code(params[:country]))
+ end
+
+ def shipping_address(params={})
+ add_field(mappings[:shipping_address][:zip], extract_avs_code(params))
+ add_field(mappings[:shipping_address][:country], lookup_country_code(params[:country]))
+ end
+
+ mapping :currency, 'currency'
+ mapping :order, 'order-id'
+ mapping :amount, 'amount'
+ mapping :return_url, 'redirect-url,'
+ mapping :customer, :email => 'email'
+ mapping :shipping_address, :zip => 'postal',
+ :country => 'country'
+ mapping :billing_address, :zip => 'postal',
+ :country => 'country'
+ end
+
+ class Notification < OffsitePayments::Notification
+ include Common
+ def initialize(post, options={})
+ super
+ @secret = options[:credential3]
+ end
+ end
+
+ class Return < OffsitePayments::Return
+ def initialize(data, options)
+ super
+ @notification = Notification.new(data, options)
+ end
+
+ def success?
+ notification.complete?
+ end
+
+ # TODO: realex does not provide a separate cancelled endpoint
+ def cancelled?
+ false
+ end
+
+ def message
+ notification.message
+ end
+ end
+
+ end
+ end
+end
diff --git a/lib/offsite_payments/integrations/pay_fast.rb b/lib/offsite_payments/integrations/pay_fast.rb
index dd0abe0c9..a91e8c819 100644
--- a/lib/offsite_payments/integrations/pay_fast.rb
+++ b/lib/offsite_payments/integrations/pay_fast.rb
@@ -212,7 +212,7 @@ def fee
# The net amount credited to the receiver's account.
def amount
- params['amount_net']
+ Money.from_amount(BigDecimal.new(params['amount_net']), currency)
end
# The name of the item being charged for.
@@ -226,7 +226,7 @@ def merchant_id
end
def currency
- nil
+ 'ZAR'
end
# Generated hash depends on params order so use OrderedHash instead of Hash
diff --git a/lib/offsite_payments/integrations/paydollar.rb b/lib/offsite_payments/integrations/paydollar.rb
index 572dfbebd..f8bda6418 100644
--- a/lib/offsite_payments/integrations/paydollar.rb
+++ b/lib/offsite_payments/integrations/paydollar.rb
@@ -2,34 +2,64 @@ module OffsitePayments #:nodoc:
module Integrations #:nodoc:
module Paydollar
CURRENCY_MAP = {
- 'AED' => '784',
- 'AUD' => '036',
- 'BND' => '096',
- 'CAD' => '124',
+ 'HKD' => '344',
+ 'USD' => '840',
+ 'SGD' => '702',
'CNY' => '156',
+ 'JPY' => '392',
+ 'TWD' => '901',
+ 'AUD' => '036',
'EUR' => '978',
'GBP' => '826',
- 'HKD' => '344',
- 'IDR' => '360',
- 'JPY' => '392',
- 'KRW' => '410',
+ 'CAD' => '124',
'MOP' => '446',
+ 'PHP' => '608',
+ 'THB' => '764',
'MYR' => '458',
+ 'IDR' => '360',
+ 'KRW' => '410',
+ 'BND' => '096',
'NZD' => '554',
- 'PHP' => '608',
'SAR' => '682',
- 'SGD' => '702',
- 'THB' => '764',
- 'TWD' => '901',
- 'USD' => '840',
+ 'AED' => '784',
+ 'BRL' => '986',
+ 'INR' => '356',
+ 'TRY' => '949',
+ 'ZAR' => '710',
+ 'VND' => '704',
+ 'DKK' => '208',
+ 'ILS' => '376',
+ 'NOK' => '578',
+ 'RUB' => '643',
+ 'SEK' => '752',
+ 'CHF' => '756',
+ 'ARS' => '032',
+ 'CLP' => '152',
+ 'COP' => '170',
+ 'CZK' => '203',
+ 'EGP' => '818',
+ 'HUF' => '348',
+ 'KZT' => '398',
+ 'LBP' => '422',
+ 'MXN' => '484',
+ 'NGN' => '566',
+ 'PKR' => '586',
+ 'PEN' => '604',
+ 'PLN' => '985',
+ 'QAR' => '634',
+ 'RON' => '946',
+ 'UAH' => '980',
+ 'VEF' => '937',
+ 'LKR' => '144',
+ 'KWD' => '414',
}
-
+ # change url
def self.service_url
case OffsitePayments.mode
when :production
- 'https://www.paydollar.com/b2c2/eng/payment/payForm.jsp'
+ 'https://www.paydollar.com/b2c2/eng/payment/payShopify.jsp'
when :test
- 'https://test.paydollar.com/b2cDemo/eng/payment/payForm.jsp'
+ 'https://test.paydollar.com/b2cDemo/eng/payment/payShopify.jsp'
else
raise StandardError, "Integration mode set to an invalid value: #{mode}"
end
diff --git a/lib/offsite_payments/integrations/paytm.rb b/lib/offsite_payments/integrations/paytm.rb
new file mode 100644
index 000000000..816c5140d
--- /dev/null
+++ b/lib/offsite_payments/integrations/paytm.rb
@@ -0,0 +1,248 @@
+module OffsitePayments #:nodoc:
+ module Integrations #:nodoc:
+ module Paytm
+ CIPHER = 'AES-128-CBC'
+ SALT_ALPHABET = ['a'..'z', 'A'..'Z', '0'..'9'].flat_map { |i| i.to_a }
+ SALT_LENGTH = 4
+ STATIC_IV = '@@@@&&&###$$$$'
+
+ mattr_accessor :test_url
+ mattr_accessor :production_url
+
+ self.test_url = 'https://pguat.paytm.com/oltp-web/processTransaction'
+ self.production_url = 'https://secure.paytm.in/oltp-web/processTransaction'
+
+ def self.service_url
+ OffsitePayments.mode == :production ? production_url : test_url
+ end
+
+ def self.notification(post, options = {})
+ Notification.new(post, options)
+ end
+
+ def self.return(post, options = {})
+ Return.new(post, options)
+ end
+
+ def self.checksum(hash, salt = nil)
+ if salt.nil?
+ salt = SALT_LENGTH.times.map { SALT_ALPHABET[SecureRandom.random_number(SALT_ALPHABET.length)] }.join
+ end
+
+ values = hash.sort.to_h.values
+ values << salt
+ Digest::SHA256.hexdigest(values.join('|')) + salt
+ end
+
+ def self.encrypt(data, key)
+ aes = OpenSSL::Cipher.new(CIPHER)
+ aes.encrypt
+ aes.key = key
+ aes.iv = STATIC_IV
+
+ encrypted_data = aes.update(data) + aes.final
+ Base64.strict_encode64(encrypted_data)
+ end
+
+ class Helper < OffsitePayments::Helper
+ CHECKSUM_FIELDS = %w(MID ORDER_ID CALLBACK_URL CUST_ID TXN_AMOUNT CHANNEL_ID INDUSTRY_TYPE_ID WEBSITE MERC_UNQ_REF).freeze
+
+ mapping :amount, 'TXN_AMOUNT'
+ mapping :account, 'MID'
+ mapping :order, 'MERC_UNQ_REF'
+
+ mapping :customer, :email => 'CUST_ID'
+
+
+ mapping :credential3, 'INDUSTRY_TYPE_ID'
+ mapping :credential4, 'WEBSITE'
+ mapping :channel_id, 'CHANNEL_ID'
+ mapping :return_url, 'CALLBACK_URL'
+ mapping :checksum, 'CHECKSUMHASH'
+
+ def initialize(order, account, options = {})
+ super
+ @options = options
+ @timestamp = Time.now.strftime('%Y%m%d%H%M%S')
+
+ add_field(mappings[:channel_id], "WEB")
+ add_field 'ORDER_ID', "#{order}-#{@timestamp.to_i}"
+
+ self.pg = 'CC'
+ end
+
+ def form_fields
+ sanitize_fields
+ @fields.merge(mappings[:checksum] => encrypt_checksum)
+ end
+
+ def encrypt_checksum
+ payload_items = {}
+
+ CHECKSUM_FIELDS.each do |field|
+ payload_items[field] = @fields[field]
+ end
+
+ Paytm.encrypt(Paytm.checksum(payload_items), @options[:credential2])
+ end
+
+ def sanitize_fields
+ %w(email phone).each do |field|
+ @fields[field].gsub!(/[^a-zA-Z0-9\-_@\/\s.]/, '') if @fields[field]
+ end
+ end
+ end
+
+ class Notification < OffsitePayments::Notification
+ PAYTM_RESPONSE_PARAMS = %w(MID BANKTXNID TXNAMOUNT CURRENCY STATUS RESPCODE RESPMSG TXNDATE GATEWAYNAME BANKNAME PAYMENTMODE PROMO_CAMP_ID PROMO_STATUS PROMO_RESPCODE ORDERID TXNID REFUNDAMOUNT REFID MERC_UNQ_REF CUSTID).freeze
+
+ def initialize(post, options = {})
+ super
+ @secret_key = options[:credential2]
+ end
+
+ def complete?
+ status == 'Completed'
+ end
+
+ def status
+ if transaction_status.casecmp("TXN_SUCCESS").zero?
+ 'Completed'
+ elsif transaction_status.casecmp("pending").zero?
+ 'Pending'
+ else
+ 'Failed'
+ end
+ end
+
+ def invoice_ok?(order_id)
+ order_id.to_s == invoice.to_s
+ end
+
+ # Order amount should be equal to gross
+ def amount_ok?(order_amount)
+ BigDecimal.new(original_gross) == order_amount
+ end
+
+ # Status of transaction return from the Paytm. List of possible values:
+ # TXN_SUCCESS::
+ # PENDING::
+ # TXN_FAILURE::
+ def transaction_status
+ @params['STATUS']
+ end
+
+ # ID of this transaction (Paytm transaction id)
+ def transaction_id
+ @params['TXNID']
+ end
+
+ # Mode of Payment
+ #
+ # 'CC' for credit-card
+ # 'NB' for net-banking
+ # 'PPI' for wallet
+ def type
+ @params['PAYMENTMODE']
+ end
+
+ # What currency have we been dealing with
+ def currency
+ @params['CURRENCY']
+ end
+
+ def item_id
+ @params['MERC_UNQ_REF']
+ end
+
+ # This is the invoice which you passed to Paytm
+ def invoice
+ @params['MERC_UNQ_REF']
+ end
+
+ # Merchant Id provided by the Paytm
+ def account
+ @params['MID']
+ end
+
+ # original amount send by merchant
+ def original_gross
+ @params['TXNAMOUNT']
+ end
+
+ def gross
+ parse_and_round_gross_amount(@params['TXNAMOUNT'])
+ end
+
+ def message
+ @params['RESPMSG']
+ end
+
+ def checksum
+ @params['CHECKSUMHASH']
+ end
+
+ def acknowledge
+ checksum_ok?
+ end
+
+ def checksum_ok?
+ normalized_data = checksum.delete("\n").tr(' ', '+')
+ encrypted_data = Base64.strict_decode64(normalized_data)
+
+ aes = OpenSSL::Cipher::Cipher.new(CIPHER)
+ aes.decrypt
+ aes.key = @secret_key
+ aes.iv = STATIC_IV
+ received_checksum = aes.update(encrypted_data) + aes.final
+
+ salt = received_checksum[-SALT_LENGTH..-1]
+ expected_params = @params.keep_if { |k| PAYTM_RESPONSE_PARAMS.include?(k) }.sort.to_h
+ expected_checksum = Paytm.checksum(expected_params, salt)
+
+ if received_checksum == expected_checksum
+ @message = @params['RESPMSG']
+ @params['RESPCODE'] == '01'
+ else
+ @message = 'Return checksum not matching the data provided'
+ false
+ end
+ end
+
+ private
+
+ def parse_and_round_gross_amount(amount)
+ rounded_amount = (amount.to_f * 100.0).round
+ sprintf('%.2f', rounded_amount / 100.00)
+ end
+ end
+
+ class Return < OffsitePayments::Return
+ def initialize(query_string, options = {})
+ super
+ @notification = Notification.new(query_string, options)
+ end
+
+ def transaction_id
+ @notification.transaction_id
+ end
+
+ def status(order_id, order_amount)
+ if @notification.invoice_ok?(order_id) && @notification.amount_ok?(BigDecimal.new(order_amount))
+ @notification.status
+ else
+ 'Mismatch'
+ end
+ end
+
+ def success?
+ status(@params['MERC_UNQ_REF'], @params['TXNAMOUNT']) == 'Completed'
+ end
+
+ def message
+ @notification.message
+ end
+ end
+ end
+ end
+end
diff --git a/lib/offsite_payments/integrations/payu_in.rb b/lib/offsite_payments/integrations/payu_in.rb
index 7ce98b624..32bec46ba 100755
--- a/lib/offsite_payments/integrations/payu_in.rb
+++ b/lib/offsite_payments/integrations/payu_in.rb
@@ -42,7 +42,7 @@ class Helper < OffsitePayments::Helper
:address1 => 'address1',
:address2 => 'address2',
:state => 'state',
- :zip => 'zip',
+ :zip => 'zipcode',
:country => 'country'
# Which tab you want to be open default on PayU
@@ -84,8 +84,9 @@ def generate_checksum
end
def sanitize_fields
- ['address1', 'address2', 'city', 'state', 'country', 'productinfo', 'email', 'phone'].each do |field|
- @fields[field].gsub!(/[^a-zA-Z0-9\-_@\/\s.]/, '') if @fields[field]
+ @fields['phone'] = @fields['phone'].gsub(/[^0-9]/, '') if @fields['phone']
+ ['address1', 'address2', 'city', 'state', 'country', 'productinfo', 'email'].each do |field|
+ @fields[field] = @fields[field].gsub(/[^a-zA-Z0-9\-_@\/\s.]/, '') if @fields[field]
end
end
@@ -116,7 +117,8 @@ def invoice_ok?( order_id )
# Order amount should be equal to gross - discount
def amount_ok?( order_amount, order_discount = BigDecimal.new( '0.0' ) )
- BigDecimal.new( original_gross ) == order_amount && BigDecimal.new( discount.to_s ) == order_discount
+ parsed_discount = discount.nil? ? 0.to_d : discount.to_d
+ BigDecimal.new( original_gross ) == order_amount && parsed_discount == order_discount
end
# Status of transaction return from the PayU. List of possible values:
diff --git a/lib/offsite_payments/integrations/platron.rb b/lib/offsite_payments/integrations/platron.rb
index b4d7d625c..2695de94c 100644
--- a/lib/offsite_payments/integrations/platron.rb
+++ b/lib/offsite_payments/integrations/platron.rb
@@ -120,7 +120,7 @@ def ps_full_amount
end
def amount
- params['pg_amount']
+ Money.from_amount(BigDecimal.new(params['pg_amount']), currency)
end
def secret
diff --git a/lib/offsite_payments/integrations/realex_offsite.rb b/lib/offsite_payments/integrations/realex_offsite.rb
index 65958ee48..dd6af55ed 100644
--- a/lib/offsite_payments/integrations/realex_offsite.rb
+++ b/lib/offsite_payments/integrations/realex_offsite.rb
@@ -3,8 +3,8 @@ module Integrations #:nodoc:
module RealexOffsite
mattr_accessor :production_url
mattr_accessor :test_url
- self.production_url = 'https://epage.payandshop.com/epage.cgi'
- self.test_url = 'https://hpp.sandbox.realexpayments.com/pay'
+ self.production_url = 'https://pay.realexpayments.com/pay'
+ self.test_url = 'https://pay.sandbox.realexpayments.com/pay'
def self.helper(order, account, options={})
Helper.new(order, account, options)
@@ -71,23 +71,28 @@ def create_signature(fields, secret)
end
# Realex accepts currency amounts as an integer in the lowest value
- # e.g.
+ # e.g.
# format_amount(110.56, 'GBP')
# => 11056
def format_amount(amount, currency)
- units = CURRENCY_SPECIAL_MINOR_UNITS[currency] || 2
- multiple = 10**units
- return (amount.to_f * multiple.to_f).to_i
+ if amount.is_a? Float
+ units = CURRENCY_SPECIAL_MINOR_UNITS[currency] || 2
+ multiple = 10**units
+ return (amount.to_f * multiple.to_f).to_i
+ else
+ return amount
+ end
end
# Realex returns currency amount as an integer
def format_amount_as_float(amount, currency)
units = CURRENCY_SPECIAL_MINOR_UNITS[currency] || 2
divisor = 10**units
- return (amount.to_f / divisor.to_f)
+ return ((amount || 0).to_d / divisor.to_d)
end
def extract_digits(value)
+ return unless value
value.scan(/\d+/).join('')
end
@@ -211,10 +216,15 @@ def gross
format_amount_as_float(params['AMOUNT'], currency)
end
+
def complete?
verified? && status == 'Completed'
end
+ def success?
+ status == 'Completed'
+ end
+
# Fields for Realex signature verification
def timestamp
params['TIMESTAMP']
@@ -231,6 +241,7 @@ def checkout_id
def order_id
params['ORDER_ID']
end
+ alias_method :transaction_id, :order_id
def result
params['RESULT']
@@ -247,6 +258,7 @@ def pasref
def authcode
params['AUTHCODE']
end
+ alias_method :authorization_code, :authcode
def signature
params['SHA1HASH']
diff --git a/lib/offsite_payments/integrations/robokassa.rb b/lib/offsite_payments/integrations/robokassa.rb
index a8a104472..3180a1e34 100644
--- a/lib/offsite_payments/integrations/robokassa.rb
+++ b/lib/offsite_payments/integrations/robokassa.rb
@@ -103,10 +103,6 @@ def complete?
true
end
- def amount
- BigDecimal.new(gross)
- end
-
def item_id
params['InvId']
end
@@ -138,6 +134,10 @@ def acknowledge(authcode = nil)
def success_response(*args)
"OK#{item_id}"
end
+
+ def currency
+ 'RUB'
+ end
end
class Return < OffsitePayments::Return
diff --git a/lib/offsite_payments/integrations/sage_pay_form.rb b/lib/offsite_payments/integrations/sage_pay_form.rb
index 70c056622..ef1a16a0d 100644
--- a/lib/offsite_payments/integrations/sage_pay_form.rb
+++ b/lib/offsite_payments/integrations/sage_pay_form.rb
@@ -69,14 +69,20 @@ def cipher(action, key, payload)
class Helper < OffsitePayments::Helper
include Encryption
+ attr_reader :identifier
+
+ def initialize(order, account, options={})
+ super
+ @identifier = rand(0..99999).to_s.rjust(5, '0')
+ add_field 'VendorTxCode', "#{order}-#{@identifier}"
+ end
+
mapping :credential2, 'EncryptKey'
mapping :account, 'Vendor'
mapping :amount, 'Amount'
mapping :currency, 'Currency'
- mapping :order, 'VendorTxCode'
-
mapping :customer,
:first_name => 'BillingFirstnames',
:last_name => 'BillingSurname',
@@ -121,6 +127,8 @@ def map_billing_address_to_shipping_address
end
def form_fields
+ fields.delete('locale')
+
map_billing_address_to_shipping_address unless @shipping_address_set
fields['DeliveryFirstnames'] ||= fields['BillingFirstnames']
@@ -154,8 +162,8 @@ def create_crypt_field(fields, key)
parts = fields.map { |k, v| "#{k}=#{sanitize(k, v)}" unless v.nil? }.compact.shuffle
parts.unshift(sage_encrypt_salt(key.length, key.length * 2))
sage_encrypt(parts.join('&'), key)
- rescue OpenSSL::Cipher::CipherError => e
- if e.message == 'key length too short'
+ rescue OpenSSL::Cipher::CipherError, ArgumentError => e
+ if e.message == 'key length too short' || e.message == 'key must be 16 bytes'
raise ActionViewHelperError, 'Invalid encryption key.'
else
raise
@@ -246,7 +254,7 @@ def message
# Vendor-supplied code (:order mapping).
def item_id
- params['VendorTxCode']
+ params['VendorTxCode'].rpartition('-').first
end
# Internal SagePay code, typically "{LONG-UUID}".
diff --git a/lib/offsite_payments/integrations/universal.rb b/lib/offsite_payments/integrations/universal.rb
index 8b79d889a..6b2503326 100644
--- a/lib/offsite_payments/integrations/universal.rb
+++ b/lib/offsite_payments/integrations/universal.rb
@@ -73,20 +73,13 @@ def amount=(amount)
add_field 'x_amount', format_amount(amount, @currency)
end
- def shipping(amount)
- add_field 'x_amount_shipping', format_amount(amount, @currency)
- end
-
- def tax(amount)
- add_field 'x_amount_tax', format_amount(amount, @currency)
- end
-
def sign_fields
@fields.merge!('x_signature' => generate_signature)
end
def generate_signature
- Universal.sign(@fields, @key)
+ fields_to_sign = @fields.select { |key, _| key.start_with?('x_') && key != 'x_signature' }
+ Universal.sign(fields_to_sign, @key)
end
mapping :account, 'x_account_id'
@@ -105,6 +98,17 @@ def generate_signature
:email => 'x_customer_email',
:phone => 'x_customer_phone'
+ mapping :billing_address, :first_name => 'x_customer_billing_first_name',
+ :last_name => 'x_customer_billing_last_name',
+ :city => 'x_customer_billing_city',
+ :company => 'x_customer_billing_company',
+ :address1 => 'x_customer_billing_address1',
+ :address2 => 'x_customer_billing_address2',
+ :state => 'x_customer_billing_state',
+ :zip => 'x_customer_billing_zip',
+ :country => 'x_customer_billing_country',
+ :phone => 'x_customer_billing_phone'
+
mapping :shipping_address, :first_name => 'x_customer_shipping_first_name',
:last_name => 'x_customer_shipping_last_name',
:city => 'x_customer_shipping_city',
@@ -160,6 +164,10 @@ def status
result && result.capitalize
end
+ def message
+ @params['x_message']
+ end
+
def test?
@params['x_test'] == 'true'
end
@@ -181,6 +189,10 @@ def initialize(query_string, options = {})
def success?
@notification.acknowledge
end
+
+ def message
+ @notification.message
+ end
end
end
end
diff --git a/lib/offsite_payments/integrations/web_pay.rb b/lib/offsite_payments/integrations/web_pay.rb
index 402be6c42..b1159e9bc 100644
--- a/lib/offsite_payments/integrations/web_pay.rb
+++ b/lib/offsite_payments/integrations/web_pay.rb
@@ -150,7 +150,7 @@ def complete?
end
def amount
- BigDecimal.new(gross)
+ Money.from_amount(BigDecimal.new(gross), currency)
end
def item_id
@@ -180,6 +180,10 @@ def acknowledge(authcode = nil)
def success_response(*args)
{:nothing => true}
end
+
+ def currency
+ params['currency_id']
+ end
end
end
end
diff --git a/lib/offsite_payments/integrations/webmoney.rb b/lib/offsite_payments/integrations/webmoney.rb
index 5c4393b5d..3d9861d07 100644
--- a/lib/offsite_payments/integrations/webmoney.rb
+++ b/lib/offsite_payments/integrations/webmoney.rb
@@ -83,7 +83,7 @@ def recognizes?
end
def amount
- BigDecimal.new(gross)
+ Money.from_amount(BigDecimal.new(gross), currency)
end
def key_present?
@@ -113,6 +113,10 @@ def acknowledge(authcode = nil)
def success_response(*args)
{:nothing => true}
end
+
+ def currency
+ 'RUB'
+ end
end
end
end
diff --git a/lib/offsite_payments/integrations/world_pay.rb b/lib/offsite_payments/integrations/world_pay.rb
index 0495e4536..5ce4a900f 100644
--- a/lib/offsite_payments/integrations/world_pay.rb
+++ b/lib/offsite_payments/integrations/world_pay.rb
@@ -34,8 +34,13 @@ class Helper < OffsitePayments::Helper
mapping :customer, :email => 'email',
:phone => 'tel'
- mapping :billing_address, :zip => 'postcode',
- :country => 'country'
+ mapping :billing_address,
+ :address1 => 'address1',
+ :address2 => 'address2',
+ :city => 'town',
+ :state => 'region',
+ :zip => 'postcode',
+ :country => 'country'
mapping :description, 'desc'
mapping :notify_url, 'MC_callback'
@@ -62,16 +67,6 @@ def initialize(order, account, options = {})
end
end
- # WorldPay only supports a single address field so we
- # have to concat together - lines are separated using
- def billing_address(params={})
- add_field(mappings[:billing_address][:zip], params[:zip])
- add_field(mappings[:billing_address][:country], lookup_country_code(params[:country]))
-
- address = [params[:address1], params[:address2], params[:city], params[:state]].compact
- add_field('address', address.join('
'))
- end
-
# WorldPay only supports a single name field so we have to concat
def customer(params={})
add_field(mappings[:customer][:email], params[:email])
diff --git a/lib/offsite_payments/notification.rb b/lib/offsite_payments/notification.rb
index 386631314..fb7aa03ec 100644
--- a/lib/offsite_payments/notification.rb
+++ b/lib/offsite_payments/notification.rb
@@ -30,11 +30,10 @@ def gross_cents
(gross.to_f * 100.0).round
end
- # This combines the gross and currency and returns a proper Money object.
- # this requires the money library located at http://rubymoney.github.io/money/
def amount
- return Money.new(gross_cents, currency) rescue ArgumentError
- return Money.new(gross_cents) # maybe you have an own money object which doesn't take a currency?
+ amount = gross ? gross.to_d : 0
+ return Money.from_amount(amount, currency) rescue ArgumentError
+ return Money.from_amount(amount) # maybe you have an own money object which doesn't take a currency?
end
# reset the notification.
diff --git a/lib/offsite_payments/return.rb b/lib/offsite_payments/return.rb
index 94446d463..11a2cc6c0 100644
--- a/lib/offsite_payments/return.rb
+++ b/lib/offsite_payments/return.rb
@@ -25,9 +25,9 @@ def parse(query_string)
return {} if query_string.blank?
query_string.split('&').inject({}) do |memo, chunk|
- next if chunk.empty?
+ next memo if chunk.empty?
key, value = chunk.split('=', 2)
- next if key.empty?
+ next memo if key.empty?
value = value.nil? ? nil : CGI.unescape(value)
memo[CGI.unescape(key)] = value
memo
diff --git a/lib/offsite_payments/version.rb b/lib/offsite_payments/version.rb
index cbbbeda84..e6781328e 100644
--- a/lib/offsite_payments/version.rb
+++ b/lib/offsite_payments/version.rb
@@ -1,3 +1,3 @@
module OffsitePayments
- VERSION = "2.1.0"
+ VERSION = "2.6.4"
end
diff --git a/offsite_payments.gemspec b/offsite_payments.gemspec
index 107466c19..3dc3fc2ee 100644
--- a/offsite_payments.gemspec
+++ b/offsite_payments.gemspec
@@ -22,13 +22,13 @@ Gem::Specification.new do |s|
s.files = Dir['CHANGELOG', 'README.md', 'MIT-LICENSE', 'lib/**/*']
s.require_path = 'lib'
- s.add_dependency('activesupport', '>= 3.2.14', '< 5.0.0')
- s.add_dependency('i18n', '~> 0.5')
+ s.add_dependency('activesupport', '>= 3.2.14', '< 5.2')
+ s.add_dependency('i18n', '>= 0.6.6')
s.add_dependency('money', '< 7.0.0')
s.add_dependency('builder', '>= 2.1.2', '< 4.0.0')
- s.add_dependency('active_utils', '~> 3.0.0')
- s.add_dependency('nokogiri', "~> 1.4")
- s.add_dependency('actionpack', ">= 3.2.20", "< 5.0.0")
+ s.add_dependency('active_utils', '~> 3.3.0')
+ s.add_dependency('nokogiri', "~> 1.6")
+ s.add_dependency('actionpack', '>= 3.2.20', '< 5.2')
s.add_development_dependency('rake')
s.add_development_dependency('test-unit', '~> 3.0')
diff --git a/test/fixtures.yml b/test/fixtures.yml
index 255717ced..9147fb622 100644
--- a/test/fixtures.yml
+++ b/test/fixtures.yml
@@ -11,10 +11,6 @@
# Paste any required PEM certificates after the pem key.
#
-app55:
- api_key: "QDtACYMCFqtuKOQ22QtCkGR1TzD7XM8i"
- api_secret: "yT1FRpuusBIQoEBIfIQ8bPStkl7yzdTz"
-
authorize_net:
login: X
password: Y
@@ -105,6 +101,11 @@ certo_direct:
login: 1
password: vP6OwK3
+# Fully working credentials
+checkout_finland:
+ merchant: '375917'
+ secret: 'SAIPPUAKAUPPIAS'
+
conekta:
key: key_eYvWV7gSDkNYXsmr
diff --git a/test/remote/remote_checkout_finland_test.rb b/test/remote/remote_checkout_finland_test.rb
new file mode 100644
index 000000000..c408a9246
--- /dev/null
+++ b/test/remote/remote_checkout_finland_test.rb
@@ -0,0 +1,61 @@
+require 'test_helper'
+require 'remote_test_helper'
+
+class RemoteCheckoutFinlandTest < Test::Unit::TestCase
+ include RemoteTestHelper
+
+ def setup
+ @stamp = Time.now.to_i.to_s # Unique identifier for the payment with all information
+ @stamp2 = (Time.now.to_i+1000).to_s # Unique identifier for the payment with minimal information
+ @merchant = fixtures(:checkout_finland)[:merchant]
+ @secret = fixtures(:checkout_finland)[:secret]
+ end
+
+ def test_valid_payment_page_minimal_fields
+ payment_page = submit %(
+ <% payment_service_for('#{@stamp}', '#{@merchant}', :service => :checkout_finland, :amount => '200', :currency => 'EUR', :credential2 => '#{@secret}') do |service| %>
+ <% service.language = 'FI' %> # Payment page language 2 character ISO code.
+ <% service.reference = '123123123' %> # Payment reference number. 20 digits max.
+ <% service.content = '1' %> # '1' for normal and '2' for adult payments.
+ <% service.delivery_date = '20140110' %> # Delivery date in the form of YYYYMMDD
+ <% service.notify_url = 'http://example.org/return' %> # Notify URL
+ <% service.reject_url = 'http://example.org/return' %> # Reject URL
+ <% service.return_url = 'http://example.org/return' %> # Return URL
+ <% service.cancel_return_url = 'http://example.org/return' %> # Cancel URL
+ <% end %>
+ )
+
+ assert_match(%r(Testi Oy)i, payment_page.body)
+ assert_match(%r(Testikuja 1)i, payment_page.body)
+ assert_match(%r(12345 Testi)i, payment_page.body)
+ end
+
+ def test_valid_payment_page_all_fields
+ payment_page = submit %(
+ <% payment_service_for('#{@stamp2}', '#{@merchant}', :service => :checkout_finland, :amount => '200', :currency => 'EUR',:credential2 => '#{@secret}') do |service| %>
+ <% service.customer :first_name => "Tero", # Optional customer information
+ :last_name => 'Testaaja',
+ :phone => '0800 552 010',
+ :email => 'support@checkout.fi' %>
+ <% service.language = 'FI' %>
+ <% service.billing_address :address1 => 'Testikatu 1 A 10', # Optional billing address
+ :city => 'Helsinki',
+ :zip => '00100',
+ :country => 'FIN' %>
+ <% service.reference = '123123123' %>
+ <% service.content = '1' %>
+ <% service.delivery_date = '20140110' %>
+ <% service.description = 'Remote test items' %>
+ <% service.notify_url = 'http://example.org/return' %>
+ <% service.reject_url = 'http://example.org/return' %>
+ <% service.return_url = 'http://example.org/return' %>
+ <% service.cancel_return_url = 'http://example.org/return' %>
+ <% end %>
+ )
+
+ assert_match(%r(Tero Testaaja)i, payment_page.body)
+ assert_match(%r(Testikatu 1 A 10)i, payment_page.body)
+ assert_match(%r(Remote test items)i, payment_page.body)
+ end
+
+end
diff --git a/test/unit/action_view_helper_test.rb b/test/unit/action_view_helper_test.rb
index a30262a57..d6a7e9d32 100644
--- a/test/unit/action_view_helper_test.rb
+++ b/test/unit/action_view_helper_test.rb
@@ -38,9 +38,7 @@ class ActionView::Base
include ActionView::Helpers::TextHelper
end
- ::MissingSourceFile::REGEXPS << [/^cannot load such file -- (.+)$/i, 1]
class PaymentServiceController < ActionController::Base
-
def payment_action
render :inline => "<% payment_service_for('order-1','test', :service => :bogus){} %>"
end
diff --git a/test/unit/integrations/a1agregator/a1agregator_notification_test.rb b/test/unit/integrations/a1agregator/a1agregator_notification_test.rb
index 8210f961c..19f478782 100644
--- a/test/unit/integrations/a1agregator/a1agregator_notification_test.rb
+++ b/test/unit/integrations/a1agregator/a1agregator_notification_test.rb
@@ -23,7 +23,7 @@ def test_accessors
end
def test_compositions
- assert_equal Money.new(10000, 'RUB'), @a1agregator.amount
+ assert_equal Money.from_amount(100.00, 'RUB'), @a1agregator.amount
end
def test_acknowledgement
diff --git a/test/unit/integrations/authorize_net_sim/authorize_net_sim_notification_test.rb b/test/unit/integrations/authorize_net_sim/authorize_net_sim_notification_test.rb
index e8732ca49..05141366c 100644
--- a/test/unit/integrations/authorize_net_sim/authorize_net_sim_notification_test.rb
+++ b/test/unit/integrations/authorize_net_sim/authorize_net_sim_notification_test.rb
@@ -26,7 +26,7 @@ def test_accessors_when_not_set
end
def test_compositions
- assert_equal Money.new(12100, 'USD'), @authorize_net_sim.amount
+ assert_equal Money.from_amount(121.00, 'USD'), @authorize_net_sim.amount
end
def test_accessors_when_set
diff --git a/test/unit/integrations/bit_pay/bit_pay_helper_test.rb b/test/unit/integrations/bit_pay/bit_pay_helper_test.rb
index be1ddddb0..c97dc2d40 100644
--- a/test/unit/integrations/bit_pay/bit_pay_helper_test.rb
+++ b/test/unit/integrations/bit_pay/bit_pay_helper_test.rb
@@ -50,10 +50,4 @@ def test_form_fields_uses_invoice_id
assert_equal '98kui1gJ7FocK41gUaBZxG', @helper.form_fields['id']
end
-
- def test_raises_when_invalid_json_returned
- Net::HTTP.any_instance.expects(:request).returns(stub(:body => 'Invalid JSON'))
-
- assert_raises(ActionViewHelperError) { @helper.form_fields['id'] }
- end
end
diff --git a/test/unit/integrations/bit_pay/bit_pay_notification_test.rb b/test/unit/integrations/bit_pay/bit_pay_notification_test.rb
index 394571584..ece1a2aad 100644
--- a/test/unit/integrations/bit_pay/bit_pay_notification_test.rb
+++ b/test/unit/integrations/bit_pay/bit_pay_notification_test.rb
@@ -17,22 +17,8 @@ def test_accessors
assert_equal 123, @bit_pay.item_id
end
- def test_invalid_data
- hash = JSON.parse(http_raw_data)
- @bit_pay = BitPay::Notification.new('{"invalid":json}')
-
- assert @bit_pay.params.empty?
- end
-
- def test_item_id_invalid_json
- hash = JSON.parse(http_raw_data)
- @bit_pay = BitPay::Notification.new(hash.merge('posData' => 'Invalid JSON').to_json)
-
- assert_nil @bit_pay.item_id
- end
-
def test_compositions
- assert_equal Money.new(1000, 'USD'), @bit_pay.amount
+ assert_equal Money.from_amount(10.00, 'USD'), @bit_pay.amount
end
def test_successful_acknowledgement
@@ -45,11 +31,6 @@ def test_acknowledgement_error
assert !@bit_pay.acknowledge
end
- def test_acknowledgement_invalid_json
- Net::HTTP.any_instance.expects(:request).returns(stub(:body => '{invalid json'))
- assert !@bit_pay.acknowledge
- end
-
private
def http_raw_data
{
diff --git a/test/unit/integrations/checkout_finland/checkout_finland_helper_test.rb b/test/unit/integrations/checkout_finland/checkout_finland_helper_test.rb
new file mode 100644
index 000000000..ae989c3a3
--- /dev/null
+++ b/test/unit/integrations/checkout_finland/checkout_finland_helper_test.rb
@@ -0,0 +1,77 @@
+# encoding: UTF-8
+require 'test_helper'
+
+class CheckoutFinlandHelperTest < Test::Unit::TestCase
+ include OffsitePayments::Integrations
+
+ def setup
+ @helper = CheckoutFinland::Helper.new('1389003386','375917', :amount => 200, :currency => 'EUR', :credential2 => "SAIPPUAKAUPPIAS")
+ end
+
+ def test_basic_helper_fields
+ assert_field 'MERCHANT', '375917'
+
+ assert_field 'AMOUNT', '200'
+ assert_field 'STAMP', '1389003386'
+ end
+
+ def test_customer_fields
+ @helper.customer :first_name => 'Tero', :last_name => 'Testaaja', :phone => '0800 552 010', :email => 'support@checkout.fi'
+ assert_field 'FIRSTNAME', 'Tero'
+ assert_field 'FAMILYNAME', 'Testaaja'
+ assert_field 'PHONE', '0800 552 010'
+ assert_field 'EMAIL', 'support@checkout.fi'
+ end
+
+ def test_address_mapping
+ @helper.billing_address :address1 => 'Testikatu 1 A 10',
+ :city => 'Helsinki',
+ :zip => '00100',
+ :country => 'FIN'
+
+ assert_field 'ADDRESS', 'Testikatu 1 A 10'
+ assert_field 'POSTOFFICE', 'Helsinki'
+ assert_field 'POSTCODE', '00100'
+ assert_field 'COUNTRY', 'FIN'
+ end
+
+ def test_authcode_generation
+ @helper.customer :first_name => 'Tero', :last_name => 'Testaaja', :phone => '0800 552 010', :email => 'support@checkout.fi'
+ @helper.billing_address :address1 => 'Testikatu 1 A 10',
+ :city => 'Helsinki',
+ :zip => '00100',
+ :country => 'FIN'
+
+ @helper.reference = "474738238"
+ @helper.language = "FI"
+ @helper.content = "1"
+ @helper.delivery_date = "20140110"
+ @helper.description = "Some items"
+
+ @helper.notify_url = "http://www.example.com/notify"
+ @helper.reject_url = "http://www.example.com/reject"
+ @helper.return_url = "http://www.example.com/return"
+ @helper.cancel_return_url = "http://www.example.com/cancel"
+
+ assert_equal @helper.generate_md5string, "0968BCF2A747F4A9118A889C8EC5CDA3"
+
+ end
+
+ def test_unknown_address_mapping
+ @helper.billing_address :farm => 'CA'
+ assert_equal 8, @helper.fields.size
+ end
+
+ def test_unknown_mapping
+ assert_nothing_raised do
+ @helper.company_address :address => '500 Dwemthy Fox Road'
+ end
+ end
+
+ def test_setting_invalid_address_field
+ fields = @helper.fields.dup
+ @helper.billing_address :street => 'My Street'
+ assert_equal fields, @helper.fields
+ end
+
+end
diff --git a/test/unit/integrations/checkout_finland/checkout_finland_module_test.rb b/test/unit/integrations/checkout_finland/checkout_finland_module_test.rb
new file mode 100644
index 000000000..062c5d127
--- /dev/null
+++ b/test/unit/integrations/checkout_finland/checkout_finland_module_test.rb
@@ -0,0 +1,9 @@
+require 'test_helper'
+
+class CheckoutFinlandModuleTest < Test::Unit::TestCase
+ include OffsitePayments::Integrations
+
+ def test_notification_method
+ assert_instance_of CheckoutFinland::Notification, CheckoutFinland.notification({"VERSION" => "0001", "STAMP" => "1388998411", "REFERENCE" => "474738238", "PAYMENT" => "12288575", "STATUS" => "3", "ALGORITHM" => "3", "MAC" =>"2657BA96CC7879C79192547EB6C9D4082EA39CA52FE1DAD09CB1C632ECFDAE67"})
+ end
+end
diff --git a/test/unit/integrations/checkout_finland/checkout_finland_notification_test.rb b/test/unit/integrations/checkout_finland/checkout_finland_notification_test.rb
new file mode 100644
index 000000000..9662cad0b
--- /dev/null
+++ b/test/unit/integrations/checkout_finland/checkout_finland_notification_test.rb
@@ -0,0 +1,34 @@
+require 'test_helper'
+
+class CheckoutFinlandNotificationTest < Test::Unit::TestCase
+ include OffsitePayments::Integrations
+
+ def setup
+ @checkout_finland = CheckoutFinland::Notification.new(http_params)
+ end
+
+ def test_accessors
+ assert_equal false, @checkout_finland.complete? # http_params return data for a delayed payment that is not complete
+ assert_equal "3", @checkout_finland.status
+ assert_equal "12288575", @checkout_finland.transaction_id
+ assert_equal "474738238", @checkout_finland.reference
+ assert_equal "2657BA96CC7879C79192547EB6C9D4082EA39CA52FE1DAD09CB1C632ECFDAE67", @checkout_finland.mac
+ assert @checkout_finland.delayed?
+ assert_equal false, @checkout_finland.activation?
+ assert_equal false, @checkout_finland.cancelled?
+ end
+
+ def test_acknowledgement
+ assert @checkout_finland.acknowledge("SAIPPUAKAUPPIAS")
+ end
+
+ def test_faulty_acknowledgement
+ # Same data different (invalid) authcode
+ assert_equal false, @checkout_finland.acknowledge("LOREMIPSUM")
+ end
+
+ private
+ def http_params
+ {"VERSION" => "0001", "STAMP" => "1388998411", "REFERENCE" => "474738238", "PAYMENT" => "12288575", "STATUS" => "3", "ALGORITHM" => "3", "MAC" =>"2657BA96CC7879C79192547EB6C9D4082EA39CA52FE1DAD09CB1C632ECFDAE67"}
+ end
+end
diff --git a/test/unit/integrations/chronopay/chronopay_notification_test.rb b/test/unit/integrations/chronopay/chronopay_notification_test.rb
index 25b387ee5..11bf80c77 100644
--- a/test/unit/integrations/chronopay/chronopay_notification_test.rb
+++ b/test/unit/integrations/chronopay/chronopay_notification_test.rb
@@ -41,7 +41,7 @@ def test_parse_received_at
end
def test_compositions
- assert_equal Money.new(50000, 'CAD'), @notification.amount
+ assert_equal Money.from_amount(500.00, 'CAD'), @notification.amount
end
def test_payment_successful_status
diff --git a/test/unit/integrations/citrus/citrus_notification_test.rb b/test/unit/integrations/citrus/citrus_notification_test.rb
index ff8f918ad..21006d4e4 100644
--- a/test/unit/integrations/citrus/citrus_notification_test.rb
+++ b/test/unit/integrations/citrus/citrus_notification_test.rb
@@ -12,7 +12,6 @@ def test_accessors
assert_equal "Completed", @citrus.status
assert_equal "CTX1309180549472058821", @citrus.transaction_id
assert_equal "SUCCESS", @citrus.transaction_status
- assert_equal "10.00", @citrus.amount
assert_equal "INR", @citrus.currency
assert_equal true, @citrus.invoice_ok?('ORD427')
assert_equal true, @citrus.amount_ok?(BigDecimal.new('10.00'))
@@ -24,7 +23,7 @@ def test_accessors
end
def test_compositions
- assert_equal '10.00', @citrus.amount
+ assert_equal Money.from_amount(10.00, @citrus.currency), @citrus.amount
end
def test_acknowledgement
diff --git a/test/unit/integrations/citrus/citrus_return_test.rb b/test/unit/integrations/citrus/citrus_return_test.rb
index 2d040265e..25f0be68d 100644
--- a/test/unit/integrations/citrus/citrus_return_test.rb
+++ b/test/unit/integrations/citrus/citrus_return_test.rb
@@ -44,7 +44,7 @@ def test_return_has_notification
assert_equal "Completed", notification.status
assert_equal "CTX1309180549472058821", notification.transaction_id
assert_equal "SUCCESS", notification.transaction_status
- assert_equal "10.00", notification.amount
+ assert_equal Money.from_amount(BigDecimal.new(10), "inr"), notification.amount
assert_equal "INR", notification.currency
assert_equal true, notification.invoice_ok?('ORD427')
assert_equal true, notification.amount_ok?(BigDecimal.new('10.00'))
diff --git a/test/unit/integrations/coinbase/coinbase_return_test.rb b/test/unit/integrations/coinbase/coinbase_return_test.rb
index af3307ba4..e3c5308b9 100644
--- a/test/unit/integrations/coinbase/coinbase_return_test.rb
+++ b/test/unit/integrations/coinbase/coinbase_return_test.rb
@@ -23,12 +23,24 @@ def test_invalid_return
assert coinbase_return.success?
end
+ def test_catch_nil_params
+ Net::HTTP.any_instance.expects(:request).returns(stub(:body => http_raw_data_missing_order_key))
+ coinbase_return = Coinbase::Return.new(valid_query_string, @options)
+
+ assert !coinbase_return.notification.acknowledge
+ assert coinbase_return.success?
+ end
+
private
def valid_http_raw_data
'{"order":{"id":"OQJ836AF","created_at":"2014-07-09T07:00:33-07:00","status":"completed","event":{"type":"completed"},"total_btc":{"cents":1463,"currency_iso":"BTC"},"total_native":{"cents":1,"currency_iso":"CAD"},"total_payout":{"cents":0,"currency_iso":"USD"},"custom":"10","receive_address":"19FuVxoEvVLxRibVnmSciNXEsfgFs8W29Z","button":{"type":"buy_now","name":"Shop One - #10","description":null,"id":"0c3e9c6dd38619a2ba11b4561631e6ad"},"refund_address":"1BmmrdqcLqGCtx54vvencNS8VCMsjJCEBA","transaction":{"id":"53bd4b0e86fd2456d8000003","hash":null,"confirmations":0}}}'
end
+ def http_raw_data_missing_order_key
+ JSON.parse(valid_http_raw_data).reject { |key, value| key == 'order' }.to_json
+ end
+
def valid_query_string
'utm_nooverride=1&order%5Bbutton%5D%5Bdescription%5D=&order%5Bbutton%5D%5Bid%5D=0c3e9c6dd38619a2ba11b4561631e6ad&order%5Bbutton%5D%5Bname%5D=Shop+One+-+%2310&order%5Bbutton%5D%5Btype%5D=buy_now&order%5Bcreated_at%5D=2014-07-09+07%3A00%3A33+-0700&order%5Bcustom%5D=10&order%5Bevent%5D=&order%5Bid%5D=OQJ836AF&order%5Breceive_address%5D=19FuVxoEvVLxRibVnmSciNXEsfgFs8W29Z&order%5Brefund_address%5D=1BmmrdqcLqGCtx54vvencNS8VCMsjJCEBA&order%5Bstatus%5D=completed&order%5Btotal_btc%5D%5Bcents%5D=1463&order%5Btotal_btc%5D%5Bcurrency_iso%5D=BTC&order%5Btotal_native%5D%5Bcents%5D=1&order%5Btotal_native%5D%5Bcurrency_iso%5D=CAD&order%5Btotal_payout%5D%5Bcents%5D=0&order%5Btotal_payout%5D%5Bcurrency_iso%5D=USD&order%5Btransaction%5D%5Bconfirmations%5D=0&order%5Btransaction%5D%5Bhash%5D=&order%5Btransaction%5D%5Bid%5D=53bd4b0e86fd2456d8000003'
end
@@ -36,4 +48,5 @@ def valid_query_string
def invalid_query_string
'utm_nooverride=1&order%5Bbutton%5D%5Bdescription%5D=&order%5Bbutton%5D%5Bid%5D=0c3e9c6dd38619a2ba11b4561631e6ad&order%5Bbutton%5D%5Bname%5D=Shop+One+-+%2310&order%5Bbutton%5D%5Btype%5D=buy_now&order%5Bcreated_at%5D=2014-07-09+07%3A00%3A33+-0700&order%5Bcustom%5D=10&order%5Bevent%5D=&order%5Bid%5D=OQJ836AF&order%5Breceive_address%5D=19FuVxoEvVLxRibVnmSciNXEsfgFs8W29Z&order%5Brefund_address%5D=1BmmrdqcLqGCtx54vvencNS8VCMsjJCEBA&order%5Bstatus%5D=failed&order%5Btotal_btc%5D%5Bcents%5D=1463&order%5Btotal_btc%5D%5Bcurrency_iso%5D=BTC&order%5Btotal_native%5D%5Bcents%5D=1&order%5Btotal_native%5D%5Bcurrency_iso%5D=CAD&order%5Btotal_payout%5D%5Bcents%5D=0&order%5Btotal_payout%5D%5Bcurrency_iso%5D=USD&order%5Btransaction%5D%5Bconfirmations%5D=0&order%5Btransaction%5D%5Bhash%5D=&order%5Btransaction%5D%5Bid%5D=53bd4b0e86fd2456d8000003'
end
+
end
diff --git a/test/unit/integrations/direc_pay/direc_pay_notification_test.rb b/test/unit/integrations/direc_pay/direc_pay_notification_test.rb
index eb68a70a4..7a7a91176 100644
--- a/test/unit/integrations/direc_pay/direc_pay_notification_test.rb
+++ b/test/unit/integrations/direc_pay/direc_pay_notification_test.rb
@@ -37,7 +37,7 @@ def test_error
end
def test_compositions
- assert_equal Money.new(100, 'INR'), @direc_pay.amount
+ assert_equal Money.from_amount(1.00, 'INR'), @direc_pay.amount
end
def test_acknowledgement
diff --git a/test/unit/integrations/direc_pay/direc_pay_return_test.rb b/test/unit/integrations/direc_pay/direc_pay_return_test.rb
index d23cf375b..5e6721233 100644
--- a/test/unit/integrations/direc_pay/direc_pay_return_test.rb
+++ b/test/unit/integrations/direc_pay/direc_pay_return_test.rb
@@ -28,7 +28,7 @@ def test_return_has_notification
assert_equal '1001', notification.item_id
assert_equal '1.00', notification.gross
assert_equal 100, notification.gross_cents
- assert_equal Money.new(100, 'INR'), notification.amount
+ assert_equal Money.from_amount(1.00, 'INR'), notification.amount
assert_equal 'INR', notification.currency
assert_equal 'IND', notification.country
assert_equal 'NULL', notification.other_details
diff --git a/test/unit/integrations/directebanking/directebanking_notification_test.rb b/test/unit/integrations/directebanking/directebanking_notification_test.rb
index 94460782f..3c96fe808 100644
--- a/test/unit/integrations/directebanking/directebanking_notification_test.rb
+++ b/test/unit/integrations/directebanking/directebanking_notification_test.rb
@@ -19,7 +19,7 @@ def test_accessors
end
def test_compositions
- assert_equal Money.new(100, 'EUR'), @deb.amount
+ assert_equal Money.from_amount(1.00, 'EUR'), @deb.amount
end
def test_acknowledgement
diff --git a/test/unit/integrations/dotpay/dotpay_notification_test.rb b/test/unit/integrations/dotpay/dotpay_notification_test.rb
index efec044cd..92724a737 100644
--- a/test/unit/integrations/dotpay/dotpay_notification_test.rb
+++ b/test/unit/integrations/dotpay/dotpay_notification_test.rb
@@ -30,7 +30,7 @@ def test_accessors_error
end
def test_compositions
- assert_equal Money.new(15000, 'PLN'), @dotpay.amount
+ assert_equal Money.from_amount(150.00, 'PLN'), @dotpay.amount
end
# Replace with real successful acknowledgement code
diff --git a/test/unit/integrations/dwolla/dwolla_notification_test.rb b/test/unit/integrations/dwolla/dwolla_notification_test.rb
index 6b1a5cb16..a05e47e2e 100644
--- a/test/unit/integrations/dwolla/dwolla_notification_test.rb
+++ b/test/unit/integrations/dwolla/dwolla_notification_test.rb
@@ -28,7 +28,7 @@ def test_error_accessors
end
def test_compositions
- assert_equal Money.new(1, 'USD'), @success.amount
+ assert_equal Money.from_amount(0.01, 'USD'), @success.amount
end
# Replace with real successful acknowledgement code
diff --git a/test/unit/integrations/easy_pay/easy_pay_notification_test.rb b/test/unit/integrations/easy_pay/easy_pay_notification_test.rb
index f9912f44a..578536775 100644
--- a/test/unit/integrations/easy_pay/easy_pay_notification_test.rb
+++ b/test/unit/integrations/easy_pay/easy_pay_notification_test.rb
@@ -14,7 +14,7 @@ def test_accessors
end
def test_compositions
- assert_equal BigDecimal.new("100"), @easypay.amount
+ assert_equal Money.from_amount(BigDecimal.new('100.00'), 'BYR'), @easypay.amount
end
def test_credential2_required
diff --git a/test/unit/integrations/epay/epay_notification_test.rb b/test/unit/integrations/epay/epay_notification_test.rb
index c25774c53..29922a282 100644
--- a/test/unit/integrations/epay/epay_notification_test.rb
+++ b/test/unit/integrations/epay/epay_notification_test.rb
@@ -18,7 +18,7 @@ def test_accessors
end
def test_compositions
- assert_equal Money.new(398750, 'DKK'), @epay.amount
+ assert_equal Money.from_amount(3987.50, 'DKK'), @epay.amount
end
def test_acknowledgement
diff --git a/test/unit/integrations/first_data/first_data_notification_test.rb b/test/unit/integrations/first_data/first_data_notification_test.rb
index 11c6142ae..4e61c6adc 100644
--- a/test/unit/integrations/first_data/first_data_notification_test.rb
+++ b/test/unit/integrations/first_data/first_data_notification_test.rb
@@ -28,7 +28,7 @@ def test_accessors_when_not_set
end
def test_compositions
- assert_equal Money.new(12100, 'USD'), @first_data.amount
+ assert_equal Money.from_amount(121.00, 'USD'), @first_data.amount
end
def test_accessors_when_set
diff --git a/test/unit/integrations/gestpay/gestpay_notification_test.rb b/test/unit/integrations/gestpay/gestpay_notification_test.rb
index 316ce716e..2efb99f56 100644
--- a/test/unit/integrations/gestpay/gestpay_notification_test.rb
+++ b/test/unit/integrations/gestpay/gestpay_notification_test.rb
@@ -13,7 +13,7 @@ def test_successful_notification
assert_equal "1000", notification.item_id
assert_equal "1234.56", notification.gross
assert_equal "EUR", notification.currency
- assert_equal Money.new(123456, 'EUR'), notification.amount
+ assert_equal Money.from_amount(1234.56, 'EUR'), notification.amount
end
def test_failed_notification
diff --git a/test/unit/integrations/hi_trust/hi_trust_helper_test.rb b/test/unit/integrations/hi_trust/hi_trust_helper_test.rb
index 3e5ad5a0b..1c7b40932 100644
--- a/test/unit/integrations/hi_trust/hi_trust_helper_test.rb
+++ b/test/unit/integrations/hi_trust/hi_trust_helper_test.rb
@@ -12,11 +12,5 @@ def test_basic_helper_fields
assert_field 'amount', '500'
assert_field 'ordernumber', 'order-500'
assert_field 'currency', 'USD'
- assert_field 'depositflag', '0'
- end
-
- def test_depositflag_option
- @helper = HiTrust::Helper.new('order-500','cody@example.com', :amount => 500, :currency => 'USD', :deposit_flag => '1')
- assert_field 'depositflag', '1'
end
end
diff --git a/test/unit/integrations/hi_trust/hi_trust_notification_test.rb b/test/unit/integrations/hi_trust/hi_trust_notification_test.rb
index 00d99d873..ab158a67b 100644
--- a/test/unit/integrations/hi_trust/hi_trust_notification_test.rb
+++ b/test/unit/integrations/hi_trust/hi_trust_notification_test.rb
@@ -24,7 +24,7 @@ def test_accessors
end
def test_compositions
- assert_equal Money.new(500, 'USD'), @notification.amount
+ assert_equal Money.from_amount(5.00, 'USD'), @notification.amount
end
def test_send_acknowledgement
diff --git a/test/unit/integrations/ipay88/ipay88_helper_test.rb b/test/unit/integrations/ipay88/ipay88_helper_test.rb
index 8e173570f..5a4ea8dd1 100644
--- a/test/unit/integrations/ipay88/ipay88_helper_test.rb
+++ b/test/unit/integrations/ipay88/ipay88_helper_test.rb
@@ -106,9 +106,9 @@ def test_sig_components_amount_doesnt_include_decimal_points
assert_equal "abcipay88merchcodeorder-5001234MYR", @helper.send(:sig_components)
@helper.amount = 1000
assert_equal "abcipay88merchcodeorder-5001000MYR", @helper.send(:sig_components)
- @helper.amount = Money.new(90)
+ @helper.amount = Money.from_amount(0.90)
assert_equal "abcipay88merchcodeorder-500090MYR", @helper.send(:sig_components)
- @helper.amount = Money.new(1000)
+ @helper.amount = Money.from_amount(10.00)
assert_equal "abcipay88merchcodeorder-5001000MYR", @helper.send(:sig_components)
end
diff --git a/test/unit/integrations/klarna/klarna_helper_test.rb b/test/unit/integrations/klarna/klarna_helper_test.rb
index 2fb140ab6..49d1532c1 100644
--- a/test/unit/integrations/klarna/klarna_helper_test.rb
+++ b/test/unit/integrations/klarna/klarna_helper_test.rb
@@ -7,7 +7,7 @@ def setup
@order_id = 1
@credential1 = "Example Merchant ID"
@options = {
- :amount => Money.new(10.00),
+ :amount => Money.from_amount(0.10),
:currency => 'SEK',
:country => 'SE',
:account_name => 'Example Shop Name',
diff --git a/test/unit/integrations/klarna/klarna_notification_test.rb b/test/unit/integrations/klarna/klarna_notification_test.rb
index f862a9948..f6c880c4b 100644
--- a/test/unit/integrations/klarna/klarna_notification_test.rb
+++ b/test/unit/integrations/klarna/klarna_notification_test.rb
@@ -24,7 +24,7 @@ def test_x2ness_of_gross_amount
end
def test_compositions
- assert_equal Money.new(5000, 'SEK'), @klarna.amount
+ assert_equal Money.from_amount(50.00, 'SEK'), @klarna.amount
end
def test_acknowledge
diff --git a/test/unit/integrations/mollie/mollie_test.rb b/test/unit/integrations/mollie/mollie_test.rb
index 5ae4f8020..1ac308199 100644
--- a/test/unit/integrations/mollie/mollie_test.rb
+++ b/test/unit/integrations/mollie/mollie_test.rb
@@ -4,20 +4,49 @@ class MollieTest < Test::Unit::TestCase
include OffsitePayments::Integrations
def setup
- @token = 'test_8isBjQoJXJoiXRSzjhwKPO1Bo9AkVA'
- JSON.stubs(:parse).returns(CREATE_PAYMENT_RESPONSE_JSON)
+ @api = Mollie::API.new('test_8isBjQoJXJoiXRSzjhwKPO1Bo9AkVA')
+ @api_response = {
+ "id" => "tr_djsfilasX",
+ "mode" => "test",
+ "createdDatetime" => "2014-03-03T10:17:05.0Z",
+ "status" => "open",
+ "amount" => "500.00",
+ "description" => "My order description",
+ "method" => "ideal",
+ "metadata" => {
+ "my_reference" => "unicorn"
+ },
+ "details" => nil,
+ "links" => {
+ "paymentUrl" => "https://www.mollie.com/paymentscreen/mistercash/testmode/ca8195a3dc8d5cbf2f7b130654abe5a5",
+ "redirectUrl" => "https://example.com/return"
+ }
+ }.to_json
end
def test_get_request
- @request = Mollie::API.new(@token).get_request("payments/#{@payment_id}")
- assert_equal 'tr_djsfilasX', @request['id']
- assert_equal '500.00', @request['amount']
- assert_equal 'https://example.com/return', @request['links']['redirectUrl']
+ @api
+ .expects(:ssl_request)
+ .with(
+ :get,
+ 'https://api.mollie.nl/v1/payments/tr_QkwjRvZBzH',
+ nil,
+ {
+ "Authorization" => "Bearer test_8isBjQoJXJoiXRSzjhwKPO1Bo9AkVA",
+ "Content-Type" => "application/json"
+ }
+ )
+ .returns(@api_response)
+
+ response = @api.get_request("payments/tr_QkwjRvZBzH")
+
+ assert_equal 'tr_djsfilasX', response['id']
+ assert_equal '500.00', response['amount']
+ assert_equal 'https://example.com/return', response['links']['redirectUrl']
end
def test_post_request
- @payment_id ='tr_QkwjRvZBzH'
- params = {
+ params = {
:amount => BigDecimal.new('123.45'),
:description => 'My order description',
:redirectUrl => 'https://example.com/return',
@@ -25,29 +54,24 @@ def test_post_request
:issuer => 'ideal_TESTNL99',
:metadata => { :my_reference => 'unicorn' }
}
- @request = Mollie::API.new(@token).post_request('payments', params)
- assert_equal 'tr_djsfilasX', @request['id']
- assert_equal '500.00', @request['amount']
- assert_equal 'https://example.com/return', @request['links']['redirectUrl']
- end
- CREATE_PAYMENT_RESPONSE_JSON = JSON.parse(<<-JSON)
- {
- "id":"tr_djsfilasX",
- "mode":"test",
- "createdDatetime":"2014-03-03T10:17:05.0Z",
- "status":"open",
- "amount":"500.00",
- "description":"My order description",
- "method":"ideal",
- "metadata":{
- "my_reference":"unicorn"
- },
- "details":null,
- "links":{
- "paymentUrl":"https://www.mollie.com/paymentscreen/mistercash/testmode/ca8195a3dc8d5cbf2f7b130654abe5a5",
- "redirectUrl":"https://example.com/return"
- }
- }
- JSON
-end
\ No newline at end of file
+ @api
+ .expects(:ssl_request)
+ .with(
+ :post,
+ 'https://api.mollie.nl/v1/payments',
+ params.to_json,
+ {
+ "Authorization" => "Bearer test_8isBjQoJXJoiXRSzjhwKPO1Bo9AkVA",
+ "Content-Type" => "application/json"
+ }
+ )
+ .returns(@api_response)
+
+
+ response = @api.post_request('payments', params)
+ assert_equal 'tr_djsfilasX', response['id']
+ assert_equal '500.00', response['amount']
+ assert_equal 'https://example.com/return', response['links']['redirectUrl']
+ end
+end
diff --git a/test/unit/integrations/mollie_ideal/mollie_ideal_notification_test.rb b/test/unit/integrations/mollie_ideal/mollie_ideal_notification_test.rb
index 3c0d5b67d..be70b199c 100644
--- a/test/unit/integrations/mollie_ideal/mollie_ideal_notification_test.rb
+++ b/test/unit/integrations/mollie_ideal/mollie_ideal_notification_test.rb
@@ -24,7 +24,7 @@ def test_acknowledgement_sets_params
assert_equal "EUR", @notification.currency
assert_equal 12345, @notification.gross_cents
assert_equal "123.45", @notification.gross
- assert_equal Money.new(12345, 'EUR'), @notification.amount
+ assert_equal Money.from_amount(123.45, 'EUR'), @notification.amount
assert_equal "123", @notification.item_id
end
diff --git a/test/unit/integrations/mollie_mistercash/mollie_mistercash_notification_test.rb b/test/unit/integrations/mollie_mistercash/mollie_mistercash_notification_test.rb
index b1b5df10b..4d36793c1 100644
--- a/test/unit/integrations/mollie_mistercash/mollie_mistercash_notification_test.rb
+++ b/test/unit/integrations/mollie_mistercash/mollie_mistercash_notification_test.rb
@@ -24,7 +24,7 @@ def test_acknowledgement_sets_params
assert_equal "EUR", @notification.currency
assert_equal 12345, @notification.gross_cents
assert_equal "123.45", @notification.gross
- assert_equal Money.new(12345, 'EUR'), @notification.amount
+ assert_equal Money.from_amount(123.45, 'EUR'), @notification.amount
assert_equal "123", @notification.item_id
end
diff --git a/test/unit/integrations/molpay/molpay_helper_test.rb b/test/unit/integrations/molpay/molpay_helper_test.rb
index b6bf261a4..729619dca 100644
--- a/test/unit/integrations/molpay/molpay_helper_test.rb
+++ b/test/unit/integrations/molpay/molpay_helper_test.rb
@@ -36,7 +36,7 @@ def test_product_fields
end
def test_supported_currency
- ['MYR', 'USD', 'SGD', 'PHP', 'VND', 'IDR', 'AUD'].each do |cur|
+ ['MYR', 'USD', 'SGD', 'PHP', 'VND', 'IDR', 'AUD', 'CNY', 'THB', 'GBP', 'EUR', 'HKD'].each do |cur|
@helper.currency cur
assert_field "cur", cur
end
@@ -65,6 +65,11 @@ def test_return_url
@helper.return_url "http://www.example.com"
assert_field "returnurl", "http://www.example.com"
end
+
+ def test_notify_url
+ @helper.notify_url "http://www.example.com"
+ assert_field "callbackurl", "http://www.example.com"
+ end
def test_signature
assert_equal '16d122e1cf4d4fac19f3c839db12b6a5', @helper.form_fields["vcode"]
diff --git a/test/unit/integrations/molpay/molpay_notification_test.rb b/test/unit/integrations/molpay/molpay_notification_test.rb
index 60f0076cf..d1b33b68f 100644
--- a/test/unit/integrations/molpay/molpay_notification_test.rb
+++ b/test/unit/integrations/molpay/molpay_notification_test.rb
@@ -33,11 +33,17 @@ def test_transaction_test
molpay = Molpay::Notification.new(http_raw_data(:test), :credential2 => @secret_key)
assert molpay.test?
end
-
+
def test_acknowledgement
assert @molpay.acknowledge
end
+ def test_result_pending
+ molpay = Molpay::Notification.new("status=22")
+ assert !molpay.complete?
+ assert_equal "Pending", molpay.status
+ end
+
def test_unsuccessful_acknowledge_due_to_signature
molpay = Molpay::Notification.new(http_raw_data(:invalid_skey), :credential2 => @secret_key)
refute molpay.acknowledge
@@ -82,7 +88,6 @@ def http_raw_data(mode=:success)
r = ['amount','appcode','error_code', 'error_desc', 'skey']
basedata.reject{|k| r.include?(k)}.collect {|k,v| "#{k}=#{CGI.escape(v.to_s)}"}.join('&')
end
-
end
def generate_signature
diff --git a/test/unit/integrations/molpay/molpay_return_test.rb b/test/unit/integrations/molpay/molpay_return_test.rb
index 01414c8f5..684f4fb07 100644
--- a/test/unit/integrations/molpay/molpay_return_test.rb
+++ b/test/unit/integrations/molpay/molpay_return_test.rb
@@ -15,11 +15,16 @@ def test_success?
end
def test_failed?
+ Molpay::Notification.any_instance.stubs(:ssl_post).returns('DECLINED')
molpay = Molpay::Return.new('', :credential2 => @secret)
-
refute molpay.success?
end
+ def test_pending?
+ molpay = Molpay::Return.new('status=22', :credential2 => @secret)
+ assert molpay.pending?
+ end
+
private
def query_data
diff --git a/test/unit/integrations/moneybookers/moneybookers_module_test.rb b/test/unit/integrations/moneybookers/moneybookers_module_test.rb
index ccea73b2f..31405de57 100644
--- a/test/unit/integrations/moneybookers/moneybookers_module_test.rb
+++ b/test/unit/integrations/moneybookers/moneybookers_module_test.rb
@@ -8,7 +8,7 @@ def test_notification_method
end
def test_service_url
- url = 'https://www.moneybookers.com/app/payment.pl'
+ url = 'https://pay.skrill.com'
assert_equal url, Moneybookers.service_url
end
end
diff --git a/test/unit/integrations/moneybookers/moneybookers_notification_test.rb b/test/unit/integrations/moneybookers/moneybookers_notification_test.rb
index 0bde6807e..042519b0d 100644
--- a/test/unit/integrations/moneybookers/moneybookers_notification_test.rb
+++ b/test/unit/integrations/moneybookers/moneybookers_notification_test.rb
@@ -20,7 +20,7 @@ def test_accessors
end
def test_compositions
- assert_equal Money.new(3960, 'EUR'), @moneybookers.amount
+ assert_equal Money.from_amount(39.60, 'EUR'), @moneybookers.amount
end
def test_respond_to_acknowledge
diff --git a/test/unit/integrations/nochex/nochex_notification_test.rb b/test/unit/integrations/nochex/nochex_notification_test.rb
index 312eaebca..8df5f2efd 100644
--- a/test/unit/integrations/nochex/nochex_notification_test.rb
+++ b/test/unit/integrations/nochex/nochex_notification_test.rb
@@ -19,7 +19,7 @@ def test_accessors
end
def test_compositions
- assert_equal Money.new(3166, 'GBP'), @nochex.amount
+ assert_equal Money.from_amount(31.66, 'GBP'), @nochex.amount
end
def test_successful_acknowledgement
diff --git a/test/unit/integrations/pag_seguro/pag_seguro_notification_test.rb b/test/unit/integrations/pag_seguro/pag_seguro_notification_test.rb
index 11405d617..decd4dea4 100644
--- a/test/unit/integrations/pag_seguro/pag_seguro_notification_test.rb
+++ b/test/unit/integrations/pag_seguro/pag_seguro_notification_test.rb
@@ -27,7 +27,7 @@ def test_accessors
def test_compositions
Net::HTTP.expects(:get_response).with(@uri).returns(stub(code: "200", body: http_raw_data))
pag_seguro = PagSeguro::Notification.new(notification_data)
- assert_equal Money.new(4912, 'BRL'), pag_seguro.amount
+ assert_equal Money.from_amount(49.12, 'BRL'), pag_seguro.amount
end
def test_respond_to_acknowledge
diff --git a/test/unit/integrations/pay_fast/pay_fast_notification_test.rb b/test/unit/integrations/pay_fast/pay_fast_notification_test.rb
index 7a064c233..7aaf4414c 100644
--- a/test/unit/integrations/pay_fast/pay_fast_notification_test.rb
+++ b/test/unit/integrations/pay_fast/pay_fast_notification_test.rb
@@ -14,8 +14,12 @@ def test_accessors
assert_equal "Name", @pay_fast.item_name
assert_equal "123.00", @pay_fast.gross
assert_equal "-2.80", @pay_fast.fee
- assert_equal "120.20", @pay_fast.amount
assert_equal "10000100", @pay_fast.merchant_id
+ assert_equal "ZAR", @pay_fast.currency
+ end
+
+ def test_compositions
+ assert_equal Money.from_amount(BigDecimal.new('120.20'), 'ZAR'), @pay_fast.amount
end
def test_acknowledgement
diff --git a/test/unit/integrations/paydollar/paydollar_module_test.rb b/test/unit/integrations/paydollar/paydollar_module_test.rb
index ed7a4b55d..61aa2cb1d 100644
--- a/test/unit/integrations/paydollar/paydollar_module_test.rb
+++ b/test/unit/integrations/paydollar/paydollar_module_test.rb
@@ -13,14 +13,14 @@ def test_return_method
def test_production_url
OffsitePayments.mode = :production
- assert_equal 'https://www.paydollar.com/b2c2/eng/payment/payForm.jsp', Paydollar.service_url
+ assert_equal 'https://www.paydollar.com/b2c2/eng/payment/payShopify.jsp', Paydollar.service_url
ensure
OffsitePayments.mode = :test
end
def test_test_url
OffsitePayments.mode = :test
- assert_equal 'https://test.paydollar.com/b2cDemo/eng/payment/payForm.jsp', Paydollar.service_url
+ assert_equal 'https://test.paydollar.com/b2cDemo/eng/payment/payShopify.jsp', Paydollar.service_url
end
def test_currency_map
diff --git a/test/unit/integrations/paydollar/paydollar_notification_test.rb b/test/unit/integrations/paydollar/paydollar_notification_test.rb
index 06c313a75..ef9c285c2 100644
--- a/test/unit/integrations/paydollar/paydollar_notification_test.rb
+++ b/test/unit/integrations/paydollar/paydollar_notification_test.rb
@@ -18,7 +18,7 @@ def test_accessors
end
def test_compositions
- assert_equal Money.new(13962, 'HKD'), @paydollar.amount
+ assert_equal Money.from_amount(139.62, 'HKD'), @paydollar.amount
end
def test_acknowledgement
diff --git a/test/unit/integrations/paypal/paypal_notification_test.rb b/test/unit/integrations/paypal/paypal_notification_test.rb
index ca07c44dc..e5f62b45a 100644
--- a/test/unit/integrations/paypal/paypal_notification_test.rb
+++ b/test/unit/integrations/paypal/paypal_notification_test.rb
@@ -57,7 +57,7 @@ def test_mass_pay_accessors
end
def test_compositions
- assert_equal Money.new(50000, 'CAD'), @paypal.amount
+ assert_equal Money.from_amount(500.00, 'CAD'), @paypal.amount
end
def test_acknowledgement
diff --git a/test/unit/integrations/paytm/paytm_helper_test.rb b/test/unit/integrations/paytm/paytm_helper_test.rb
new file mode 100644
index 000000000..18b5f1db9
--- /dev/null
+++ b/test/unit/integrations/paytm/paytm_helper_test.rb
@@ -0,0 +1,27 @@
+require 'test_helper'
+
+class RemotePaytmTest < Test::Unit::TestCase
+ include OffsitePayments::Integrations
+
+ def setup
+ @paytm = Paytm::Notification.new(http_raw_data, credential1: 'WorldP64425807474247', credential2: 'kbzk1DSbJiV_O3p5', credential3: 'Retail', credential4: 'worldpressplg')
+ end
+
+ def test_raw
+ OffsitePayments.mode = :production
+ assert_equal 'https://secure.paytm.in/oltp-web/processTransaction', Paytm.service_url
+
+ OffsitePayments.mode = :test
+ assert_equal 'https://pguat.paytm.com/oltp-web/processTransaction', Paytm.service_url
+
+ assert_nothing_raised do
+ assert @paytm.checksum_ok?
+ end
+ end
+
+ private
+
+ def http_raw_data
+ 'MID=WorldP64425807474247&ORDERID=100PT012&TXNAMOUNT=10&CURRENCY=INR&TXNID=494157&BANKTXNID=201512236592678&STATUS=TXN_SUCCESS&RESPCODE=01&RESPMSG=Txn Successful&TXNDATE=2015-12-23 16:06:22.0&GATEWAYNAME=ICICI&BANKNAME=ICICI&PAYMENTMODE=CC&MERC_UNQ_REF=100PT012&CHECKSUMHASH=M9E4OLugj4L3TLLiof2BSO03hhQQLMucnVgtYuHi4wIVLB20dCXS632PRw0dTmnAa58R0kEuh9+V3bfQs4F/SrlmsmV+hvhb3Nui1zlnh/o='
+ end
+end
diff --git a/test/unit/integrations/paytm/paytm_module_test.rb b/test/unit/integrations/paytm/paytm_module_test.rb
new file mode 100644
index 000000000..eb015eba2
--- /dev/null
+++ b/test/unit/integrations/paytm/paytm_module_test.rb
@@ -0,0 +1,50 @@
+require 'test_helper'
+
+class PaytmModuleTest < Test::Unit::TestCase
+ include OffsitePayments::Integrations
+
+ def setup
+ OffsitePayments.mode = :test
+ @merchant_id = 'WorldP64425807474247'
+ @secret_key = 'kbzk1DSbJiV_O3p5'
+ @industry_type_id = 'Retail'
+ @website = 'worldpressplg'
+ end
+
+ def test_service_url_method
+ OffsitePayments.mode = :test
+ assert_equal 'https://pguat.paytm.com/oltp-web/processTransaction', Paytm.service_url
+
+ OffsitePayments.mode = :production
+ assert_equal 'https://secure.paytm.in/oltp-web/processTransaction', Paytm.service_url
+ ensure
+ OffsitePayments.mode = :test
+ end
+
+ def test_return_method
+ assert_instance_of Paytm::Return, Paytm.return('name=foo', {})
+ end
+
+ def test_notification_method
+ assert_instance_of Paytm::Notification, Paytm.notification('name=foo', {})
+ end
+
+ def test_checksum_method
+ paytm_load = { 'MID' => @merchant_id, 'ORDER_ID' => '100PT012', 'CUST_ID' => 'test@example.com', 'TXN_AMOUNT' => '10', 'CHANNEL_ID' => 'WEB', 'INDUSTRY_TYPE_ID' => @industry_type_id, 'WEBSITE' => @website, 'MERC_UNQ_REF' => '100PT012', 'CALLBACK_URL' => 'http://www.shopify.com/paytmRes' }
+
+ salt = '1234'
+ values = paytm_load.sort.to_h.values
+ values << salt
+ check_sum = Digest::SHA256.hexdigest(values.join('|')) + salt
+ ### encrypting checksum ###
+ aes = OpenSSL::Cipher::AES.new('128-CBC')
+ aes.encrypt
+ aes.key = @secret_key
+ aes.iv = '@@@@&&&###$$$$'
+
+ encrypted_data = aes.update(check_sum.to_s) + aes.final
+ checksum = Base64.strict_encode64(encrypted_data)
+
+ assert_equal checksum, Paytm.encrypt(Paytm.checksum(paytm_load, '1234'), @secret_key)
+ end
+end
diff --git a/test/unit/integrations/paytm/paytm_notification_test.rb b/test/unit/integrations/paytm/paytm_notification_test.rb
new file mode 100644
index 000000000..064792960
--- /dev/null
+++ b/test/unit/integrations/paytm/paytm_notification_test.rb
@@ -0,0 +1,39 @@
+require 'test_helper'
+
+class PaytmNotificationTest < Test::Unit::TestCase
+ include OffsitePayments::Integrations
+
+ def setup
+ @paytm = Paytm::Notification.new(http_raw_data, credential1: 'WorldP64425807474247', credential2: 'kbzk1DSbJiV_O3p5', credential3: 'Retail', credential4: 'worldpressplg')
+ end
+
+ def test_accessors
+ assert @paytm.complete?
+ assert_equal 'Completed', @paytm.status
+ assert_equal '494157', @paytm.transaction_id
+ assert_equal 'TXN_SUCCESS', @paytm.transaction_status
+ assert_equal '10.00', @paytm.gross
+ assert_equal 'INR', @paytm.currency
+ assert_equal true, @paytm.invoice_ok?('100PT012')
+ assert_equal true, @paytm.amount_ok?(BigDecimal.new('10.00'))
+ assert_equal 'CC', @paytm.type
+ assert_equal '100PT012', @paytm.invoice
+ assert_equal 'WorldP64425807474247', @paytm.account
+ assert_equal 'M9E4OLugj4L3TLLiof2BSO03hhQQLMucnVgtYuHi4wIVLB20dCXS632PRw0dTmnAa58R0kEuh9+V3bfQs4F/SrlmsmV+hvhb3Nui1zlnh/o=', @paytm.checksum
+ assert_equal true, @paytm.checksum_ok?
+ end
+
+ def test_compositions
+ assert_equal '10.00', @paytm.gross
+ end
+
+ def test_acknowledgement
+ assert @paytm.acknowledge
+ end
+
+ private
+
+ def http_raw_data
+ 'MID=WorldP64425807474247&ORDERID=100PT012&TXNAMOUNT=10&CURRENCY=INR&TXNID=494157&BANKTXNID=201512236592678&STATUS=TXN_SUCCESS&RESPCODE=01&RESPMSG=Txn Successful&TXNDATE=2015-12-23 16:06:22.0&GATEWAYNAME=ICICI&BANKNAME=ICICI&PAYMENTMODE=CC&MERC_UNQ_REF=100PT012&CHECKSUMHASH=M9E4OLugj4L3TLLiof2BSO03hhQQLMucnVgtYuHi4wIVLB20dCXS632PRw0dTmnAa58R0kEuh9%2bV3bfQs4F/SrlmsmV%2bhvhb3Nui1zlnh/o='
+ end
+end
diff --git a/test/unit/integrations/paytm/paytm_return_test.rb b/test/unit/integrations/paytm/paytm_return_test.rb
new file mode 100644
index 000000000..222e20e18
--- /dev/null
+++ b/test/unit/integrations/paytm/paytm_return_test.rb
@@ -0,0 +1,60 @@
+require 'test_helper'
+
+class PaytmReturnTest < Test::Unit::TestCase
+ include OffsitePayments::Integrations
+
+ def setup
+ @paytm = Paytm::Return.new(http_raw_data_success, credential1: 'WorldP64425807474247', credential2: 'kbzk1DSbJiV_O3p5', credential3: 'Retail', credential4: 'worldpressplg')
+ end
+
+ def setup_failed_return
+ @paytm = Paytm::Return.new(http_raw_data_failure, credential1: 'WorldP64425807474247', credential2: 'kbzk1DSbJiV_O3p5', credential3: 'Retail', credential4: 'worldpressplg')
+ end
+
+ def test_success
+ assert @paytm.success?
+ assert_equal 'Completed', @paytm.status('100PT012', '10')
+ end
+
+ def test_failure_is_successful
+ setup_failed_return
+ assert_equal 'Failed', @paytm.status('100PT012', '10')
+ end
+
+ def test_treat_initial_failures_as_pending
+ setup_failed_return
+ assert_equal 'Failed', @paytm.notification.status
+ end
+
+ def test_return_has_notification
+ notification = @paytm.notification
+
+ assert notification.complete?
+ assert_equal 'Completed', notification.status
+ assert notification.invoice_ok?('100PT012')
+ assert notification.amount_ok?(BigDecimal.new('10.00'))
+ assert_equal 'TXN_SUCCESS', notification.transaction_status
+ assert_equal '494157', @paytm.notification.transaction_id
+ assert_equal 'CC', @paytm.notification.type
+ assert_equal 'INR', notification.currency
+ assert_equal '100PT012', notification.invoice
+ assert_equal 'WorldP64425807474247', notification.account
+ assert_equal '10.00', notification.gross
+ assert_equal 'M9E4OLugj4L3TLLiof2BSO03hhQQLMucnVgtYuHi4wIVLB20dCXS632PRw0dTmnAa58R0kEuh9+V3bfQs4F/SrlmsmV+hvhb3Nui1zlnh/o=', notification.checksum
+ assert notification.checksum_ok?
+ end
+
+ private
+
+ def http_raw_data_success
+ 'MID=WorldP64425807474247&ORDERID=100PT012&TXNAMOUNT=10&CURRENCY=INR&TXNID=494157&BANKTXNID=201512236592678&STATUS=TXN_SUCCESS&RESPCODE=01&RESPMSG=Txn+Successful&TXNDATE=2015-12-23 16:06:22.0&GATEWAYNAME=ICICI&BANKNAME=ICICI&PAYMENTMODE=CC&MERC_UNQ_REF=100PT012&CHECKSUMHASH=M9E4OLugj4L3TLLiof2BSO03hhQQLMucnVgtYuHi4wIVLB20dCXS632PRw0dTmnAa58R0kEuh9%2bV3bfQs4F/SrlmsmV%2bhvhb3Nui1zlnh/o='
+ end
+
+ def http_raw_data_failure
+ 'MID=WorldP64425807474247&ORDERID=100PT012&TXNAMOUNT=10&CURRENCY=INR&TXNID=494157&BANKTXNID=201512236592678&TXNDATE=2015-12-23 16:06:22.0&GATEWAYNAME=ICICI&BANKNAME=ICICI&PAYMENTMODE=CC&MERC_UNQ_REF=100PT012&STATUS=TXN_FAILURE&RESPCODE=330&RESPMSG=Invalid+Checksum&CHECKSUMHASH=x6FmPuyiHDCZ4dI4ffflLEDhngj8zuf6CVgrkpZEkmxfLw22coNvru8H1xZztSKUQeF7qsnR5aC/O36m%2bam6sDLXN9eqSdl7%2bNhe8kp9qFs='
+ end
+
+ def checksum
+ 'M9E4OLugj4L3TLLiof2BSO03hhQQLMucnVgtYuHi4wIVLB20dCXS632PRw0dTmnAa58R0kEuh9%2bV3bfQs4F/SrlmsmV%2bhvhb3Nui1zlnh/o='
+ end
+end
diff --git a/test/unit/integrations/payu_in/payu_in_helper_test.rb b/test/unit/integrations/payu_in/payu_in_helper_test.rb
index 478dd3128..84812a86e 100644
--- a/test/unit/integrations/payu_in/payu_in_helper_test.rb
+++ b/test/unit/integrations/payu_in/payu_in_helper_test.rb
@@ -28,7 +28,7 @@ def test_billing_address_fields
assert_equal '666, Wooo', @helper.fields['address1']
assert_equal 'EEE Street', @helper.fields['address2']
assert_equal 'New Delhi', @helper.fields['state']
- assert_equal '110001', @helper.fields['zip']
+ assert_equal '110001', @helper.fields['zipcode']
assert_equal 'india', @helper.fields['country']
end
@@ -71,4 +71,8 @@ def test_sanitize_fields_in_form_fields
assert_nil @helper.fields['email']
end
+ def test_phone_replace_non_digits
+ @helper.fields['phone'] = '+(999)-99 99999'
+ assert_equal '9999999999', @helper.form_fields['phone']
+ end
end
diff --git a/test/unit/integrations/payu_in_paisa/payu_in_paisa_helper_test.rb b/test/unit/integrations/payu_in_paisa/payu_in_paisa_helper_test.rb
index 905c75f9d..e6b3c4385 100644
--- a/test/unit/integrations/payu_in_paisa/payu_in_paisa_helper_test.rb
+++ b/test/unit/integrations/payu_in_paisa/payu_in_paisa_helper_test.rb
@@ -28,7 +28,7 @@ def test_billing_address_fields
assert_equal '666, Wooo', @helper.fields['address1']
assert_equal 'EEE Street', @helper.fields['address2']
assert_equal 'New Delhi', @helper.fields['state']
- assert_equal '110001', @helper.fields['zip']
+ assert_equal '110001', @helper.fields['zipcode']
assert_equal 'india', @helper.fields['country']
end
diff --git a/test/unit/integrations/platron/platron_notification_test.rb b/test/unit/integrations/platron/platron_notification_test.rb
index 46a5cbf20..768d6cd8d 100644
--- a/test/unit/integrations/platron/platron_notification_test.rb
+++ b/test/unit/integrations/platron/platron_notification_test.rb
@@ -16,7 +16,10 @@ def test_accessors
assert_equal '1', @correct_notification.complete?
assert_equal 'Visa', @correct_notification.payment_system
assert_equal 'VI', @correct_notification.card_brand
- assert_equal '990',@correct_notification.amount
+ end
+
+ def test_compositions
+ assert_equal Money.from_amount(990, 'USD'), @correct_notification.amount
end
def test_acknowledgement
diff --git a/test/unit/integrations/quickpay/quickpay_notification_test.rb b/test/unit/integrations/quickpay/quickpay_notification_test.rb
index f6ab855bc..2b2ce0196 100644
--- a/test/unit/integrations/quickpay/quickpay_notification_test.rb
+++ b/test/unit/integrations/quickpay/quickpay_notification_test.rb
@@ -18,7 +18,7 @@ def test_accessors
end
def test_compositions
- assert_equal Money.new(123, 'DKK'), @quickpay.amount
+ assert_equal Money.from_amount(1.23, 'DKK'), @quickpay.amount
end
def test_acknowledgement
diff --git a/test/unit/integrations/realex_offsite/realex_offsite_helper_test.rb b/test/unit/integrations/realex_offsite/realex_offsite_helper_test.rb
index 624413f03..ff5e3d1ee 100644
--- a/test/unit/integrations/realex_offsite/realex_offsite_helper_test.rb
+++ b/test/unit/integrations/realex_offsite/realex_offsite_helper_test.rb
@@ -67,11 +67,18 @@ def test_shipping_address
end
def test_format_amount_as_float
- amount_gbp = @helper.format_amount_as_float(999, 'GBP')
- assert_in_delta amount_gbp, 9.99, 0.00
+ amount_gbp = @helper.format_amount_as_float(929, 'GBP')
+ assert_in_delta amount_gbp, 9.29, 0.00
- amount_bhd = @helper.format_amount_as_float(999, 'BHD')
- assert_in_delta amount_bhd, 0.999, 0.00
+ amount_bhd = @helper.format_amount_as_float(929, 'BHD')
+ assert_in_delta amount_bhd, 0.929, 0.00
end
+ def test_format_amount
+ amount_gbp = @helper.format_amount('9.29', 'GBP')
+ assert_equal amount_gbp, 929
+
+ amount_bhd = @helper.format_amount(0.929, 'BHD')
+ assert_equal amount_bhd, 929
+ end
end
diff --git a/test/unit/integrations/realex_offsite/realex_offsite_notification_test.rb b/test/unit/integrations/realex_offsite/realex_offsite_notification_test.rb
index 917b88732..314b15c74 100644
--- a/test/unit/integrations/realex_offsite/realex_offsite_notification_test.rb
+++ b/test/unit/integrations/realex_offsite/realex_offsite_notification_test.rb
@@ -21,7 +21,7 @@ def test_accessors
end
def test_compositions
- assert_equal Money.new(5000, 'USD'), @notification.amount
+ assert_equal Money.from_amount(50.00, 'USD'), @notification.amount
end
def test_test_mode
diff --git a/test/unit/integrations/robokassa/robokassa_notification_test.rb b/test/unit/integrations/robokassa/robokassa_notification_test.rb
index 1b62fd865..b0d49854a 100644
--- a/test/unit/integrations/robokassa/robokassa_notification_test.rb
+++ b/test/unit/integrations/robokassa/robokassa_notification_test.rb
@@ -14,7 +14,7 @@ def test_accessors
end
def test_compositions
- assert_equal Money.new(50000, 'USD'), @robokassa.amount
+ assert_equal Money.from_amount(500.00, 'RUB'), @robokassa.amount
end
# Replace with real successful acknowledgement code
diff --git a/test/unit/integrations/sage_pay_form/sage_pay_form_helper_test.rb b/test/unit/integrations/sage_pay_form/sage_pay_form_helper_test.rb
index 18755d454..c90c2e24f 100644
--- a/test/unit/integrations/sage_pay_form/sage_pay_form_helper_test.rb
+++ b/test/unit/integrations/sage_pay_form/sage_pay_form_helper_test.rb
@@ -24,7 +24,11 @@ def test_basic_helper_fields
assert_equal 5, @helper.fields.size
assert_field 'Vendor', 'cody@example.com'
assert_field 'Amount', '5.00'
- assert_field 'VendorTxCode', 'order-500'
+ assert_field 'VendorTxCode', "order-500-#{@helper.identifier}"
+ end
+
+ def test_identifier_should_only_contain_digits
+ assert_match /^[0-9]*$/, @helper.identifier
end
def test_customer_fields
@@ -264,6 +268,20 @@ def test_do_not_send_referrer_id_by_default
assert_false @helper.fields['ReferrerID']
end
+ def test_form_fields_does_not_contain_locale
+ @helper.add_field(:locale, 'en')
+
+ refute @helper.form_fields.key?('locale')
+ end
+
+ def test_encrypted_fields_do_not_contain_locale
+ @helper.add_field(:locale, 'en')
+
+ with_crypt_plaintext do |plain|
+ refute plain.include?('locale')
+ end
+ end
+
private
def with_crypt_plaintext
diff --git a/test/unit/integrations/sage_pay_form/sage_pay_form_notification_test.rb b/test/unit/integrations/sage_pay_form/sage_pay_form_notification_test.rb
index 9c6a8eac3..6422f041e 100644
--- a/test/unit/integrations/sage_pay_form/sage_pay_form_notification_test.rb
+++ b/test/unit/integrations/sage_pay_form/sage_pay_form_notification_test.rb
@@ -2,6 +2,7 @@
class SagePayFormNotificationTest < Test::Unit::TestCase
include OffsitePayments::Integrations
+ include OffsitePayments::Integrations::SagePayForm::Encryption
def setup
@options = {:credential2 => 'EncryptionKey123'}
@@ -15,7 +16,7 @@ def test_successful_purchase
assert_equal 'Completed', n.status
assert_equal 'OK', n.status_code
assert_equal 'Successfully Authorised Transaction', n.message
- assert_equal '28', n.item_id
+ assert_equal 'order-28', n.item_id
assert_equal '{2D370B0B-692D-4D07-B616-91B86CCDF85A}', n.transaction_id
assert_equal '7349', n.auth_id
assert_equal '1231.47', n.gross
@@ -44,7 +45,7 @@ def test_failed_purchase
assert_equal 'Failed', n.status
assert_equal 'NOTAUTHED', n.status_code
assert_equal 'NOTAUTHED message generated by Simulator', n.message
- assert_equal '28', n.item_id
+ assert_equal 'order-28', n.item_id
assert_equal '{2D370B0B-692D-4D07-B616-91B86CCDF85A}', n.transaction_id
assert_equal '31.47', n.gross
assert_equal 'ALL MATCH', n.avs_cv2_result
@@ -73,7 +74,7 @@ def test_cancelled_purchase
assert_equal 'Failed', n.status
assert_equal 'ABORT', n.status_code
assert_equal 'ABORT message generated by Simulator', n.message
- assert_equal '5', n.item_id
+ assert_equal 'order-5', n.item_id
assert_equal '{90A42BA2-1281-4CA9-8E84-E43C0E7FD85F}', n.transaction_id
assert_equal '148.99', n.gross
assert_equal 'ALL MATCH', n.avs_cv2_result
@@ -96,7 +97,7 @@ def test_cancelled_purchase
def test_compositions
n = SagePayForm::Notification.new(successful_purchase, @options)
- assert_equal Money.new(123147, nil), n.amount
+ assert_equal Money.from_amount(1231.47), n.amount
end
def test_bogus_crypt
@@ -120,14 +121,30 @@ def test_missing_key
private
def successful_purchase
- 'utm_nooverride=1&crypt=@BE1F6226E7478FACFA239E0F882B10E7BAE1149909C1F8D163038E623A188E693C6CFC594A49D5BB257E2CBBA58D3436A6FED00FCD7268FB9D0978CEEE3086A8B25F92FF65F059886A07BFE7E228AA965F44B9018AD73612BA2FFDFD3A2A468B88E4E77D81252B3F28173E9DCD5559D5A89937BBB88AE8FE358FE89974FC4761172694ADEAD7671F07BCECB3552F285F78C30F8DF830494429777F91B58344FDE411794FD64F215EC8ED395FB621958D4241EA41B08C7F5FDC3302C8B75BC92E55FABA6126CE1B27E9B1A01CD6F03BF99051D67A0829E2AF3C22E6159D2D5551D499A3677C695E50C3000EFFDA15102987BFF0329BEB8FED280D343723C47EF2A4475835AABBE1980560356E3D9F0F84562E8739EAC4E859F72E4FBEBB5C3830099E2908B433318FD1B3905244AD5CAB4CE8120D33D39391CF4E9F0E4CC9C62B'
+ encrypt_params(raw_successful_purchase)
end
def failed_purchase
- 'utm_nooverride=1&crypt=@A60BFC79F8FAA1C02E548AD3D3D2EC888C6FF1DA74889EB45D6ED7D680CC45087A449B3E3E8727AA90AC451C0B3AC0D61F3761F3269EFEA8276DF568905DA1EFB19EE7526DA4EDC894C29A1D1D92831C22C1BC0614B86C6C6262ED29F5E8178BD80C1D9389A4B7A78305A625D49522E19C6D623C28CF34D9F87E4607F2D361894B344037120F745BC267E055762D7BD642847647FA98E6573245AFD125C2212319499D7C332893DF2E9EB085C6F58D7FD34665AC5365F46FEE276E3D17615C3FA97ACB335045BF79B6F2F612FED564587EC52CBAA558D910209ACD88E5859F6EA0FD4FC7160CD4D68E3E6B8894737708AB212A2E33CE22EB245E117AFCE6F7B29A51E903BE9209E6EA8E3C9C543F85F4A9F3109A464A0BE85FE7706BC24F7F257BE9C2D54FE46E3B382F726B53E9876D292ACB76931AA2ACD0EED18766D2D142'
+ encrypt_params(raw_failed_purchase)
end
def cancelled_purchase
- 'utm_nooverride=1&crypt=@F2039156479BC99C3448EB6CDAAD52E1746785AAB0B7477467FD9F4F84AC52EC981DA7105EAE3FA281648ADA29F2E2874A0B49C5D35159CB1B191A0FF1CEF68F4C1D06BDE7AAEC9356585210B013872790D12172726FFBD443E0F31925275DA6BCBAA198349D79828DE210088D1621E512272B4D325B35B12FFF931CBDE601E47F8F21FE7F0E9CE20069CB156AAB61C595D97190EBEEA1160524A0E557360C3C606909C0B01F0FEA252489AB873299DD427F21AAA14304886219E4AD16E2A288A16063CC058543619D7B80F283595B9AD3DBF9D27DB4E4631900AFDECABC45D899D5A12689104B6B76C1F119939D26BD4160074A46517A97194C8C3C882D901F28417FA5CE3BBC9B11D220E0CCE4E07BB3EDE72ECEEF7B5EA1E56EA3C1EE77F37479A226A9A1ADB91B0F4AC405C94F37CACA147939FC317FA0BE799140B149B7'
+ encrypt_params(raw_cancelled_purchase)
+ end
+
+ def encrypt_params(raw)
+ "utm_nooverride=1&crypt=#{sage_encrypt(raw, @options[:credential2])}"
+ end
+
+ def raw_successful_purchase
+ "Status=OK&StatusDetail=Successfully Authorised Transaction&VendorTxCode=order-28-1234&VPSTxId={2D370B0B-692D-4D07-B616-91B86CCDF85A}&TxAuthNo=7349&Amount=1,231.47&AVSCV2=ALL MATCH&AddressResult=MATCHED&PostCodeResult=MATCHED&CV2Result=MATCHED&GiftAid=0&3DSecureStatus=OK&CAVV=MNG8ZAJDJRUKW90GGYZNTH&CardType=VISA&Last4Digits=8356"
+ end
+
+ def raw_failed_purchase
+ "Status=NOTAUTHED&StatusDetail=NOTAUTHED message generated by Simulator&VendorTxCode=order-28-1234&VPSTxId={2D370B0B-692D-4D07-B616-91B86CCDF85A}&Amount=31.47&AVSCV2=ALL MATCH&AddressResult=MATCHED&PostCodeResult=MATCHED&CV2Result=MATCHED&GiftAid=0&3DSecureStatus=OK&CAVV=MNVJYYXXHMCNH0BOTBT97Z&CardType=VISA&Last4Digits=4353"
+ end
+
+ def raw_cancelled_purchase
+ "Status=ABORT&StatusDetail=ABORT message generated by Simulator&VendorTxCode=order-5-1234&VPSTxId={90A42BA2-1281-4CA9-8E84-E43C0E7FD85F}&Amount=148.99&AVSCV2=ALL MATCH&AddressResult=MATCHED&PostCodeResult=MATCHED&CV2Result=MATCHED&GiftAid=0&3DSecureStatus=OK&CAVV=MNJ8W58FNX1Q5OAV4TZKW2&CardType=VISA&Last4Digits=6425"
end
end
diff --git a/test/unit/integrations/two_checkout/two_checkout_notification_test.rb b/test/unit/integrations/two_checkout/two_checkout_notification_test.rb
index 7c4420868..7c474f6ed 100644
--- a/test/unit/integrations/two_checkout/two_checkout_notification_test.rb
+++ b/test/unit/integrations/two_checkout/two_checkout_notification_test.rb
@@ -21,7 +21,7 @@ def test_accessors
end
def test_compositions
- assert_equal Money.new(20, 'USD'), @live_notification.amount
+ assert_equal Money.from_amount(0.20, 'USD'), @live_notification.amount
end
def test_acknowledgement
diff --git a/test/unit/integrations/universal/universal_helper_test.rb b/test/unit/integrations/universal/universal_helper_test.rb
index 8fb7b9803..45bd759d1 100644
--- a/test/unit/integrations/universal/universal_helper_test.rb
+++ b/test/unit/integrations/universal/universal_helper_test.rb
@@ -34,8 +34,6 @@ def test_credential_based_url
end
def test_core_fields
- @helper.shipping 6.78
- @helper.tax 0
@helper.description 'Box of Red Wine'
@helper.invoice 'Invoice #1A'
@@ -44,8 +42,6 @@ def test_core_fields
assert_field 'x_credential4', @credential4
assert_field 'x_currency', @currency
assert_field 'x_amount', '123.45'
- assert_field 'x_amount_shipping', '6.78'
- assert_field 'x_amount_tax', '0.00'
assert_field 'x_reference', @order
assert_field 'x_shop_country', @country
assert_field 'x_shop_name', @account_name
@@ -67,13 +63,9 @@ def test_empty_credential_field_not_present_in_request
def test_special_currency_formatting
@options[:currency] = 'COU'
@helper = Universal::Helper.new(@order, @account, @options)
- @helper.shipping 6.78
- @helper.tax 0
assert_field 'x_currency', 'COU'
assert_field 'x_amount', '123.4500'
- assert_field 'x_amount_shipping', '6.7800'
- assert_field 'x_amount_tax', '0.0000'
end
def test_customer_fields
@@ -112,6 +104,30 @@ def test_shipping_address_fields
assert_field 'x_customer_shipping_phone', '(416) 123-4567'
end
+ def test_billing_address_fields
+ @helper.billing_address :first_name => 'John',
+ :last_name => 'Doe',
+ :city => 'Toronto',
+ :company => 'Shopify Toronto',
+ :address1 => '241 Spadina Ave',
+ :address2 => 'Front Entrance',
+ :state => 'ON',
+ :zip => 'M5T 3A8',
+ :country => 'CA',
+ :phone => '(416) 123-4567'
+
+ assert_field 'x_customer_billing_first_name', 'John'
+ assert_field 'x_customer_billing_last_name', 'Doe'
+ assert_field 'x_customer_billing_city', 'Toronto'
+ assert_field 'x_customer_billing_company', 'Shopify Toronto'
+ assert_field 'x_customer_billing_address1', '241 Spadina Ave'
+ assert_field 'x_customer_billing_address2', 'Front Entrance'
+ assert_field 'x_customer_billing_state', 'ON'
+ assert_field 'x_customer_billing_zip', 'M5T 3A8'
+ assert_field 'x_customer_billing_country', 'CA'
+ assert_field 'x_customer_billing_phone', '(416) 123-4567'
+ end
+
def test_url_fields
@helper.notify_url 'https://zork.com/notify'
@helper.return_url 'https://zork.com/return'
@@ -129,6 +145,18 @@ def test_signature
assert_field 'x_signature', expected_signature
end
+ def test_signature_only_uses_fields_that_start_with_x_
+ expected_signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new, @key, 'x_account_idzorkx_amount123.45x_credential3123456789x_credential4abcdefghijkx_currencyUSDx_referenceorder-500x_shop_countryUSx_shop_nameWidgets Incx_testfalsex_transaction_typesale')
+ @helper.sign_fields
+
+ assert_field 'x_signature', expected_signature
+
+ @helper.add_field('should_not_be_used_in_signature', 'value')
+ @helper.sign_fields
+
+ assert_field 'x_signature', expected_signature
+ end
+
def test_signature_when_some_credentials_are_not_defined
@options[:credential3] = ''
@options[:credential4] = ''
diff --git a/test/unit/integrations/universal/universal_notification_test.rb b/test/unit/integrations/universal/universal_notification_test.rb
index f7a18c63c..c1a124594 100644
--- a/test/unit/integrations/universal/universal_notification_test.rb
+++ b/test/unit/integrations/universal/universal_notification_test.rb
@@ -14,11 +14,12 @@ def test_accessors
assert_equal '123.45', @notification.gross
assert_equal 'blorb123', @notification.transaction_id
assert_equal 'Completed', @notification.status
+ assert_equal 'helloworld', @notification.message
assert @notification.test?
end
def test_compositions
- assert_equal Money.new(12345, 'USD'), @notification.amount
+ assert_equal Money.from_amount(123.45, 'USD'), @notification.amount
end
def test_acknowledge_valid_signature
@@ -46,7 +47,7 @@ def test_acknowledge_invalid_signature
private
def http_raw_data
- 'x_account_id=zork&x_reference=order-500&x_currency=USD&x_test=true&x_amount=123.45&x_gateway_reference=blorb123&x_timestamp=2014-03-24T12:15:41Z&x_result=completed&x_signature=d8797220f2f0ccef90c1ee80e82494cd709fb10ab1f50a016578208c3fb5a0c1'
+ 'x_account_id=zork&x_reference=order-500&x_currency=USD&x_test=true&x_amount=123.45&x_gateway_reference=blorb123&x_timestamp=2014-03-24T12:15:41Z&x_result=completed&x_signature=82b635305a18e3e614c473ab4dce900a7c00db79bd68525e565a29ff69218f37&x_message=helloworld'
end
def http_raw_data_extra_parameter
diff --git a/test/unit/integrations/universal/universal_return_test.rb b/test/unit/integrations/universal/universal_return_test.rb
index 189dbc743..c01813666 100644
--- a/test/unit/integrations/universal/universal_return_test.rb
+++ b/test/unit/integrations/universal/universal_return_test.rb
@@ -23,9 +23,13 @@ def test_success_after_acknowledge
assert @return.success?
end
+ def test_return_message
+ assert_equal 'helloworld', @return.message
+ end
+
private
def query_data
- 'x_account_id=zork&x_reference=order-500&x_currency=USD&x_test=true&x_amount=123.45&x_gateway_reference=blorb123&x_timestamp=2014-03-24T12:15:41Z&x_result=success&x_signature=4365fef32f5309845052b728c8cbe962e583ecaf62bf1cdec91f248162b7f65e'
+ 'x_account_id=zork&x_reference=order-500&x_currency=USD&x_test=true&x_amount=123.45&x_gateway_reference=blorb123&x_timestamp=2014-03-24T12:15:41Z&x_result=success&x_signature=55bd5acfabe65041568a94cb8981489ebced1f1eceebe0b985c8db43f3fedf91&x_message=helloworld'
end
end
diff --git a/test/unit/integrations/web_pay/web_pay_notification_test.rb b/test/unit/integrations/web_pay/web_pay_notification_test.rb
index 09b79d0e7..72edad896 100644
--- a/test/unit/integrations/web_pay/web_pay_notification_test.rb
+++ b/test/unit/integrations/web_pay/web_pay_notification_test.rb
@@ -14,7 +14,7 @@ def test_accessors
end
def test_compositions
- assert_equal BigDecimal.new("500"), @web_pay.amount
+ assert_equal Money.from_amount(500, 'BYR'), @web_pay.amount
end
def test_respond_to_acknowledge
diff --git a/test/unit/integrations/webmoney/webmoney_notification_test.rb b/test/unit/integrations/webmoney/webmoney_notification_test.rb
index 24590eaf5..50ac21f27 100644
--- a/test/unit/integrations/webmoney/webmoney_notification_test.rb
+++ b/test/unit/integrations/webmoney/webmoney_notification_test.rb
@@ -10,7 +10,10 @@ def setup
def test_accessors
assert_equal "1.00", @webmoney.gross
assert_equal "123", @webmoney.item_id
- assert_equal BigDecimal.new("1"), @webmoney.amount
+ end
+
+ def test_compositions
+ assert_equal Money.from_amount(1.00, 'RUB'), @webmoney.amount
end
def test_acknowledgement
diff --git a/test/unit/integrations/world_pay/world_pay_helper_test.rb b/test/unit/integrations/world_pay/world_pay_helper_test.rb
index 4102d4916..6a70993c5 100644
--- a/test/unit/integrations/world_pay/world_pay_helper_test.rb
+++ b/test/unit/integrations/world_pay/world_pay_helper_test.rb
@@ -33,7 +33,10 @@ def test_address_mapping
:zip => 'CV1 1AA',
:country => 'GB'
- assert_field 'address', '1 Nowhere Close
Electric Wharf
Coventry
Warwickshire'
+ assert_field 'address1', '1 Nowhere Close'
+ assert_field 'address2', 'Electric Wharf'
+ assert_field 'town', 'Coventry'
+ assert_field 'region', 'Warwickshire'
assert_field 'postcode', 'CV1 1AA'
assert_field 'country', 'GB'
end
@@ -44,7 +47,8 @@ def test_address_mapping_without_address1_and_state
:zip => '10000',
:country => 'DE'
- assert_field 'address', 'Teststr. 1
Berlin'
+ assert_field 'address1', 'Teststr. 1'
+ assert_field 'town', 'Berlin'
assert_field 'postcode', '10000'
assert_field 'country', 'DE'
end
diff --git a/test/unit/integrations/world_pay/world_pay_notification_test.rb b/test/unit/integrations/world_pay/world_pay_notification_test.rb
index 4d0df109e..14652bdb6 100644
--- a/test/unit/integrations/world_pay/world_pay_notification_test.rb
+++ b/test/unit/integrations/world_pay/world_pay_notification_test.rb
@@ -19,7 +19,7 @@ def test_accessors
end
def test_compositions
- assert_equal Money.new(500, 'GBP'), @world_pay.amount
+ assert_equal Money.from_amount(5.00, 'GBP'), @world_pay.amount
end
def test_extra_accessors
@@ -66,7 +66,7 @@ def test_custom_parameters
end
def test_valid_sender
- OffsitePayments.mode = :production
+ OffsitePayments.mode = :production
assert @world_pay.valid_sender?('195.35.90.0')
assert @world_pay.valid_sender?('195.35.90.11')
assert @world_pay.valid_sender?('195.35.91.255')
diff --git a/test/unit/return_test.rb b/test/unit/return_test.rb
index 0c4741b44..2e8588a7a 100644
--- a/test/unit/return_test.rb
+++ b/test/unit/return_test.rb
@@ -7,4 +7,17 @@ def test_return
r = Return.new('')
assert r.success?
end
+
+ def test_parse
+ r = Return.new('')
+ assert r.parse('account=test').is_a?(Hash)
+ end
+
+ def test_parse_with_bad_query
+ r = Return.new('')
+ assert r.parse('&account=test').is_a?(Hash)
+ assert r.parse('key1=value1&key2&key3=value3').is_a?(Hash)
+ assert r.parse('foooo=value1&=value&key3=value3').is_a?(Hash)
+ assert r.parse('key1=value1&&key3=value3').is_a?(Hash)
+ end
end