WebService-Braintree

 view release on metacpan or  search on metacpan

README  view on Meta::CPAN

    WebService::Braintree::Configuration for details.

  Class Style

        use WebService::Braintree;
    
        my $conf = WebService::Braintree->configuration;
        $conf->environment( 'sandbox' );
        $conf->merchant_id( 'use_your_merchant_id' );
        $conf->public_key( 'use_your_public_key' );
        $conf->private_key( 'use_your_private_key' );
    
        my $result = WebService::Braintree::Transaction->sale(
            ...
        );

  Object Style

        use WebService::Braintree;
    
        my $gateway = WebService::Braintree::Gateway->new({
            environment => 'sandbox',
            merchant_id => 'use_your_merchant_id',
            public_key  => 'use_your_public_key',
            private_key => 'use_your_private_key',
        });
    
        my $result = $gateway->transaction->sale(
            ...
        );

  Client Tokens

    In general, your server code (that uses this library) will be
    interacting with a client-side SDK (such as for Mobile or Javascript).

README  view on Meta::CPAN


      Create a sandbox_config.json

	On the dashboard page of your new sandbox account, three are three
	values you will need to put into a sandbox_config.json. The format
	of the file must be:

            {
              "merchant_id": "<< value 1 >>",
              "public_key": "<< value 2 >>",
              "private_key": "<< value 3 >>"
            }

	replacing what's in the double-quotes with the appropriate values
	from your Braintree sandbox's dashboard.

      Link your Paypal Sandbox Account

	You'll need to follow the instructions at
	https://developers.braintreepayments.com/guides/paypal/testing-go-live/ruby#linked-paypal-testing.
	This is required for some of the integration tests to pass.

README.pod  view on Meta::CPAN

L<WebService::Braintree::Configuration/> for details.

=head3 Class Style

    use WebService::Braintree;

    my $conf = WebService::Braintree->configuration;
    $conf->environment( 'sandbox' );
    $conf->merchant_id( 'use_your_merchant_id' );
    $conf->public_key( 'use_your_public_key' );
    $conf->private_key( 'use_your_private_key' );

    my $result = WebService::Braintree::Transaction->sale(
        ...
    );

=head3 Object Style

    use WebService::Braintree;

    my $gateway = WebService::Braintree::Gateway->new({
        environment => 'sandbox',
        merchant_id => 'use_your_merchant_id',
        public_key  => 'use_your_public_key',
        private_key => 'use_your_private_key',
    });

    my $result = $gateway->transaction->sale(
        ...
    );

=head3 Client Tokens

In general, your server code (that uses this library) will be interacting with
a client-side SDK (such as for Mobile or Javascript).  That library will need a

README.pod  view on Meta::CPAN


=item Create a sandbox_config.json

On the dashboard page of your new sandbox account, three are three values you
will need to put into a C<< sandbox_config.json >>.  The format of the file must
be:

    {
      "merchant_id": "<< value 1 >>",
      "public_key": "<< value 2 >>",
      "private_key": "<< value 3 >>"
    }

replacing what's in the double-quotes with the appropriate values from your
Braintree sandbox's dashboard.

=item Link your Paypal Sandbox Account

You'll need to follow the instructions at L<< https://developers.braintreepayments.com/guides/paypal/testing-go-live/ruby#linked-paypal-testing >>.  This is
required for some of the integration tests to pass.

lib/WebService/Braintree.pm  view on Meta::CPAN

L<WebService::Braintree::Configuration/> for details.

=head3 Class Style

    use WebService::Braintree;

    my $conf = WebService::Braintree->configuration;
    $conf->environment( 'sandbox' );
    $conf->merchant_id( 'use_your_merchant_id' );
    $conf->public_key( 'use_your_public_key' );
    $conf->private_key( 'use_your_private_key' );

    my $result = WebService::Braintree::Transaction->sale(
        ...
    );

=head3 Object Style

    use WebService::Braintree;

    my $gateway = WebService::Braintree::Gateway->new({
        environment => 'sandbox',
        merchant_id => 'use_your_merchant_id',
        public_key  => 'use_your_public_key',
        private_key => 'use_your_private_key',
    });

    my $result = $gateway->transaction->sale(
        ...
    );

=head3 Client Tokens

