package Business::OnlinePayment::PaymenTech::Orbital;
use strict;
our $VERSION = '1.7';
=head1 NAME
Business::OnlinePayment::PaymenTech::Orbital - PaymenTech Orbital backend for Business::OnlinePayment
=head1 SYNPOSIS
my %options;
$options{'merchantid'} = '1234';
my $tx = Business::OnlinePayment->new('PaymenTech::Orbital', %options);
$tx->content(
username => 'username',
password => 'pass',
invoice_number => $orderid,
trace_number => $trace_num, # Optional
action => 'Authorization Only',
cvn => 123, # cvv2, cvc2, cid
card_number => '1234123412341234',
exp_date => '0410',
address => '123 Test Street',
name => 'Test User',
amount => 100 # $1.00
);
$tx->submit;
if($tx->is_success) {
print "Card processed successfully: ".$tx->authorization."\n";
} else {
print "Card was rejected: ".$tx->error_message."\n";
}
=head1 DESCRIPTION
Business::OnlinePayment::PaymenTech::Orbital allows you to utilize
PaymenTech's Orbital SDK credit card services. You will need to install the
Perl Orbital SDK for this to work.
This module was previous named Business::OnlinePayment::PaymenTech but was
renamed since it is specific to the Orbital SDK product.
For detailed information see L<Business::OnlinePayment>.
=head1 SUPPORTED ACTIONS
Authorization Only, Authorization and Capture, Capture, Credit
By default, Business::Online::PaymenTech::Orbital uses the MOTO API calls in
the PaymenTech library. If you specifically set the C<ecommerce> option to a
true value in your C<content> then the CC API will be used where applicable,
notably Authorization, Authorization and Capture and Refund. (Actually,
refund uses ECOMMERCE_REFUND when C<ecommerce> is true).
=head1 NOTES
There are a few rough edges to this module, but having it significantly eased
a transition from one processor to another.
=head1 SOFT DESCRIPTORS
The Soft Descriptor feature is enabled by setting C<sd_merchant_name> and,
optionally, any of the the following fields:
=over 4
=item sd_merchant_name
=item sd_product_description
=item sd_merchant_city
=item sd_merchant_phone
=item sd_merchant_url
=item sd_merchant_email
=head2 DEFAULTS
=back
=item time zone defaults to 706 (Central)
=item BIN defaults 001
=back
Some extra getters are provided. They are:
response - Get the response code
avs_response - Get the AVS response
cvv2_response - Get the CVV2 response
transaction_id - Get the PaymenTech assigned Transaction Id
=cut
use base qw(Business::OnlinePayment);
use Paymentech::SDK;
use Paymentech::eCommerce::RequestBuilder 'requestBuilder';
use Paymentech::eCommerce::RequestTypes qw(CC_AUTHORIZE_REQUEST MOTO_AUTHORIZE_REQUEST CC_MARK_FOR_CAPTURE_REQUEST ECOMMERCE_REFUND_REQUEST MOTO_REFUND_REQUEST);
use Paymentech::eCommerce::TransactionProcessor ':alias';
sub set_defaults {
my $self = shift;
$self->{'_content'} = {};
$self->build_subs(
qw(response avs_response cvv2_response transaction_id card_proc_resp)
);
}
sub submit {
my $self = shift;
my %content = $self->content;
my $req;
if($content{'action'} eq 'Authorization Only') {
if(lc($content{industry}) eq 'ecommerce') {
$req = requestBuilder()->make(CC_AUTHORIZE_REQUEST());
if(defined($content{'cvn'})) {
$req->CardSecVal($content{'cvn'});
}
} else {
$req = requestBuilder()->make(MOTO_AUTHORIZE_REQUEST());
}
$self->_add_bill_to($req);
# Authorize
$req->MessageType('A');
$req->CurrencyCode('840');
$req->Exp($content{'exp_date'});
$req->AccountNum($content{'card_number'});
} elsif($content{'action'} eq 'Capture') {
$req = requestBuilder()->make(CC_MARK_FOR_CAPTURE_REQUEST());
$req->TxRefNum($content{'tx_ref_num'});
} elsif($content{'action'} eq 'Force Authorization Only') {
# ?
} elsif($content{'action'} eq 'Authorization and Capture') {
if(lc($content{industry}) eq 'ecommerce') {
$req = requestBuilder()->make(CC_AUTHORIZE_REQUEST());
if(defined($content{'cvn'})) {
$req->CardSecVal($content{'cvn'});
}
} else {
$req = requestBuilder()->make(MOTO_AUTHORIZE_REQUEST());
}
$self->_add_bill_to($req);
# Authorize and Capture
$req->MessageType('AC');
$req->CurrencyCode('840');
$req->Exp($content{'exp_date'});
$req->AccountNum($content{'card_number'});
} elsif($content{'action'} eq 'Credit') {
if(lc($content{industry}) eq 'ecommerce') {
$req = requestBuilder()->make(ECOMMERCE_REFUND_REQUEST());
} else {
$req = requestBuilder()->make(MOTO_REFUND_REQUEST());
}
$req->CurrencyCode($content{'currency_code'} || '840');
$req->AccountNum($content{'card_number'});
} else {
die('Unknown Action: '.$content{'action'}."\n");
}
if(defined($content{sd_merchant_name}) && $content{'action'} ne 'Capture') {
$self->_add_soft_descriptor($req);
}
$req->BIN($content{'BIN'} || '000001');
$req->MerchantID($self->{'merchantid'});
if(exists($content{'trace_number'}) && $content{'trace_number'} =~ /^\d+$/) {
$req->traceNumber($content{'trace_number'});
}
$req->OrderID($content{'invoice_number'});
$req->Amount(sprintf("%012d", $content{'amount'}));
$req->TzCode($content{'TzCode'} || '706');
if(exists($content{'comments'})) {
$req->Comments($content{'comments'} || '');
}
$self->{'request'} = $req;
$self->_post;
$self->_process_response;
}
sub _post {
my $self = shift;
my %content = $self->content;
if($self->test_transaction) {
print STDERR $self->{request}->renderAsXML."\n";
}
my $gw_resp = gatewayTP()->process($self->{'request'});
}
sub _process_response {
my $self = shift;
my $resp = $self->{'request'}->response;
unless(defined($resp)) {
$self->is_success(0);
$self->error_message($self->error_message." No response.");
return;
}
if($self->test_transaction) {
print STDERR $resp->raw;
}
$self->transaction_id($resp->value('TxRefNum'));
$self->cvv2_response($resp->CVV2ResponseCode);
$self->response($resp->ResponseCode);
$self->avs_response($resp->AVSResponseCode);
$self->authorization($resp->value('AuthCode'));
$self->error_message($resp->status);
if(!$resp->approved) {
$self->is_success(0);
return;
}
$self->is_success(1);
}
sub _add_bill_to {
my ($self, $req) = @_;
my %content = $self->content;
$req->AVSname($content{'name'});
$req->AVSaddress1($content{'address'});
$req->AVSaddress2($content{'address2'});
$req->AVScity($content{'city'});
$req->AVSstate($content{'state'});
$req->AVSzip($content{'zip'});
$req->AVScountryCode($content{'country'});
if(exists($content{'phone_number'})) {
$req->AVSphoneNum($content{'phone_number'});
}
}
sub _add_soft_descriptor {
my ($self, $req) = @_;
my %content = $self->content;
$req->SDMerchantName($content{'sd_merchant_name'});
$req->SDProductDescription($content{'sd_product_description'});
$req->SDMerchantCity($content{'sd_merchant_city'});
$req->SDMerchantPhone($content{'sd_merchant_phone'});
$req->SDMerchantURL($content{'sd_merchant_url'});
$req->SDMerchantEmail($content{'sd_merchant_email'});
}
=head1 AUTHOR
Cory 'G' Watson <gphat@cpan.org>
=head2 CONTRIBUTORS
Garth Sainio <gsainio@cpan.org>
=head1 SEE ALSO
perl(1), L<Business::OnlinePayment>.
=head1 COPYRIGHT AND LICENSE
Copyright 2008 by Magazines.com, LLC
You can redistribute and/or modify this code under the same terms as Perl
itself.
=cut
1;