[bop-devel] Proposed - Barclaycard EPDQextra Plus API Direct Link Integration
Simon Waters
simonw at zynet.net
Wed Jan 23 07:15:24 PST 2013
Okay, my first stab - which works with my test scripts for "Normal
Authorization" only.
Basically:
1) It multiplies "amount" by 100 (or sets to invalid)
2) Remaps fields
3) Ensure the SHA hash parameter is created correctly
4) Parses the response codes
Otherwise it is fairly vanilla HTTPS
Heavily based on TCLink.pm
Currently the test server is "hardwired", and I haven't tried
implementing any of the authentication only responses.
I've mostly answered my own questions.
Things I know now.....
Yes I should use Business::OnlinePayment::HTTPS
get_fields and remap_fields methods are in OnlinePayment.pm now - it was
in the copy of TCLink.pm I worked from, but that one needs bringing up
to speed as well. So I should just be able to delete these.
I still don't know the preferred format for expiration date in the caller.
This provider wants a "customer name" but BOP seems to offer both "name"
and "first_name" "last_name. I suspect it can be safely left to
implementers.
Wouldn't recommend anyone else uses the code yet, on the other hand it
may save someone a little time if they are using BOP already.
I've no idea how to do the error handling. Fortunately most things that
don't make sense already fail in "required fields" or fail at
Barclaycard end and thus get a suitable error back.
EPDQ also has optional ECI field for whether card is present etc. I've
ignored it for the moment, although some transactions failed with "CVC
is required" which makes me think that I may need to set it to 9 for
some types of request we do.
Any constructive criticism or advice welcome.
Simon
Business::OnlinePayment::EPDQPLUS.pm
package Business::OnlinePayment::EPDQPLUS;
use base qw( Business::OnlinePayment::HTTPS );
use strict;
use warnings;
use Business::OnlinePayment::HTTPS;
use URI::Escape qw/uri_escape/;
use Digest::SHA qw/sha1_base64/;
use XML::Simple;
use vars qw($VERSION $DEBUG);
$VERSION = '0.01';
$DEBUG=1;
sub set_defaults {
my $self = shift;
$self->server('mdepayments.epdq.co.uk') unless $self->server; #
Test server - live is "payments.epdq.co.uk"
$self->port('443') unless $self->port;
$self->path('/ncol/test/orderdirect.asp') unless $self->path; #
Test server - live is "/ncol/prod/orderdirect.asp
}
sub map_fields {
my($self) = @_;
my %content = $self->content();
my %actions = ('normal authorization' => 'SAL', # Only one implemented
'authorization only' => 'RES', # from Barclays
docs 4.3.3
'credit' => 'RFD', # from Barclays
docs 4.3.3
);
$content{'action'} = $actions{lc($content{'action'} || '')} ||
$content{'action'};
my $amount = $content{'amount'};
if ( $amount =~ /-?\d*\.\d\d/ ) { # Match a number with two decimal
places
$content{'amount'} = int(100*$amount);
} else {
$content{'amount'}='invalid amount';
}
$self->content(%content);
}
sub remap_fields {
my($self,%map) = @_;
my %content = $self->content();
foreach(keys %map) {
$content{$map{$_}} = $content{$_};
}
$self->content(%content);
}
sub get_fields {
my($self, at fields) = @_;
my %content = $self->content();
my %new = ();
foreach( grep defined $content{$_}, @fields) { $new{$_} =
$content{$_}; }
return %new;
}
sub submit {
my($self) = @_;
$self->map_fields();
$self->remap_fields(
# type => '',
pspid => 'PSPID',
login => 'USERID',
password => 'PSWD',
shasign => 'SHASIGN',
action => 'OPERATION',
description => 'COM',
name => 'CN',
amount => 'AMOUNT', # Note Barclays expect this in
cents or pence thus $13.23 is transformed to 1323 and £142.00 is 14200
currency => 'CURRENCY', # USD GBP EUR other - must
have Multi-currency store with Barclays
order_number => 'ORDERID',
customer_ip => 'REMOTE_ADDR',
address => 'OWNERADDRESS',
city => 'OWNERTOWN',
zip => 'OWNERZIP',
country => 'OWNERCTY', # As ISO country code GB, US, etc
ship_last_name => 'ECOM_SHIPTO_POSTAL_NAME_LAST', # SHIPTO
fields not yet tested
ship_first_name => 'ECOM_SHIPTO_POSTAL_NAME_FIRST',
ship_company => 'ECOM_SHIPTO_COMPANY',
ship_address => 'ECOM_SHIPTO_POSTAL_STREET_LINE1',
ship_city => 'ECOM_SHIPTO_POSTAL_CITY',
ship_zip => 'ECOM_SHIPTO_POSTAL_POSTCODE',
ship_country => 'ECOM_SHIPTO_POSTAL_COUNTRYCODE', # ISO
country code GB, US, etc
phone => 'OWNERTELNO',
email_customer => 'EMAIL',
card_number => 'CARDNO',
expiration => 'ED',
cvv2 => 'CVC',
);
my @required_fields = ( qw(pspid login password shasign action
amount currency card_number expiration) );
$self->required_fields(@required_fields);
my %post_data = $self->get_fields(qw/
PSPID USERID PSWD
OPERATION COM CN AMOUNT CURRENCY ORDERID CARDNO ED CVC
REMOTE_ADDR
OWNERADDRESS OWNERTOWN OWNERZIP OWNERCTY OWNERTELNO EMAIL
ECOM_SHIPTO_POSTAL_NAME_LAST ECOM_SHIPTO_POSTAL_NAME_FIRST
ECOM_SHIPTO_COMPANYi
ECOM_SHIPTO_POSTAL_STREET_LINE1 ECOM_SHIPTO_POSTAL_CITY
ECOM_SHIPTO_POSTAL_POSTCODE ECOM_SHIPTO_POSTAL_COUNTRYCODE
/);
# Compute a suitable SHA1 sum for the transaction.
my $SHATEXT;
my %content = $self->content();
foreach my $key (sort keys %post_data) {
$SHATEXT.=$key."=".$post_data{$key}.$content{'SHASIGN'};
}
my $SHAHASH= sha1_base64($SHATEXT);
print "SHA TEXT IS $SHATEXT\n" if $DEBUG;
print "Hash is $SHAHASH\n" if $DEBUG;
$post_data{'SHASIGN'}=$SHAHASH;
my $opt = {};
my($page, $server_response, %headers) =
$self->https_post( $opt, \%post_data );
$self->server_response($page);
$self->response_headers(%headers);
#??? IF SUCCEEDED
my $result = XMLin($page);
#print Dumper($result);
#print "Result is: ",$result->{STATUS},"\n";
#print "Error is: ",$result->{NCERROR},"\n";
#print "Error message is: ",$result->{NCERRORPLUS},"\n";
my $status=$result->{STATUS};
my $ncerror=$result->{NCERROR};
if ( $status eq 9 and $ncerror eq 0 ){
$self->is_success(1);
$self->result_code($result->{ACCEPTANCE});
$self->authorization($result->{PAYID});
} else {
$self->is_success(0);
$self->result_code($result->{ACCEPTANCE});
$self->error_message("Failed: Status: $status, Error: $ncerror,
Message:".$result->{NCERRORPLUS});
}
}
1;
__END__
=head1 NAME
Business::OnlinePayment::EPDQPLUS - Barclaycard EPDQplus API Direct Link
Dev version - not released
=head1 DESCRIPTION
This module provides access to the Barclaycard EPDQplus Direct Link API
and documented in v4.3.3 of the
Barclay Integration guide.
It is currently a work in progress.
To use/test this module you will need:
PSPID - Barclaycard supplied credential
"admin" user for the api with password (login and password) in the
Barclaycard backend as per the online help.
SHA signing secret defined for API access (strictly this is optional
the Barclaycard interface by the module assumed you will use it)
Currently implemented - "Normal Authorization" (Operation "SAL").
=head USAGE
use Business::OnlinePayment;
my $tx = Business::OnlinePayment->new("EPDQPLUS");
$tx->content(
pspid => 'see above',
login => 'added via Barclaycard Backoffice',
password => 'set via Barclaycard Backoffice'
shasign => 'set via Barclaycard Backoffice',
action => 'Normal Authorization',
description => '20 English Roses',
amount => '49.95',
currency => 'USD',
order_number => 'ORDER0001',
name => 'B Obama',
address => 'Whitehouse, 1600 Pennsylvannia Road',
city => 'Washington DC',
zip => 'DC 20500',
country => 'US',
phone => '',
card_number => '5569510117486571',
expiration => '0515', # MMYY is a Barclay card format -- what
does BOP expect
cvv2 => '377',
);
$tx->submit();
print "server_response = ", $tx->server_response, "\n";
print "is_success = ", $tx->is_success, "\n";
print "authorization = ", $tx->authorization, "\n";
print "error_message = ", $tx->error_message, "\n\n";
print "result_code = ", $tx->result_code, "\n";
=head1 AUTHOR
Simon Waters <simonw at zynet.net>
Derived from code by Jason Kohles and Ivan Kohler and Dan Helfman
=head1 SEE ALSO
perl(1). L<Business::OnlinePayment>
=cut
More information about the bop-devel
mailing list