require 'spec_helper'
ActiveMerchant::Billing::Base.mode = :test
shared_examples 'common_specs' do
before(:each) do
create_payment
end
after(:each) do
@plugin.stop_plugin
end
it 'should be able to purchase' do
Killbill::Orbital::OrbitalResponse.all.size.should == 1
Killbill::Orbital::OrbitalTransaction.all.size.should == 0
payment_response = @plugin.purchase_payment(@pm.kb_account_id, @kb_payment.id, @kb_payment.transactions[0].id, @pm.kb_payment_method_id, @amount, @currency, @properties, @call_context)
payment_response.status.should eq(:PROCESSED), payment_response.gateway_error
payment_response.amount.should == @amount
payment_response.transaction_type.should == :PURCHASE
responses = Killbill::Orbital::OrbitalResponse.all
responses.size.should == 2
responses[0].api_call.should == 'add_payment_method'
responses[0].message.should == 'Profile Request Processed'
responses[1].api_call.should == 'purchase'
responses[1].message.should == 'Approved'
transactions = Killbill::Orbital::OrbitalTransaction.all
transactions.size.should == 1
transactions[0].api_call.should == 'purchase'
end
it 'should be able to charge and refund' do
payment_response = @plugin.purchase_payment(@pm.kb_account_id, @kb_payment.id, @kb_payment.transactions[0].id, @pm.kb_payment_method_id, @amount, @currency, @properties, @call_context)
payment_response.status.should eq(:PROCESSED), payment_response.gateway_error
payment_response.amount.should == @amount
payment_response.transaction_type.should == :PURCHASE
# Try a full refund
refund_response = @plugin.refund_payment(@pm.kb_account_id, @kb_payment.id, @kb_payment.transactions[1].id, @pm.kb_payment_method_id, @amount, @currency, @properties, @call_context)
refund_response.status.should eq(:PROCESSED), refund_response.gateway_error
refund_response.amount.should == @amount
refund_response.transaction_type.should == :REFUND
end
it 'should be able to auth, capture and refund' do
payment_response = @plugin.authorize_payment(@pm.kb_account_id, @kb_payment.id, @kb_payment.transactions[0].id, @pm.kb_payment_method_id, @amount, @currency, @properties, @call_context)
payment_response.status.should eq(:PROCESSED), payment_response.gateway_error
payment_response.amount.should == @amount
payment_response.transaction_type.should == :AUTHORIZE
# Try multiple partial captures
partial_capture_amount = BigDecimal.new('10')
1.upto(3) do |i|
payment_response = @plugin.capture_payment(@pm.kb_account_id, @kb_payment.id, @kb_payment.transactions[i].id, @pm.kb_payment_method_id, partial_capture_amount, @currency, @properties, @call_context)
payment_response.status.should eq(:PROCESSED), payment_response.gateway_error
payment_response.amount.should == partial_capture_amount
payment_response.transaction_type.should == :CAPTURE
end
# Try a partial refund
refund_response = @plugin.refund_payment(@pm.kb_account_id, @kb_payment.id, @kb_payment.transactions[4].id, @pm.kb_payment_method_id, partial_capture_amount, @currency, @properties, @call_context)
refund_response.status.should eq(:PROCESSED), refund_response.gateway_error
refund_response.amount.should == partial_capture_amount
refund_response.transaction_type.should == :REFUND
# Try to capture again
payment_response = @plugin.capture_payment(@pm.kb_account_id, @kb_payment.id, @kb_payment.transactions[5].id, @pm.kb_payment_method_id, partial_capture_amount, @currency, @properties, @call_context)
payment_response.status.should eq(:PROCESSED), payment_response.gateway_error
payment_response.amount.should == partial_capture_amount
payment_response.transaction_type.should == :CAPTURE
end
it 'should be able to auth and void' do
payment_response = @plugin.authorize_payment(@pm.kb_account_id, @kb_payment.id, @kb_payment.transactions[0].id, @pm.kb_payment_method_id, @amount, @currency, @properties, @call_context)
payment_response.status.should eq(:PROCESSED), payment_response.gateway_error
payment_response.amount.should == @amount
payment_response.transaction_type.should == :AUTHORIZE
payment_response = @plugin.void_payment(@pm.kb_account_id, @kb_payment.id, @kb_payment.transactions[1].id, @pm.kb_payment_method_id, @properties, @call_context)
payment_response.status.should eq(:PROCESSED), payment_response.gateway_error
payment_response.transaction_type.should == :VOID
end
it 'should be able to auth, partial capture and void' do
payment_response = @plugin.authorize_payment(@pm.kb_account_id, @kb_payment.id, @kb_payment.transactions[0].id, @pm.kb_payment_method_id, @amount, @currency, @properties, @call_context)
payment_response.status.should eq(:PROCESSED), payment_response.gateway_error
payment_response.amount.should == @amount
payment_response.transaction_type.should == :AUTHORIZE
partial_capture_amount = BigDecimal.new('10')
payment_response = @plugin.capture_payment(@pm.kb_account_id, @kb_payment.id, @kb_payment.transactions[1].id, @pm.kb_payment_method_id, partial_capture_amount, @currency, @properties, @call_context)
payment_response.status.should eq(:PROCESSED), payment_response.gateway_error
payment_response.amount.should == partial_capture_amount
payment_response.transaction_type.should == :CAPTURE
payment_response = @plugin.void_payment(@pm.kb_account_id, @kb_payment.id, @kb_payment.transactions[2].id, @pm.kb_payment_method_id, @properties, @call_context)
payment_response.status.should eq(:PROCESSED), payment_response.gateway_error
payment_response.transaction_type.should == :VOID
end
end
shared_examples 'cvv_indicator_specs' do
after(:each) do
@plugin.stop_plugin
end
it 'should set correct indicator for visa and discover if cvv value is present regardless of cvv_indicator_visa_discover' do
validate_cvv_indicator_field 1
@properties = build_pm_properties(nil, { :cc_number => '5454545454545454', :cc_type => 'discover' })
validate_cvv_indicator_field 1
@properties = build_pm_properties(nil, { :cc_number => '5454545454545454', :cvv_indicator_visa_discover => true })
validate_cvv_indicator_field 1
@properties = build_pm_properties(nil, { :cc_number => '5454545454545454', :cc_type => 'discover', :cvv_indicator_visa_discover => true })
validate_cvv_indicator_field 1
end
it 'should set correct indicator for visa and discover if cvv value is not present and cvv_indicator_visa_discover is true' do
@properties = build_pm_properties(nil, { :cc_number => '5454545454545454', :cvv_indicator_visa_discover => true })
@properties.reject! {|property| property.key == 'ccVerificationValue' }
validate_cvv_indicator_field 9
@properties = build_pm_properties(nil, { :cc_number => '5454545454545454', :cc_type => 'discover', :cvv_indicator_visa_discover => true })
@properties.reject! {|property| property.key == 'ccVerificationValue' }
validate_cvv_indicator_field 9
end
it 'should set customized indicator for visa and discover if cvv value is not present and cvv_indicator_visa_discover is true and cvv_indicator_override_visa_discover is given' do
@properties = build_pm_properties(nil, { :cc_number => '5454545454545454', :cvv_indicator_visa_discover => true, :cvv_indicator_override_visa_discover => '2' })
@properties.reject! {|property| property.key == 'ccVerificationValue' }
validate_cvv_indicator_field 2
@properties = build_pm_properties(nil, { :cc_number => '5454545454545454', :cc_type => 'discover', :cvv_indicator_visa_discover => true, :cvv_indicator_override_visa_discover => '2' })
@properties.reject! {|property| property.key == 'ccVerificationValue' }
validate_cvv_indicator_field 2
end
it 'should set correct indicator for visa and discover if cvv value is not present and cvv_indicator_visa_discover is nil or false' do
@properties = build_pm_properties(nil, { :cc_number => '5454545454545454'})
@properties.reject! {|property| property.key == 'ccVerificationValue' }
validate_cvv_indicator_field
@properties = build_pm_properties(nil, { :cc_number => '5454545454545454', :cc_type => 'discover'})
@properties.reject! {|property| property.key == 'ccVerificationValue' }
validate_cvv_indicator_field
@properties = build_pm_properties(nil, { :cc_number => '5454545454545454', :cvv_indicator_visa_discover => false })
@properties.reject! {|property| property.key == 'ccVerificationValue' }
validate_cvv_indicator_field
@properties = build_pm_properties(nil, { :cc_number => '5454545454545454', :cc_type => 'discover', :cvv_indicator_visa_discover => false })
@properties.reject! {|property| property.key == 'ccVerificationValue' }
validate_cvv_indicator_field
end
it 'should not include indicator except visa and discover for all cases' do
@properties = build_pm_properties(nil, { :cc_number => '5454545454545454', :cc_type => 'master' })
validate_cvv_indicator_field
@properties = build_pm_properties(nil, { :cc_number => '5454545454545454', :cc_type => 'american_express' })
validate_cvv_indicator_field
@properties = build_pm_properties(nil, { :cc_number => '5454545454545454', :cc_type => 'master', :cvv_indicator_visa_discover => false })
validate_cvv_indicator_field
@properties = build_pm_properties(nil, { :cc_number => '5454545454545454', :cc_type => 'american_express', :cvv_indicator_visa_discover => false })
validate_cvv_indicator_field
@properties = build_pm_properties(nil, { :cc_number => '5454545454545454', :cc_type => 'master', :cvv_indicator_visa_discover => true})
validate_cvv_indicator_field
@properties = build_pm_properties(nil, { :cc_number => '5454545454545454', :cc_type => 'american_express', :cvv_indicator_visa_discover => true })
validate_cvv_indicator_field
@properties = build_pm_properties(nil, { :cc_number => '5454545454545454', :cc_type => 'master' })
@properties.reject! {|property| property.key == 'ccVerificationValue' }
validate_cvv_indicator_field
@properties = build_pm_properties(nil, { :cc_number => '5454545454545454', :cc_type => 'american_express' })
@properties.reject! {|property| property.key == 'ccVerificationValue' }
validate_cvv_indicator_field
@properties = build_pm_properties(nil, { :cc_number => '5454545454545454', :cc_type => 'master', :cvv_indicator_visa_discover => false})
@properties.reject! {|property| property.key == 'ccVerificationValue' }
validate_cvv_indicator_field
@properties = build_pm_properties(nil, { :cc_number => '5454545454545454', :cc_type => 'american_express', :cvv_indicator_visa_discover => false })
@properties.reject! {|property| property.key == 'ccVerificationValue' }
validate_cvv_indicator_field
@properties = build_pm_properties(nil, { :cc_number => '5454545454545454', :cc_type => 'master', :cvv_indicator_visa_discover => true})
@properties.reject! {|property| property.key == 'ccVerificationValue' }
validate_cvv_indicator_field
@properties = build_pm_properties(nil, { :cc_number => '5454545454545454', :cc_type => 'american_express', :cvv_indicator_visa_discover => true })
@properties.reject! {|property| property.key == 'ccVerificationValue' }
validate_cvv_indicator_field
end
end
describe Killbill::Orbital::PaymentPlugin do
include ::Killbill::Plugin::ActiveMerchant::RSpec
before(:each) do
# Start the plugin early to configure ActiveRecord
@plugin = build_plugin(::Killbill::Orbital::PaymentPlugin, 'orbital')
@plugin.start_plugin
::Killbill::Orbital::OrbitalPaymentMethod.delete_all
::Killbill::Orbital::OrbitalResponse.delete_all
::Killbill::Orbital::OrbitalTransaction.delete_all
@call_context = build_call_context
end
context 'credit card flow' do
before(:each) do
@properties = build_pm_properties(nil, { :cc_number => '5454545454545454' })
@pm = create_payment_method(::Killbill::Orbital::OrbitalPaymentMethod, nil, @call_context.tenant_id, @properties, {})
@amount = BigDecimal.new('100')
@currency = 'USD'
end
include_examples 'common_specs'
end
context 'custom profile flow' do
before(:each) do
@properties = []
@pm = create_payment_method(::Killbill::Orbital::OrbitalPaymentMethod, nil, @call_context.tenant_id, @properties, { :cc_number => '5454545454545454' })
@amount = BigDecimal.new('100')
@currency = 'USD'
end
include_examples 'common_specs'
end
context 'cvv indicator spec' do
before(:each) do
@properties = build_pm_properties(nil, { :cc_number => '5454545454545454' })
@pm = create_payment_method(::Killbill::Orbital::OrbitalPaymentMethod, nil, @call_context.tenant_id, @properties, {})
@amount = BigDecimal.new('100')
@currency = 'USD'
end
include_examples 'cvv_indicator_specs'
end
def successful_authorize_response
<<-XML
A1111111001CCXXXXXXXXXXXX54545b257b31-1f84-44bc-b325834AA75E4466AEA59512165057C37DD810053C200100B tst424Approved100I3 152837
XML
end
def successful_purchase_response
<<-XML
AC1111111001CCXXXXXXXXXXXX545488132d30-f4f7-4028-9495834EAC9C7A53FEB600A479629FB6C6427A2532C101003 Itst703Approved100 I200306 XML
XML
end
def validate_cvv_indicator_field(expected_field = nil)
::ActiveMerchant::Billing::OrbitalGateway.any_instance.stub(:ssl_post) do |host, request_body|
if expected_field.nil?
request_body.should_not match('')
else
request_body.should match("#{expected_field}")
end
if request_body.include? 'A'
successful_authorize_response
else
successful_purchase_response
end
end
create_payment
payment_response = @plugin.authorize_payment(@pm.kb_account_id, @kb_payment.id, @kb_payment.transactions[0].id, @pm.kb_payment_method_id, @amount, @currency, @properties, @call_context)
payment_response.status.should eq(:PROCESSED), payment_response.gateway_error
payment_response.amount.should == @amount
payment_response.transaction_type.should == :AUTHORIZE
create_payment
payment_response = @plugin.purchase_payment(@pm.kb_account_id, @kb_payment.id, @kb_payment.transactions[0].id, @pm.kb_payment_method_id, @amount, @currency, @properties, @call_context)
payment_response.status.should eq(:PROCESSED), payment_response.gateway_error
payment_response.amount.should == @amount
payment_response.transaction_type.should == :PURCHASE
end
def create_payment
kb_payment_id = SecureRandom.uuid
1.upto(6) do
@kb_payment = @plugin.kb_apis.proxied_services[:payment_api].add_payment(kb_payment_id)
end
kb_payment_id
end
end