Skip to content

Commit

Permalink
Add Payflow Link support
Browse files Browse the repository at this point in the history
  • Loading branch information
John Duff committed Aug 9, 2011
1 parent 1457518 commit 2a6e4e1
Show file tree
Hide file tree
Showing 5 changed files with 301 additions and 0 deletions.
21 changes: 21 additions & 0 deletions lib/active_merchant/billing/integrations/payflow_link.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module ActiveMerchant #:nodoc:
module Billing #:nodoc:
module Integrations #:nodoc:
module PayflowLink
autoload :Helper, 'active_merchant/billing/integrations/payflow_link/helper.rb'
autoload :Notification, 'active_merchant/billing/integrations/payflow_link/notification.rb'

mattr_accessor :service_url
self.service_url = 'https://payflowlink.paypal.com'

def self.notification(post, options = {})
Notification.new(post)
end

def self.return(query_string, options = {})
ActiveMerchant::Billing::Integrations::Return.new(query_string)
end
end
end
end
end
58 changes: 58 additions & 0 deletions lib/active_merchant/billing/integrations/payflow_link/helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
module ActiveMerchant #:nodoc:
module Billing #:nodoc:
module Integrations #:nodoc:
module PayflowLink
class Helper < ActiveMerchant::Billing::Integrations::Helper

def initialize(order, account, options = {})
super
add_field('login', account)
add_field('type', 'S')
add_field('echodata', 'True')
add_field('user2', ActiveMerchant::Billing::Base.integration_mode == :test || options[:test])
add_field('invoice', order)
end

mapping :amount, 'amount'
mapping :account, 'login'
mapping :credential2, 'partner'
mapping :order, 'user1'
mapping :description, 'description'


mapping :billing_address, :city => 'city',
:address => 'address',
:state => 'state',
:zip => 'zip',
:country => 'country',
:phone => 'phone',
:name => 'name'

mapping :customer, :name => 'name'

def customer(params = {})
add_field(mappings[:customer][:name], [params.delete(:first_name), params.delete(:last_name)].compact.join(' '))
end

def billing_address(params = {})
# Get the country code in the correct format
# Use what we were given if we can't find anything
country_code = lookup_country_code(params.delete(:country))
add_field(mappings[:billing_address][:country], country_code)

add_field(mappings[:billing_address][:address], [params.delete(:address1), params.delete(:address2)].compact.join(' '))

province_code = params.delete(:state)
add_field(mappings[:billing_address][:state], province_code.blank? ? 'N/A' : province_code.upcase)

# Everything else
params.each do |k, v|
field = mappings[:billing_address][k]
add_field(field, v) unless field.nil?
end
end
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
require 'net/http'

module ActiveMerchant #:nodoc:
module Billing #:nodoc:
module Integrations #:nodoc:
module PayflowLink
class Notification < ActiveMerchant::Billing::Integrations::Notification

# Was the transaction complete?
def complete?
status == "Completed"
end

# When was this payment received by the client.
# sometimes it can happen that we get the notification much later.
# One possible scenario is that our web application was down. In this case paypal tries several
# times an hour to inform us about the notification
def received_at
DateTime.parse(params['TRANSTIME']) if params['TRANSTIME']
rescue ArgumentError
nil
end

def status
params['RESPMSG']
end

# Id of this transaction (paypal number)
def transaction_id
params['PNREF']
end

# What type of transaction are we dealing with?
def type
params['TYPE']
end

# the money amount we received in X.2 decimal.
def gross
params['AMT']
end

# What currency have we been dealing with
def currency
nil
end

def status
params['RESULT'] == '0' ? 'Completed' : 'Failed'
end

# This is the item number which we submitted to paypal
def item_id
params['USER1']
end

# This is the invoice which you passed to paypal
def invoice
params['INVNUM']
end

# Was this a test transaction?
def test?
params['USER2'] == 'true'
end

def account
params["ACCT"]
end

def acknowledge
true
end
end
end
end
end
end
83 changes: 83 additions & 0 deletions test/unit/integrations/helpers/payflow_link_helper_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
require 'test_helper'

class PayflowLinkHelperTest < Test::Unit::TestCase
include ActiveMerchant::Billing::Integrations

def setup
@helper = PayflowLink::Helper.new(1121,'loginname', :amount => 500, :currency => 'CAD', :credential2 => 'PayPal')
@url = 'http://example.com'
end

def test_basic_helper_fields
assert_field 'login', 'loginname'
assert_field 'partner', 'PayPal'
assert_field 'amount', '500'
assert_field 'type', 'S'
assert_field 'user1', '1121'
assert_field 'invoice', '1121'
end

