diff options
author | Mark Wells <mark@freeside.biz> | 2013-06-28 16:36:47 -0700 |
---|---|---|
committer | Mark Wells <mark@freeside.biz> | 2013-06-28 16:36:47 -0700 |
commit | 472f07098c2e10ac025b132df098f4b51c14adb1 (patch) | |
tree | fb6f5bb33ff55b658b298f3cd00316c054225b82 /FCMB.pm |
start
Diffstat (limited to 'FCMB.pm')
-rw-r--r-- | FCMB.pm | 168 |
1 files changed, 168 insertions, 0 deletions
@@ -0,0 +1,168 @@ +package Business::OnlineThirdPartyPayment::FCMB; + +use strict; +use base 'Business::OnlineThirdPartyPayment'; + +use strict; +use LWP; +use URI; +use Data::Dumper; +use Date::Format 'time2str'; +use XML::LibXML; + +our $VERSION = '0.01'; +our $ENDPOINT_SANDBOX = 'localhost'; +our $ENDPOINT_LIVE = 'fcmbwebpay.firstcitygrouponline.com'; + +our $DEBUG = 3; + +# ISO 4217 currency codes (the relevant ones) +our %ALPHA_TO_NUM = ( + USD => 840, + UKP => 826, + NGN => 566, +); + +sub set_defaults { + my $self = shift; + my %args = @_; + $self->build_subs(qw(username password host)); + if ( $args{debug} ) { + $DEBUG = $args{debug}; + } +} + +sub create { + my $self = shift; + my %content = @_; + + my %params; + $params{'orderId'} = time2str('%Y%m%d%H%M%S', time) . '-' . + sprintf('%06d', int(rand(1000000))); + $params{'mercId'} = $self->username + or die "FCMB merchant ID (username) must be configured\n"; + $params{'currCode'} = $ALPHA_TO_NUM{$content{currency}}; + $params{'prod'} = $content{'description'}; + $params{'email'} = $content{'email'}; + $params{'amt'} = $content{'amount'}; + + my $host = $self->host; + if ( $self->test_transaction ) { + $host ||= $ENDPOINT_SANDBOX; + } else { + $host ||= $ENDPOINT_LIVE; + } + my $url = 'https://' . $host . + '/customerportal/MerchantServices/MakePayment.aspx'; + + warn Dumper \%params if $DEBUG > 2; + + # we don't post to the url ourselves, just give it to the user + $self->is_success(1); + $self->redirect($url); + $self->post_params(\%params); + + $self->token( $params{'orderId'} ); +} + +sub execute { + my $self = shift; + my %params = @_; + +# URL looks like +# http://merchantA.com/Success?OrderID=988676&TransactionReference=8765678998989779 + warn Dumper(\%params) if $DEBUG > 2; + + if ($params{'OrderID'}) { + $self->token($params{'OrderID'}); + } else { + die 'No order ID returned from processor'; + } + if ($params{'TransactionReference'}) { + $self->order_number($params{'TransactionReference'}); + } else { + die 'No transaction reference returned from processor'; + } + + my $host = $self->host; + if ( $self->test_transaction ) { + $host ||= $ENDPOINT_SANDBOX; + $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0; + } else { + $host ||= $ENDPOINT_LIVE; + } + my $url = 'https://' . $host . + '/customerportal/MerchantServices/UpayTransactionStatus.ashx'; + my $ua = LWP::UserAgent->new; + warn "Querying transaction status at $url\n" if $DEBUG; + my $response = $ua->get($url, + 'MERCHANT_ID' => $self->username, + 'ORDER_ID' => $self->token + ); + + if ( $response->is_success ) { + + local $@; + my $parser = XML::LibXML->new; + my $doc = eval { $parser->parse_string($response->content) }; + if ( $@ ) { + die "malformed response to transaction status request: $@\n". + ($DEBUG ? ("\n\n".$response->content) : ''); + } + my $root = $doc->documentElement; + my %hash = map { $_->nodeName => $_->textContent } + $root->nonBlankChildNodes; + + warn Dumper \%hash if $DEBUG > 2; + if ( $hash{StatusCode} == 0 ) { + $self->is_success(1); + $self->authorization($hash{PaymentRef}); + } else { + $self->is_success(0); + $self->error_message($hash{Status} . ' - ' . $hash{ResponseDescription}); + } + } else { + die "No confirmation received: ".$response->status_line; + } +} + +1; +__END__ + +=head1 NAME + +Business::OnlineThirdPartyPayment::FCMB + +=head1 DESCRIPTION + +Business::OnlineThirdPartyPayment interface to the First City Monument Bank +(Nigeria) web-based payment processing system. + +=head1 NOTES + +=over 4 + +=item FCMB requires the callback URL to be configured statically; +I<return_url> and I<cancel_url> parameters will be ignored. + +=item Set I<username> to your merchant ID (5 digits). No password is needed. + +=item The only required transaction fields are currency (NGN, USD, or UKP), +amount, description, and email. + +=item The 'faker' directory contains a simple mock-up of the FCMB interface +for testing. This was created from the documentation, without reference +to the real FCMB system, and is NOT known to be accurate. + +=back + +=head1 AUTHOR + +Mark Wells <mark@freeside.biz> + +=head1 SEE ALSO + +perl(1). L<Business::OnlineThirdPartyPayment>. + +=cut + |