Billing address fields. Credit card processors may use these (especially
zip) for authentication.
+=item phone
+
+Customer phone number.
+
=cut
has [ qw(
state
country
zip
+ phone
) ] => ( is => 'rw', isa => 'Str', default => '' );
=back
=item process_date
-The date requested for processing.
+The date requested for processing. This is meaningful only if the
+processor allows different processing dates for items in the same
+batch.
=item invoice_number
=cut
has card_number => ( is => 'rw', isa => 'Str' );
-has expiration => ( is => 'rw', isa => 'Str' );
+has ['expiration_month', 'expiration_year'] => ( is => 'rw', isa => 'Int' );
+
+sub expiration {
+ # gets/sets expiration_month and _year in MMYY format
+ my $self = shift;
+ my $arg = shift;
+ if ( $arg ) {
+ # well, we said it's in MMYY format
+ my ($m, $y) = _parse_expiration($arg);
+ $self->expiration_month($m);
+ $self->expiration_year($y);
+ }
+ return sprintf('%02d/%02d',
+ $self->expiration_month,
+ $self->expiration_year % 2000);
+}
+
+sub _parse_expiration {
+ my $arg = shift;
+ if ( $arg =~ /^(\d\d)(\d\d)$/ ) {
+ return ($1, 2000 + $2);
+ } elsif ( $arg =~ /^(\d\d?)\W(\d\d)$/ ) {
+ return ($1, 2000 + $2);
+ } elsif ( $arg =~ /^(\d\d?)\W(\d\d\d\d)$/ ) {
+ return ($1, $2);
+ } elsif ( $arg =~ /^(\d\d?)\W\d\d?\W(\d\d\d\d)$/) {
+ return ($1, $3);
+ } else {
+ die "can't parse expiration date '$arg'";
+ }
+}
+
+sub payinfo {
+ # gets/sets either the card number, or the account number + routing code
+ # depending on the payment type
+ my $self = shift;
+ if ( $self->payment_type eq 'CC' ) {
+ $self->card_number(@_);
+ } elsif ( $self->payment_type eq 'ECHECK' ) {
+ my $arg = shift;
+ if ( $arg ) {
+ $arg =~ /^(\d+)@(\d+)$/ or die "Validation failed for payinfo";
+ $self->account_number($1);
+ $self->routing_code($2);
+ }
+ return ($self->account_number . '@' . $self->routing_code);
+ }
+}
=back
The message returned by the gateway. This may contain a value even
if the payment was successful (use C<approved> to determine that.)
+=item failure_status
+
+A normalized failure status, from the following list:
+
+=over 4
+
+=item expired
+
+=item nsf (non-sufficient funds / credit limit)
+
+=item stolen
+
+=item pickup
+
+=item blacklisted
+
+=item inactive
+
+=item decline (other card/transaction declines)
+
+=back
+
=back
=cut
assigned_token
)] => ( is => 'rw', isa => 'Str');
+enum FailureStatus => qw(
+ expired
+ nsf
+ stolen
+ pickup
+ blacklisted
+ inactive
+ decline
+);
+has failure_status => ( is => 'rw', isa => 'Maybe[FailureStatus]' );
+
has check_number => ( is => 'rw', isa => 'Int' );
+around 'BUILDARGS' => sub {
+ my ($orig, $self, %args) = @_;
+ if ( $args{expiration} ) {
+ @args{'expiration_month', 'expiration_year'} =
+ _parse_expiration($args{expiration});
+ }
+ $self->$orig(%args);
+};
+
__PACKAGE__->meta->make_immutable;
1;