def test_description
@helper.description = "my order"
assert_field 'description', 'my order'
end

def test_name
@helper.customer :first_name => "John", :last_name => "Doe"

assert_field 'name', 'John Doe'
end

def test_billing_information
@helper.billing_address :country => 'CA',
:address1 => '1 My Street',
:address2 => 'APT. 2',
:city => 'Ottawa',
:state => 'ON',
:zip => '90210',
:phone => '(555)123-4567'

assert_field 'address', '1 My Street APT. 2'
assert_field 'city', 'Ottawa'
assert_field 'state', 'ON'
assert_field 'zip', '90210'
assert_field 'country', 'CA'
assert_field 'phone', '(555)123-4567'
end

def test_province
@helper.billing_address :country => 'CA',
:state => 'On'

assert_field 'country', 'CA'
assert_field 'state', 'ON'
end

def test_state
@helper.billing_address :country => 'US',
:state => 'TX'

assert_field 'country', 'US'
assert_field 'state', 'TX'
end

def test_country_code
@helper.billing_address :country => 'CAN'
assert_field 'country', 'CA'
end

def test_setting_invalid_address_field
fields = @helper.fields.dup
fields["state"] = 'N/A'

@helper.billing_address :street => 'My Street'
assert_equal fields, @helper.fields
end

def test_uk_shipping_address_with_no_state
@helper.billing_address :country => 'GB',
:state => ''

assert_field 'state', 'N/A'
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
require 'test_helper'

class PayflowLinkNotificationTest < Test::Unit::TestCase
include ActiveMerchant::Billing::Integrations

def setup
@payflow = ActiveMerchant::Billing::Integrations::PayflowLink.notification(http_raw_data)
end

def test_accessors
assert @payflow.complete?
assert_equal "Completed", @payflow.status
assert_equal "V24A0C03E977", @payflow.transaction_id
assert_equal "S", @payflow.type
assert_equal "21.30", @payflow.gross
assert_equal "20" , @payflow.item_id
assert_equal "1111" , @payflow.account
assert_equal "2011-08-03T10:05:41+00:00", @payflow.received_at.to_s
assert @payflow.test?
end

def test_payment_successful_status
notification = PayflowLink::Notification.new('RESULT=0')
assert_equal 'Completed', notification.status
end

def test_missing_transittime
notification = PayflowLink::Notification.new('')
assert_nil notification.received_at
end

def test_invalid_transittime
notification = PayflowLink::Notification.new('TRANSTIME=magic')
assert_nil notification.received_at
end

def test_payment_failure_status
notification = PayflowLink::Notification.new('RESULT=7')
assert_equal 'Failed', notification.status
end

def test_respond_to_acknowledge
assert @payflow.respond_to?(:acknowledge)
end

def test_item_id_mapping
notification = PayflowLink::Notification.new('USER1=1')
assert_equal '1', notification.item_id
end

def test_invoice_mapping
notification = PayflowLink::Notification.new('INVNUM=1')
assert_equal '1', notification.invoice
end

private

def http_raw_data
"AVSZIP=Y&STATE=ON&TYPE=S&USER4=&ZIPTOSHIP=&ACCT=1111&EMAIL=&EMAILTOSHIP=&ADDRESSTOSHIP=&METHOD=CC&TRANSTIME=2011-08-03+10%3A05%3A41&USER8=&USER5=&IAVS=N&STATETOSHIP=&USER3=&PHONETOSHIP=&USER7=&TAX=&CARDTYPE=1&AVSDATA=YYY&CITYTOSHIP=&USER6=&PROCAVS=Y&INVNUM=&CITY=Ottawa&USER1=20&DESCRIPTION=Shop+One+store+purchase.+Order+1008&HOSTCODE=A&RESULT=0&USER10=&USER2=true&FAX=&PONUM=&LASTNAME=Doe&PNREF=V24A0C03E977&PHONE=6132623672&AMT=21.30&NAMETOSHIP=&ZIP=K1p4l2&AUTHCODE=026PNI&EXPDATE=0522&RESPMSG=Approved&COUNTRY=&CUSTID=&ORIGMETHOD=&FIRSTNAME=John&USER9=&FAXTOSHIP=&AVSADDR=Y&NAME=John+Doe+&COUNTRYTOSHIP=&ADDRESS=43+Somewhere+Street+"
end
end

0 comments on commit 2a6e4e1

Please sign in to comment.