The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Finance::Bank::ID::BPRKS - Check your BPR KS accounts from Perl

VERSION

version 0.01

SYNOPSIS

    use Finance::Bank::ID::BPRKS;

    # FBI::BPRKS uses Log::Any. to show logs using, e.g., Log4perl:
    use Log::Log4perl qw(:easy);
    use Log::Any::Adapter;
    Log::Log4perl->easy_init($DEBUG);
    Log::Any::Adapter->set('Log4perl');

    my $ibank = Finance::Bank::ID::BPRKS->new(
        username => 'ABCDEFGH1234', # opt if only using parse_statement()
        password => '123456',       # idem
        verify_https => 1,          # default is 0
        #https_ca_dir => '/etc/ssl/certs', # default is already /etc/ssl/certs
    );

    eval {
        $ibank->login(); # dies on error

        my @cards = $ibank->list_cards();

        my $bal = $ibank->check_balance($card); # $card is optional

        my $stmt = $ibank->get_statement(
            card       => ..., # opt, default card will be used if undef
            days       => 30,  # opt
            start_date => DateTime->new(year=>2012, month=>6, day=>1),
                               # opt, takes precedence over 'days'
            end_date   => DateTime->today, # opt, takes precedence over 'days'
        );

        print "Transactions: ";
        for my $tx (@{ $stmt->{transactions} }) {
            print "$tx->{date} $tx->{amount} $tx->{description}\n";
        }
    };

    # remember to call this, otherwise you will have trouble logging in again
    # for some time
    if ($ibank->logged_in) { $ibank->logout() }

    # utility routines
    my $res = $ibank->parse_statement($html);

Also see the examples/ subdirectory in the distribution for a sample script using this module.

DESCRIPTION

RELEASE NOTE: This is an early release. Only parse_statement() for a single statement page is implemented.

This module provide a rudimentary interface to the web-based online banking interface of the Indonesian BPR Karyajatnika Sadaya (BPR KS, BPRKS) at https://ib.bprks.co.id. You will need either Crypt::SSLeay or IO::Socket::SSL installed for HTTPS support to work (and strictly Crypt::SSLeay to enable certificate verification). WWW::Mechanize is required but you can supply your own mech-like object.

This module can only login to the individual edition of the site. I haven't checked out the other versions.

Warning: This module is neither offical nor is it tested to be 100% safe! Because of the nature of web-robots, everything may break from one day to the other when the underlying web interface changes.

WARNING

This warning is from Simon Cozens' Finance::Bank::LloydsTSB, and seems just as apt here.

This is code for online banking, and that means your money, and that means BE CAREFUL. You are encouraged, nay, expected, to audit the source of this module yourself to reassure yourself that I am not doing anything untoward with your banking data. This software is useful to me, but is provided under NO GUARANTEE, explicit or implied.

ERROR HANDLING AND DEBUGGING

Most methods die() when encountering errors, so you can use eval() to trap them.

This module uses Log::Any, so you can see more debugging statements on your screen, log files, etc. See the Log::Any documentation on how to do that.

Full response headers and bodies are dumped to a separate logger. See documentation on new() below and the sample script in examples/ subdirectory in the distribution.

ATTRIBUTES

skip_NEXT => BOOL

If set to true, then statement with NEXT status will be skipped.

METHODS

new(%args)

