+
+ $response;
+}
+
+=head2 submit_authorization_only
+
+Capture a card authorization, but do not complete transaction
+
+=cut
+
+sub submit_authorization_only {
+ my $self = shift;
+
+ $self->submit_normal_authorization;
+
+ my $response = $self->response_decoded;
+
+ if (
+ $self->is_success
+ && (
+ ref $response
+ && $response->{type} != 'PA'
+ )
+ ) {
+ # Bambora API uses nearly identical API calls for normal
+ # card transactions and pre-authorization. Sanity check
+ # that response reported a pre-authorization code
+ die "Expected API Respose type=PA, but type=$response->{type}! ".
+ "Pre-Authorization attempt may have charged card!";
+ }
+}
+
+=head2 submit_post_authorization
+
+Complete a card pre-authorization
+
+=cut
+
+sub submit_post_authorization {
+ shift->submit_normal_authorization;
+}
+
+=head2 submit_reverse_authorization
+
+Reverse a pre-authorization
+
+=cut
+
+sub submit_reverse_authorization {
+ shift->submit_void;
+}
+
+=head2 submit_void
+
+Void a transaction
+
+=cut
+
+sub submit_void {
+ my $self = shift;
+ my $content = $self->{_content};
+
+ for my $f (qw/ order_number invoice_number amount/) {
+ unless ( $content->{$f} ) {
+ $self->error_message("Cannot process void - missing required content $f");
+ warn $self->error_message if $DEBUG;
+
+ return $self->is_success(0);
+ }
+ }
+
+ my %post = (
+ order_number => $self->truncate( $content->{invoice_number}, 30 ),
+ amount => $content->{amount},
+ );
+ my $post_body = encode_json( \%post );
+
+ if ( $DEBUG ) {
+ warn Dumper({
+ post => \%post,
+ post_body => $post_body,
+ });
+ }
+ $self->path( sprintf '/v1/payments/%s/void', $content->{order_number} );
+
+ my $response = $self->submit_api_request( $post_body );
+