In general, your server code (that uses this library) will be interacting with
a client-side SDK (such as for Mobile or Javascript).  That library will need a

lib/WebService/Braintree.pm  view on Meta::CPAN


=item Create a sandbox_config.json

On the dashboard page of your new sandbox account, three are three values you
will need to put into a C<< sandbox_config.json >>.  The format of the file must
be:

    {
      "merchant_id": "<< value 1 >>",
      "public_key": "<< value 2 >>",
      "private_key": "<< value 3 >>"
    }

replacing what's in the double-quotes with the appropriate values from your
Braintree sandbox's dashboard.

=item Link your Paypal Sandbox Account

You'll need to follow the instructions at L<< https://developers.braintreepayments.com/guides/paypal/testing-go-live/ruby#linked-paypal-testing >>.  This is
required for some of the integration tests to pass.

lib/WebService/Braintree/Configuration.pm  view on Meta::CPAN

has merchant_id => (is => 'rw');

=head2 public_key(?$value)

This is your public_key.

=cut

has public_key => (is => 'rw');

=head2 private_key(?$value)

This is your private_key.

=cut

has private_key => (is => 'rw');

=head2 environment(?$value)

This is your environment. The environment can be:

=over 4

=item development | integration

This is when you're using a local server for testing. It's unlikely you will

lib/WebService/Braintree/Configuration.pm  view on Meta::CPAN

        my ($self, $new_value, $old_value) = @_;
        my %valid = map { $_ => 1 } qw(
            development integration sandbox qa production
        );
        if (!$valid{$new_value}) {
            warn 'Assigned invalid value to WebService::Braintree::Configuration::environment';
        }

        if ($new_value eq 'integration') {
            $self->public_key('integration_public_key');
            $self->private_key('integration_private_key');
            $self->merchant_id('integration_merchant_id');
        }
    }
);

has gateway => (is  => 'ro', lazy => 1, default => sub {
    WebService::Braintree::Gateway->new({config => shift});
});

# This method is used in ::HTTP

lib/WebService/Braintree/HTTP.pm  view on Meta::CPAN

}

sub delete {
    my $self = shift;
    $self->make_request(DELETE => @_);
}