Create a new instance. %args keys:

  • username

    Optional if you are just using utility methods like parse_statement() and not login() etc.

  • password

    Optional if you are just using utility methods like parse_statement() and not login() etc.

  • mech

    Optional. A WWW::Mechanize-like object. By default this module instantiate a new Finance::BankUtils::ID::Mechanize (a WWW::Mechanize subclass) object to retrieve web pages, but if you want to use a custom/different one, you are allowed to do so here. Use cases include: you want to retry and increase timeout due to slow/unreliable network connection (using WWW::Mechanize::Plugin::Retry), you want to slow things down using WWW::Mechanize::Sleepy, you want to use IE engine using Win32::IE::Mechanize, etc.

  • verify_https

    Optional. If you are using the default mech object (see previous option), you can set this option to 1 to enable SSL certificate verification (recommended for security). Default is 0.

    SSL verification will require a CA bundle directory, default is /etc/ssl/certs. Adjust https_ca_dir option if your CA bundle is not located in that directory.

  • https_ca_dir

    Optional. Default is /etc/ssl/certs. Used to set HTTPS_CA_DIR environment variable for enabling certificate checking in Crypt::SSLeay. Only used if verify_https is on.

  • logger

    Optional. You can supply a Log::Any-like logger object here. If not specified, this module will use a default logger.

  • logger_dump

    Optional. You can supply a Log::Any-like logger object here. This is just like logger but this module will log contents of response here instead of to logger for debugging purposes. You can configure using something like Log::Dispatch::Dir to save web pages more conveniently as separate files. If unspecified, the default logger is used (same as logger).

login()

Login to the net banking site. You actually do not have to do this explicitly as login() is called by other methods like check_balance() or get_statement().

If login is successful, logged_in will be set to true and subsequent calls to login() will become a no-op until logout() is called.

Dies on failure.

logout()

Logout from the net banking site. You need to call this at the end of your program, otherwise the site will prevent you from re-logging in for some time (e.g. 10 minutes).

If logout is successful, logged_in will be set to false and subsequent calls to logout() will become a no-op until login() is called.

Dies on failure.

list_accounts()

Return an array containing all account numbers that are associated with the current net banking login.

check_balance([$account])

Return balance for specified account, or the default account if $account is not specified.

get_statement(%args) => $stmt

Get account statement. %args keys:

  • account

    Optional. Select the account to get statement of. If not specified, will use the already selected account.

  • days

    Optional. Number of days between 1 and 30. If days is 1, then start date and end date will be the same. Default is 30.

  • start_date

    Optional. Default is end_date - days.

  • end_date

    Optional. Default is today (or some 1+ days from today if today is a Saturday/Sunday/holiday, depending on the default value set by the site's form).

See parse_statement() on structure of $stmt.

parse_statement($html, %opts) => $res

Given the HTML text of the account statement results page, parse it into structured data:

 $stmt = {
    start_date     => $start_dt, # a DateTime object
    end_date       => $end_dt,   # a DateTime object
    account_holder => STRING,
    account        => STRING,    # account number
    currency       => STRING,    # 3-digit currency code
    transactions   => [
        # first transaction
        {
          date        => $dt,  # a DateTime obj, book date ("tanggal pembukuan")
          seq         => INT,  # a number >= 1 which marks the sequence of
                               # transactions for the day
          amount      => REAL, # a real number, positive means credit (deposit),
                               # negative means debit (withdrawal)
          description => STRING,
          #is_pending  => BOOL,
          branch      => STRING, # a 4-digit branch/ATM code
          balance     => REAL,
        },
        # second transaction
        ...
    ]
 }

$html is the HTML text. Since there can be multiple pages, $html can also be an arrayref of HTML texts (this is not yet implemented).

Returns:

 [$status, $err_details, $stmt]

$status is 200 if successful or some other 3-digit code if parsing failed. $stmt is the result (structure as above, or undef if parsing failed).

Options (%opts):

  • return_datetime_obj => BOOL

    Default is true. If set to false, the method will return dates as strings with this format: 'YYYY-MM-DD HH::mm::SS' (produced by DateTime->dmy . ' ' . DateTime->hms). This is to make it easy to pass the data structure into YAML, JSON, MySQL, etc. Nevertheless, internally DateTime objects are still used.

Additional notes:

The method can also handle some copy-pasted text from the GUI browser, but this is no longer documented or guaranteed to keep working.

AUTHOR

Steven Haryanto <stevenharyanto@gmail.com>

COPYRIGHT AND LICENSE

This software is copyright (c) 2012 by Steven Haryanto.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.