+=head2 jhref_card
+
+Return a hashref for inclusin into a json object
+representing Card for the API
+
+If necessary values are missing from %content, will set
+error_message and is_success
+
+=cut
+
+sub jhref_card {
+ my $self = shift;
+ my $content = $self->{_content};
+
+ $self->set_expiration;
+
+ # Check required input
+ for my $f (qw/
+ card_number
+ owner
+ expiry_month
+ expiry_year
+ cvv2
+ /) {
+ next if $content->{$f};
+
+ $self->error_message(
+ "Cannot parse card payment - missing required content $f"
+ );
+
+ warn $self->error_message if $DEBUG;
+ $self->is_success( 0 );
+
+ return {};
+ }
+
+ return +{
+ number => $self->truncate( $content->{card_number}, 20 ),
+ name => $self->truncate( $content->{owner}, 64 ),
+ expiry_month => sprintf( '%02d', $content->{expiry_month} ),
+ expiry_year => sprintf( '%02d', $content->{expiry_year} ),
+ cvd => $content->{cvv2},
+ }
+}
+
+=head2 generate_token
+
+Generate a 16-digit numeric token, beginning with the digits 99,
+based on the current epoch time
+
+Implementation note:
+
+If this module is somehow used to tokenize multiple cardholders within
+the same microsecond, these cardholders will be assigned the same
+customer_code. In the unlikely event this does happen, the Bambora system
+will decline to process cards for either of the profiles with a duplicate
+customer_code.
+
+=cut
+
+sub generate_token {
+ my $self = shift;
+ my $time = Time::HiRes::time();
+
+ $time =~ s/\D//g;
+ $time = substr($time, 0, 14 ); # Eventually time() will contain 15 digits
+
+ "99$time";
+}
+