summaryrefslogtreecommitdiff
path: root/FS/t/suite/14-tokenization_refund.t
blob: 65202fdfd5cdc55243d888b8438839558806e014 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#!/usr/bin/perl

use strict;
use FS::Test;
use Test::More;
use FS::Conf;
use FS::cust_main;
use Business::CreditCard qw(generate_last_digit);
use DateTime;
if ( stat('/usr/local/etc/freeside/cardfortresstest.txt') ) {
  plan tests => 33;
} else {
  plan skip_all => 'CardFortress test encryption key is not installed.';
}

#local $FS::cust_main::Billing_Realtime::DEBUG = 2;

my $fs = FS::Test->new( user => 'admin' );
my $conf = FS::Conf->new;
my $err;
my @bopconf;

### can only run on test database (company name "Freeside Test")
like( $conf->config('company_name'), qr/^Freeside Test/, 'using test database' ) or BAIL_OUT('');

### database might need to be upgraded before this,
### but doesn't matter if existing records are tokenized or not,
### this is all about testing new record creation

# these will just get in the way for now
foreach my $apg ($fs->qsearch('agent_payment_gateway')) {
  $err = $apg->delete;
  last if $err;
}
ok( !$err, 'removing agent gateway overrides' ) or BAIL_OUT($err);

# will need this
my $reason = FS::reason->new_or_existing(
  reason => 'Token Test',
  type   => 'Refund',
  class  => 'F',
);
isa_ok ( $reason, 'FS::reason', "refund reason" ) or BAIL_OUT('');

# non-tokenizing gateway
push @bopconf,
'IPPay
TESTTERMINAL';

# tokenizing gateway
push @bopconf,
'CardFortress
cardfortresstest
(TEST54)
Normal Authorization
gateway
IPPay
gateway_login
TESTTERMINAL
gateway_password

private_key
/usr/local/etc/freeside/cardfortresstest.txt';

# for attempting refund post-tokenization
my $n_cust_main;
my $n_cust_pay;

foreach my $tokenizing (0,1) {

  my $adj = $tokenizing ? 'tokenizable' : 'non-tokenizable';

  # set payment gateway
  $conf->set('business-onlinepayment' => $bopconf[$tokenizing]);
  is( join("\n",$conf->config('business-onlinepayment')), $bopconf[$tokenizing], "set $adj default gateway" ) or BAIL_OUT('');

  if ($tokenizing) {

    my $n_paynum = $n_cust_pay->paynum;

    # refund the previous non-tokenized payment through CF
    $err = $n_cust_main->realtime_refund_bop({
      reasonnum => $reason->reasonnum,
      paynum    => $n_paynum,
      method    => 'CC',
    });
    ok( !$err, "run post-switch refund" ) or BAIL_OUT($err);

    # check for void record
    my $n_cust_pay_void = $fs->qsearchs('cust_pay_void',{ paynum => $n_paynum });
    isa_ok( $n_cust_pay_void, 'FS::cust_pay_void', 'post-switch void') or BAIL_OUT("paynum $n_paynum");

    # check that void tokenized
    ok ( $n_cust_pay_void->tokenized, "post-switch void tokenized" ) or BAIL_OUT("paynum $n_paynum");

    # check for no refund record
    ok( !$fs->qsearch('cust_refund',{ source_paynum => $n_paynum }), "post-switch refund did not generate cust_refund" ) or BAIL_OUT("paynum $n_paynum");

  }

  # create customer
  my $cust_main = $fs->new_customer($adj);
  isa_ok ( $cust_main, 'FS::cust_main', "$adj customer" ) or BAIL_OUT('');

  # insert customer
  $err = $cust_main->insert;
  ok( !$err, "insert $adj customer" ) or BAIL_OUT($err);

  # add card
  my $cust_payby;
  my %card = random_card();
  $err = $cust_main->save_cust_payby(
    %card,
    payment_payby => $card{'payby'},
    auto => 1,
    saved_cust_payby => \$cust_payby
  );
  ok( !$err, "save $adj card" ) or BAIL_OUT($err);

  # retrieve card
  isa_ok ( $cust_payby, 'FS::cust_payby', "$adj card" ) or BAIL_OUT('');

  # check that card tokenized or not
  if ($tokenizing) {
    ok( $cust_payby->tokenized, 'new cust card tokenized' ) or BAIL_OUT('');
  } else {
    ok( !$cust_payby->tokenized, 'new cust card not tokenized' ) or BAIL_OUT('');
  }

  # run a payment
  $err = $cust_main->realtime_cust_payby( amount => '1.00' );
  ok( !$err, "run $adj payment" ) or BAIL_OUT($err);

  # get the payment
  my $cust_pay = $fs->qsearchs('cust_pay',{ custnum => $cust_main->custnum }); 
  isa_ok ( $cust_pay, 'FS::cust_pay', "$adj payment" ) or BAIL_OUT('');

  # refund the payment
  $err = $cust_main->realtime_refund_bop({
    reasonnum => $reason->reasonnum,
    paynum    => $cust_pay->paynum,
    method    => 'CC',
  });
  ok( !$err, "run $adj refund" ) or BAIL_OUT($err);

  unless ($tokenizing) {

    # run a second payment, to refund after switch
    $err = $cust_main->realtime_cust_payby( amount => '2.00' );
    ok( !$err, "run $adj second payment" ) or BAIL_OUT($err);
    
    # get the second payment
    $n_cust_pay = $fs->qsearchs('cust_pay',{ custnum => $cust_main->custnum, paid => '2.00' });
    isa_ok ( $n_cust_pay, 'FS::cust_pay', "$adj second payment" ) or BAIL_OUT('');

    $n_cust_main = $cust_main;

  }

  #check that all transactions tokenized or not
  foreach my $table (qw(cust_pay_pending cust_pay cust_pay_void)) {
    foreach my $record ($fs->qsearch($table,{ custnum => $cust_main->custnum })) {
      if ($tokenizing) {
        $err = "record not tokenized: $table ".$record->get($record->primary_key)
          unless $record->tokenized;
      } else {
        $err = "record tokenized: $table ".$record->get($record->primary_key)
          if $record->tokenized;
      }
      last if $err;
    }
  }
  ok( !$err, "$adj transaction token check" ) or BAIL_OUT($err);

  #make sure we voided
  ok( $fs->qsearch('cust_pay_void',{ custnum => $cust_main->custnum}), "$adj refund voided" ) or BAIL_OUT('');

  #make sure we didn't generate refund records
  ok( !$fs->qsearch('cust_refund',{ custnum => $cust_main->custnum}), "$adj refund did not generate cust_refund" ) or BAIL_OUT('');

};

exit;

sub random_card {
  my $payinfo = '4111' . join('', map { int(rand(10)) } 1 .. 11);
  $payinfo .= generate_last_digit($payinfo);
  my $paydate = DateTime->now
                ->add('years' => 1)
                ->truncate(to => 'month')
                ->strftime('%F');
  return ( 'payby'    => 'CARD',
           'payinfo'  => $payinfo,
           'paydate'  => $paydate,
           'payname'  => 'Tokenize Me',
  );
}

1;