sub make_request {
    my ($self, $verb, $path, $params, $file) = @_;
    my $request = HTTP::Request->new($verb => $self->config->base_merchant_url . $path);
    $request->headers->authorization_basic($self->config->public_key, $self->config->private_key);

    if ($file) {
        my $boundary = DateTime->now->strftime('%Q');
        $request->content_type("multipart/form-data; boundary=${boundary}");

        my @form_params = map {
            $self->add_form_field($_, $params->{$_})
        } keys %{$params // {}};
        push @form_params, $self->add_file_part(file => $file);

lib/WebService/Braintree/TransparentRedirect/QueryString.pm  view on Meta::CPAN

    my $uri = URI->new;
    $uri->query($query_string);
    return { $uri->query_form};
}

sub hash_is_forged {
    my ($self, $query_string) = @_;
    if ($query_string =~ /(.*)(&|;)hash=(.*)/) {
        my $query_string_without_hash = $1;
        my $hash = $3;
        return $hash ne hexdigest($self->config->private_key, $query_string_without_hash);
    }
    return 1;
}

sub check_http_status {
    my($self, $query_string) = @_;
    my $params = $self->parse($query_string);
    confess "UnexpectedError: expected query string to have an http_status param" unless $params->{'http_status'};
    confess "AuthenticationError" if $params->{'http_status'} eq '401';
    confess "AuthorizationError"  if $params->{'http_status'} eq '403';

lib/WebService/Braintree/TransparentRedirectGateway.pm  view on Meta::CPAN

    my ($self, $params) = @_;
    $params->{'api_version'} = $self->gateway->config->api_version;
    $params->{'time'}        = time_string;
    $params->{'public_key'}  = $self->gateway->config->public_key;
    return $self->build_tr_data($params);
}

sub build_tr_data {
    my ($self, $params) = @_;
    my $query = hash_to_query_string($params);
    my $tr_hash = hexdigest($self->gateway->config->private_key, $query);
    return "$tr_hash|$query";
}

__PACKAGE__->meta->make_immutable;

1;
__END__

lib/WebService/Braintree/WebhookNotificationGateway.pm  view on Meta::CPAN


    # Definitively return undef if nothing is found.
    return;
}

sub _validate_signature {
    my ($self, $signature, $payload) = @_;

    my $matching_signature = $self->_matching_signature($signature, $payload);

    if (!defined($matching_signature) || $matching_signature ne hexdigest($self->gateway->config->private_key, $payload)) {
        confess "InvalidSignature";
    }

    return 1;
}

sub verify {
    my ($self, $challenge) = @_;

    if ($challenge !~ /^[a-f0-9]{20,32}$/) {
        confess "InvalidChallenge";
    }

    return $self->gateway->config->public_key . "|" . hexdigest($self->gateway->config->private_key, $challenge);
}

__PACKAGE__->meta->make_immutable;

1;
__END__

lib/WebService/Braintree/WebhookTestingGateway.pm  view on Meta::CPAN

use WebService::Braintree::WebhookNotification::Kind;

# This does not use Role::MakeRequest which provides the gateway attribute.
has 'gateway' => (is => 'ro');

sub sample_notification {
    my ($self, $kind, $id) = @_;

    my $sample_xml = $self->_sample_xml($kind, $id);
    my $payload = encode_base64($sample_xml);
    my $signature = $self->gateway->config->public_key . "|" . hexdigest($self->gateway->config->private_key, $payload);

    return ($signature, $payload);
}

sub _sample_xml {
    my ($self, $kind, $id) = @_;
    my $subject_sample_xml = $self->_subject_sample_xml($kind, $id);
    my $timestamp = strftime("%Y-%m-%dT%H:%M:%SZ", gmtime());

    return <<XML

lib/WebService/Braintree/WebhookTestingGateway.pm  view on Meta::CPAN

      </discounts>
    </subscription>
XML
}

sub _partner_merchant_connected_sample_xml {
    return <<XML
        <partner-merchant>
          <merchant-public-id>public_id</merchant-public-id>
          <public-key>public_key</public-key>
          <private-key>private_key</private-key>
          <partner-merchant-id>abc123</partner-merchant-id>
          <client-side-encryption-key>cse_key</client-side-encryption-key>
        </partner-merchant>
XML
}

sub _partner_merchant_disconnected_sample_xml {
    return <<XML
        <partner-merchant>
          <partner-merchant-id>abc123</partner-merchant-id>

t/lib/WebService/Braintree/TestHelper.pm  view on Meta::CPAN

        $class->export_to_level(1, @EXPORT);

        $config = WebService::Braintree->configuration;
        $config->environment($env);
        if ($env eq 'sandbox') {
            my $conf_file = 'sandbox_config.json';
            die "Can not run sandbox tests without $conf_file in distribution root" unless -e $conf_file;
            my $sandbox = decode_json( do { local $/; open my($f), $conf_file; <$f>} );
            $config->public_key($sandbox->{public_key});
            $config->merchant_id($sandbox->{merchant_id});
            $config->private_key($sandbox->{private_key});
        }
    }
}

