Business-GoCardless
view release on metacpan or search on metacpan
t/business/gocardless.t view on Meta::CPAN
#!perl
use strict;
use warnings;
use Test::Most;
use Test::Deep;
use Test::MockObject;
use Test::Exception;
use JSON;
# soft requirements of Business::GoCardless::Client
# "soft" in that they're not required => 1 but must
# be set in the ENV var if not passed to constructor
$ENV{GOCARDLESS_APP_ID} = 'foo';
$ENV{GOCARDLESS_APP_SECRET} = 'bar';
$ENV{GOCARDLESS_MERCHANT_ID} = 'baz';
# this makes Business::GoCardless::Exception show a stack
# trace when any error is thrown so i don't have to keep
# wrapping stuff in this test in evals to debug
$ENV{GOCARDLESS_DEV_TESTING} = 1;
use_ok( 'Business::GoCardless' );
isa_ok(
my $GoCardless = Business::GoCardless->new(
token => 'MvYX0i6snRh/1PXfPoc6',
merchant_id => 'MID',
),
'Business::GoCardless'
);
can_ok(
$GoCardless,
qw/
token
client_details
client
bill
/,
);
cmp_deeply(
$GoCardless->client_details,
{ api_version => 1 },
'client_details'
);
isa_ok( $GoCardless->client,'Business::GoCardless::Client' );
# monkey patching LWP here to make this test work without
# having to actually hit the endpoints or use credentials
no warnings 'redefine';
no warnings 'once';
my $mock = Test::MockObject->new;
$mock->mock( 'is_success',sub { 1 } );
$mock->mock( 'header',sub {} );
*LWP::UserAgent::request = sub { $mock };
test_bill( $GoCardless,$mock );
test_merchant( $GoCardless,$mock );
test_payout( $GoCardless,$mock );
test_pre_authorization( $GoCardless,$mock );
test_subscription( $GoCardless,$mock );
test_user( $GoCardless,$mock );
test_webhook( $GoCardless,$mock );
done_testing();
sub test_bill {
my ( $GoCardless,$mock ) = @_;
note( "Bill" );
like(
my $new_bill_url = $GoCardless->new_bill_url(
amount => 100,
name => "Test Bill",
description => "Test Bill for testing",
redirect_uri => "http://localhost/success",
cancel_uri => "http://localhost/cancel",
state => "id_9SX5G36",
user => {
first_name => "Lee",
}
),
qr!https://gocardless\.com/connect/bills/new\?bill%5Bamount%5D=100&bill%5Bdescription%5D=Test%20Bill%20for%20testing&bill%5Bmerchant_id%5D=baz&bill%5Bname%5D=Test%20Bill&bill%5Buser%5D%5Bfirst_name%5D=Lee&cancel_uri=http%3A%2F%2Flocalhost%2Fc...
'->new_bill_url returns a url'
);
$ENV{GOCARDLESS_DEV_TESTING} = 0;
throws_ok(
sub { $GoCardless->confirm_resource( signature => 'foo' ) },
'Business::GoCardless::Exception',
'->confirm_resource checks signature',
);
like(
$@->message,
qr/Invalid signature for confirm_resource/,
' ... and throws expected error',
);
$ENV{GOCARDLESS_DEV_TESTING} = 1;
$ENV{GOCARDLESS_SKIP_SIG_CHECK} = 1;
$mock->mock( 'content',sub { _bill_json() } );
cmp_deeply(
my $Bill = $GoCardless->confirm_resource(
resource_id => 'foo',
t/business/gocardless.t view on Meta::CPAN
my $i = 0;
$mock->mock(
'content',
sub {
# first time return a merchant object, next time a list of pre_auths
$i++
? '[' . _user_json() . ',' . _user_json() . ']'
: _user_json()
}
);
my @users = $GoCardless->users;
cmp_deeply(
\@users,
[ _user_obj(),_user_obj() ],
'->users returns an array of Business::GoCardless::User objects'
);
}
sub test_webhook {
my ( $GoCardless,$mock ) = @_;
$ENV{GOCARDLESS_SKIP_SIG_CHECK} = 0;
$ENV{GOCARDLESS_DEV_TESTING} = 0;
note( "Webhook" );
my $Webhook = $GoCardless->webhook( _webhook_payload() );
isa_ok( $Webhook,'Business::GoCardless::Webhook' );
throws_ok(
sub { $GoCardless->webhook( _webhook_payload( "bad signature" ) ) },
'Business::GoCardless::Exception',
'->webhook checks signature',
);
}
sub _user_json {
return qq{
{
"created_at":"2011-11-18T17:06:15Z",
"email":"customer40\@gocardless.com",
"id": "JKH8HGKL9H",
"first_name":"Frank",
"last_name":"Smith"
} }
}
sub _user_obj {
return bless( {
'client' => ignore(),
'created_at' => '2011-11-18T17:06:15Z',
'email' => 'customer40@gocardless.com',
'endpoint' => '/users/%s',
'first_name' => 'Frank',
'id' => 'JKH8HGKL9H',
'last_name' => 'Smith'
}, 'Business::GoCardless::User' );
}
sub _subscription_json {
my ( $status ) = @_;
$status //= 'active';
return qq{
{
"currency": "GBP",
"created_at": "2014-08-20T21:41:25Z",
"expires_at": "2016-08-20T21:41:25Z",
"id": "0NZ71WBMVF",
"name": "Membership subscription",
"description": "GoCardless magazine",
"amount": "7.50",
"setup_fee": "0.00",
"interval_unit": "month",
"interval_length": "1",
"start_at": "2014-12-31T00:00:00Z",
"status": "$status",
"sub_resource_uris": {
"bills": "https://sandbox.gocardless.com/api/v1/merchants/0HMARBD8H1/bills?source_id=0PWCDRPCWN"
},
"next_interval_start": "2014-09-20T00:00:00Z",
"merchant_id": "06Z06JWQW1",
"user_id": "FIVWCCVEST6S4D",
"uri": "https://gocardless.com/api/v1/subscriptions/0NZ71WBMVF"
} }
}
sub _subscription_obj {
my ( $status ) = @_;
$status //= 'active';
return bless( {
'amount' => '7.50',
'client' => ignore(),
'created_at' => '2014-08-20T21:41:25Z',
'currency' => 'GBP',
'description' => 'GoCardless magazine',
'endpoint' => '/subscriptions/%s',
'expires_at' => '2016-08-20T21:41:25Z',
'id' => '0NZ71WBMVF',
'interval_length' => '1',
'interval_unit' => 'month',
'merchant_id' => '06Z06JWQW1',
'name' => 'Membership subscription',
'next_interval_start' => '2014-09-20T00:00:00Z',
'setup_fee' => '0.00',
'start_at' => '2014-12-31T00:00:00Z',
'status' => $status,
'sub_resource_uris' => {
'bills' => 'https://sandbox.gocardless.com/api/v1/merchants/0HMARBD8H1/bills?source_id=0PWCDRPCWN'
},
'uri' => 'https://gocardless.com/api/v1/subscriptions/0NZ71WBMVF',
'user_id' => 'FIVWCCVEST6S4D'
}, 'Business::GoCardless::Subscription' );
}
sub _pre_auth_obj {
my ( $status ) = @_;
$status //= 'active';
return bless( {
'client' => ignore(),
'created_at' => '2014-08-20T21:41:25Z',
'currency' => 'GBP',
'description' => 'GoCardless magazine',
'endpoint' => '/pre_authorizations/%s',
'expires_at' => '2016-08-20T21:41:25Z',
'id' => '1234ABCD',
'interval_length' => '1',
'interval_unit' => 'month',
'max_amount' => '750.00',
'merchant_id' => '06Z06JWQW1',
'name' => 'Computer support invoices',
'next_interval_start' => '2014-09-20T00:00:00Z',
'remaining_amount' => '750.00',
'setup_fee' => '10.00',
'status' => $status,
'sub_resource_uris' => {
'bills' => 'https://sandbox.gocardless.com/api/v1/merchants/0HMARBD8H1/bills?source_id=0PWCDRPCWN'
},
'uri' => 'https://gocardless.com/api/v1/pre-authorisations/1234ABCD',
'user_id' => 'FIVWCCVEST6S4D'
}, 'Business::GoCardless::PreAuthorization' );
}
sub _pre_auth_json {
my ( $status ) = @_;
$status //= 'active';
return qq{
{
"currency": "GBP",
"created_at": "2014-08-20T21:41:25Z",
"expires_at": "2016-08-20T21:41:25Z",
"id": "1234ABCD",
"name": "Computer support invoices",
"description": "GoCardless magazine",
"max_amount": "750.00",
"setup_fee": "10.00",
"remaining_amount": "750.00",
"interval_unit": "month",
"interval_length": "1",
"status": "$status",
"sub_resource_uris": {
"bills": "https://sandbox.gocardless.com/api/v1/merchants/0HMARBD8H1/bills?source_id=0PWCDRPCWN"
},
"next_interval_start": "2014-09-20T00:00:00Z",
"merchant_id": "06Z06JWQW1",
"user_id": "FIVWCCVEST6S4D",
"uri": "https://gocardless.com/api/v1/pre-authorisations/1234ABCD"
} }
}
sub _payout_json {
my ( $extra ) = @_;
$extra //= '';
return qq{
{
$extra
"amount": "12.37",
"bank_reference": "JOHNSMITH-Z5DRM",
"created_at": "2013-05-10T16:34:34Z",
"id": "0BKR1AZNJF",
"paid_at": "2013-05-10T17:00:26Z",
"transaction_fees": "0.13"
}}
}
sub _payouts_json {
my $payout = _payout_json( '"app_ids": [ "ABC" ],' );
return qq{ [ $payout ] };
}
sub _payout_obj {
my ( $extra ) = @_;
$extra //= {};
return bless( {
%{ $extra },
'amount' => '12.37',
'bank_reference' => 'JOHNSMITH-Z5DRM',
'client' => ignore(),
'created_at' => '2013-05-10T16:34:34Z',
'endpoint' => '/payouts/%s',
'id' => '0BKR1AZNJF',
'paid_at' => '2013-05-10T17:00:26Z',
'transaction_fees' => '0.13'
}, 'Business::GoCardless::Payout' );
}
sub _merchant_json {
return qq{{
"id":"06Z06JWQW1",
"name":"Company Ltd",
"description":"We do stuff.",
"created_at":"2014-01-22T10:27:42Z",
"first_name":"Lee",
"last_name":"Johnson",
"email":"lee\@foo.com",
"uri":"https://sandbox.gocardless.com/api/v1/merchants/06Z06JWQW1",
"balance":"0.0",
"pending_balance":"0.0",
"next_payout_date":null,
"next_payout_amount":null,
"hide_variable_amount":false,
"sub_resource_uris":{
"users":"https://sandbox.gocardless.com/api/v1/merchants/06Z06JWQW1/users",
"bills":"https://sandbox.gocardless.com/api/v1/merchants/06Z06JWQW1/bills",
"pre_authorizations":"https://sandbox.gocardless.com/api/v1/merchants/06Z06JWQW1/pre_authorizations",
"subscriptions":"https://sandbox.gocardless.com/api/v1/merchants/06Z06JWQW1/subscriptions",
"payouts":"https://sandbox.gocardless.com/api/v1/merchants/06Z06JWQW1/payouts"
},
"gbp_balance":"0.0",
"eur_balance":"0.0",
"gbp_pending_balance":"0.0",
"eur_pending_balance":"0.0"
}};
}
sub _merchant_obj {
return bless(
{
'balance' => '0.0',
'client' => ignore(),
'created_at' => '2014-01-22T10:27:42Z',
'description' => 'We do stuff.',
'email' => 'lee@foo.com',
'endpoint' => '/merchants/%s',
'eur_balance' => '0.0',
'eur_pending_balance' => '0.0',
'first_name' => 'Lee',
'gbp_balance' => '0.0',
'gbp_pending_balance' => '0.0',
'hide_variable_amount' => JSON::false,
'id' => '06Z06JWQW1',
'last_name' => 'Johnson',
'name' => 'Company Ltd',
'next_payout_amount' => undef,
'next_payout_date' => undef,
'pending_balance' => '0.0',
'sub_resource_uris' => {
'bills' => 'https://sandbox.gocardless.com/api/v1/merchants/06Z06JWQW1/bills',
'payouts' => 'https://sandbox.gocardless.com/api/v1/merchants/06Z06JWQW1/payouts',
'pre_authorizations' =>
'https://sandbox.gocardless.com/api/v1/merchants/06Z06JWQW1/pre_authorizations',
'subscriptions' =>
'https://sandbox.gocardless.com/api/v1/merchants/06Z06JWQW1/subscriptions',
'users' => 'https://sandbox.gocardless.com/api/v1/merchants/06Z06JWQW1/users'
},
'uri' => 'https://sandbox.gocardless.com/api/v1/merchants/06Z06JWQW1'
},
'Business::GoCardless::Merchant'
);
}
sub _bill_json {
my ( $status,$amount ) = @_;
$status //= 'pending';
$amount //= '44.0';
return qq{{
"amount": "$amount",
"gocardless_fees": "0.44",
"partner_fees": "0",
"currency": "GBP",
"created_at": "2014-08-20T21:41:25Z",
"description": "Month 2 payment",
"id": "123ABCD",
"name": "Bill 2 for Subscription description",
"paid_at": null,
"status": "$status",
"merchant_id": "06Z06JWQW1",
"user_id": "FIVWCCVEST6S4D",
"source_type": "ad_hoc_authorization",
"source_id": "YH1VEVQHYVB1UT",
"uri": "https://gocardless.com/api/v1/bills/123ABCD",
"can_be_retried": false,
"payout_id": null,
"is_setup_fee": false,
"charge_customer_at": "2014-09-01"
}};
}
sub _bill_obj {
my ( $status ) = @_;
$status //= 'pending';
return bless({
'amount' => '44.0',
'can_be_retried' => JSON::false,
'charge_customer_at' => '2014-09-01',
'client' => ignore(),
'created_at' => '2014-08-20T21:41:25Z',
'currency' => 'GBP',
'description' => 'Month 2 payment',
'endpoint' => '/bills/%s',
'gocardless_fees' => '0.44',
'id' => '123ABCD',
'is_setup_fee' => JSON::false,
'merchant_id' => '06Z06JWQW1',
'name' => 'Bill 2 for Subscription description',
'paid_at' => undef,
'partner_fees' => '0',
'payout_id' => undef,
'source_id' => 'YH1VEVQHYVB1UT',
'source_type' => 'ad_hoc_authorization',
'status' => $status,
'user_id' => 'FIVWCCVEST6S4D',
'uri' => 'https://gocardless.com/api/v1/bills/123ABCD',
},'Business::GoCardless::Bill'
);
}
sub _webhook_payload {
my ( $signature ) = @_;
$signature //= 'c6e7ea99cfb52b98a04a36a79920fff71ce851ca38e1f5a1e487f8c92417350e';
return qq{{
"payload": {
"resource_type": "bill",
"action": "paid",
"bills": [
{
"id": "AKJ398H8KA",
"status": "paid",
"source_type": "subscription",
"source_id": "KKJ398H8K8",
"amount": "20.0",
"amount_minus_fees": "19.8",
"paid_at": "2011-12-01T12:00:00Z",
"uri": "https://gocardless.com/api/v1/bills/AKJ398H8KA"
},
{
"id": "AKJ398H8KB",
"status": "paid",
"source_type": "subscription",
"source_id": "8AKJ398H78",
"amount": "20.0",
"amount_minus_fees": "19.8",
"paid_at": "2011-12-09T12:00:00Z",
"uri": "https://gocardless.com/api/v1/bills/AKJ398H8KB"
}
],
"signature": "$signature"
}
}};
}
# vim: ts=4:sw=4:et
( run in 1.120 second using v1.01-cache-2.11-cpan-a49fcb8fa48 )