# The sandbox must have specific items in it with specific values.
sub verify_sandbox {
    subtest verify_sandbox => sub {
        my %required_addons = (
            increase_30 => superhashof(bless {
                id => 'increase_30',

t/sandbox/README  view on Meta::CPAN

In order to run these tests you need a file named 'sandbox_config.json' in the current directory.
The file is formatted thusly:

{
  "public_key": "xxx",
  "merchant_id": "xxx",
  "private_key": "xxx"
}

Should you want to contribute to the development of Webservice::Braintree,
please mail zarquon@cpan.org for the shared credentials used by the
development team (however for casual development your own sandbox
credentials should mostly be fine).

You also need to have created elements in the control panel. These items are
verified by test preambles, but the description of how to create them is here.

t/sandbox/configuration.t  view on Meta::CPAN


    cmp_ok $result->transaction->amount, '==', $amount;
};

subtest "configuration two" => sub {
    my $config = WebService::Braintree::Configuration->new;

    $config->environment("sandbox");
    $config->public_key("it_should_explode");
    $config->merchant_id(WebService::Braintree::TestHelper->config->merchant_id);
    $config->private_key("with_these_values");

    my $gateway = $config->gateway;
    should_throw("AuthenticationError", sub {
        $gateway->transaction->create({
            type => "sale",
            amount => amount(5, 15),
        });
    });
};

t/unit/configuration.t  view on Meta::CPAN


use lib qw(lib t/lib);

use WebService::Braintree;

my $config = WebService::Braintree->configuration;

$config->environment("sandbox");
$config->public_key("integration_public_key");
$config->merchant_id("integration_merchant_id");
$config->private_key("integration_private_key");

$config = WebService::Braintree->configuration;

subtest 'server()' => sub {
    my %choices = (
        development => 'localhost',
        integration => 'localhost',
        sandbox     => 'api.sandbox.braintreegateway.com',
        qa          => 'qa-master.braintreegateway.com',
        production  => 'api.braintreegateway.com',

t/unit/digest.t  view on Meta::CPAN

# vim: sw=4 ts=4 ft=perl

use 5.010_001;
use strictures 1;

use Test::More;

use lib qw(lib t/lib);

my $query_string = 'one=1&two=2&http_status=200';
my $private_key = 'integration_private_key';
my $expected_hash = '3970ae558c51cf6f54340b5b1842d47ba1f5a19e';

use WebService::Braintree::Digest qw(hexdigest);

is(
    hexdigest($private_key, $query_string),
    $expected_hash,
    'Braintree digest works',
);

done_testing();

t/unit/transparent_redirect_query_string.t  view on Meta::CPAN

use WebService::Braintree::TestHelper;
use WebService::Braintree::TransparentRedirect::QueryString;
use WebService::Braintree::Digest qw(hexdigest);
use WebService::Braintree::Configuration;

my $config = WebService::Braintree::Configuration->new({environment => 'integration'});

my $tr = WebService::Braintree::TransparentRedirect::QueryString->new(config => $config);
my $query_string = 'one=1&two=2&http_status=200';
my $cgi_query_string = 'one=1;two=2;http_status=200';
my $hash = hexdigest($config->private_key, $query_string);
my $cgi_hash = hexdigest($config->private_key, $cgi_query_string);
my $complete_query_string = with_hash($query_string);
my $cgi_complete_query_string = "${cgi_query_string};hash=${cgi_hash}";
my %query_as_hash = (one => 1, two => 2, http_status => 200, hash => $hash);

subtest 'check query string for forgery' => sub {
    ok($tr->validate($complete_query_string), 'Query String is valid');
    should_throw('ForgedQueryString', sub {
        $tr->validate($query_string);
    }, 'Query String is invalid without hash');
    should_throw('ForgedQueryString', sub {

t/unit/transparent_redirect_query_string.t  view on Meta::CPAN

    foreach (@error_types) {
        my($error, $code) = @$_;
        should_throw($error, sub {
            $tr->validate(with_hash("http_status=${code}"));
        }, "Raises $error if status is $code");
    }
};

sub with_hash {
    my $query_string = shift;
    my $hash = hexdigest($config->private_key, $query_string);
    return "${query_string}&hash=${hash}";
}

done_testing();

t/unit/webhook_notification.t  view on Meta::CPAN

        WebService::Braintree::WebhookNotification::Kind::PartnerMerchantConnected,
        'my_id',
    );

    my $webhook_notification = WebService::Braintree::WebhookNotification->parse($signature, $payload);

    is $webhook_notification->kind, WebService::Braintree::WebhookNotification::Kind::PartnerMerchantConnected;
    is $webhook_notification->partner_merchant->partner_merchant_id, 'abc123';
    is $webhook_notification->partner_merchant->merchant_public_id, 'public_id';
    is $webhook_notification->partner_merchant->public_key, 'public_key';
    is $webhook_notification->partner_merchant->private_key, 'private_key';
    is $webhook_notification->partner_merchant->client_side_encryption_key, 'cse_key';
};

subtest 'sample_notification builds a sample notification for partner merchant disconnected', sub {
    my ($signature, $payload) = WebService::Braintree::WebhookTesting->sample_notification(
        WebService::Braintree::WebhookNotification::Kind::PartnerMerchantDisconnected,
        'my_id',
    );

    my $webhook_notification = WebService::Braintree::WebhookNotification->parse($signature, $payload);



( run in 0.838 second using v1.01-cache-2.11-cpan-a5abf4f5562 )