From 5f4261beda268a2bb7f6e111c1e68bd3e0961764 Mon Sep 17 00:00:00 2001 From: "Bradley M. Kuhn" Date: Mon, 30 Dec 2013 19:06:55 -0500 Subject: [PATCH 1/6] ProfileID is a valid search term for TransactionSearch in the PayPal SOAP API: I learned this by reading: https://developer.paypal.com/webapps/developer/docs/classic/api/merchant/TransactionSearch_API_Operation_SOAP/ --- lib/Business/PayPal/API/TransactionSearch.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Business/PayPal/API/TransactionSearch.pm b/lib/Business/PayPal/API/TransactionSearch.pm index 0e8971f..b93bca7 100644 --- a/lib/Business/PayPal/API/TransactionSearch.pm +++ b/lib/Business/PayPal/API/TransactionSearch.pm @@ -20,6 +20,7 @@ sub TransactionSearch { Payer => 'ebl:EmailAddressType', Receiver => 'ebl:EmailAddressType', ReceiptID => 'xs:string', + ProfileID => 'xs:string', TransactionID => 'xs:string', InvoiceID => 'xs:string', PayerName => 'xs:string', From 7198b854b9f32a9e28a4b8558b8550874c50af0b Mon Sep 17 00:00:00 2001 From: "Bradley M. Kuhn" Date: Thu, 1 Jan 2015 16:36:58 -0500 Subject: [PATCH 2/6] Add SellerEmail variable for testing data. There are some situations were having the email address of the seller is useful for testing. This change allows for it as a parameter to the tests. --- auth.sample.3token | 1 + auth.sample.cert | 1 + t/API.pl | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/auth.sample.3token b/auth.sample.3token index 2c21d05..509bf27 100644 --- a/auth.sample.3token +++ b/auth.sample.3token @@ -1,3 +1,4 @@ Username = test1_api.mydomain.tld Password = XXXXXXXXXXXXXXXX Signature = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +SellerEmail = email-of-business-test-account@mydomain.tld diff --git a/auth.sample.cert b/auth.sample.cert index 9af9d49..d97ae78 100644 --- a/auth.sample.cert +++ b/auth.sample.cert @@ -2,3 +2,4 @@ Username = test1_api.mydomain.tld Password = myapipassword CertFile = /www/var/cert_key_pem.txt KeyFile = /www/var/cert_key_pem.txt +SellerEmail = email-of-business-test-account@mydomain.tld diff --git a/t/API.pl b/t/API.pl index 8c2f84d..121be44 100644 --- a/t/API.pl +++ b/t/API.pl @@ -26,7 +26,7 @@ sub do_args { my @variables = qw( Username Password Signature Subject timeout CertFile KeyFile PKCS12File PKCS12Password - BuyerEmail + BuyerEmail SellerEmail ); my %patterns = (); From c5f62dbdb186859473c394cdf69f489a24a909a4 Mon Sep 17 00:00:00 2001 From: "Bradley M. Kuhn" Date: Thu, 1 Jan 2015 17:06:49 -0500 Subject: [PATCH 3/6] Beginnings of tests for subscription payments. These tests verify a TransactionSearch for ProfileID, and also serve as an example of the method to find subscriptions using that method. I've also added to the test a creation of an HTML form that can be used to create a transaction that will allow the test to pass. This is a hack, not unlike the hacks existing in the tests now that ask for pasting of a transaction ID. Long term, if someone wants to do the work, using WWW:Mechanize or some other method for full automation of these tests might be useful, but I think the generated HTML file is a step forward from the cut-and-paste solution currently in use. --- .gitignore | 1 + t/SubscriptionPayments.t | 107 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 t/SubscriptionPayments.t diff --git a/.gitignore b/.gitignore index eac2520..420c0be 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ auth.txt blib perltidy.LOG pm_to_blib +subscription-payment.html diff --git a/t/SubscriptionPayments.t b/t/SubscriptionPayments.t new file mode 100644 index 0000000..91cff12 --- /dev/null +++ b/t/SubscriptionPayments.t @@ -0,0 +1,107 @@ +# -*- mode: cperl -*- +use Test::More; +use strict; +if ( !$ENV{WPP_TEST} || !-f $ENV{WPP_TEST} ) { + plan skip_all => + 'No WPP_TEST env var set. Please see README to run tests'; +} +else { + plan tests => 5; +} + +use_ok( 'Business::PayPal::API::TransactionSearch' ); +######################### + +require 't/API.pl'; + +my %args = do_args(); + +=pod + +The following four tests shows the methodology to use TransactionSearch to +find transactions that are part of the same ProfileID. This method was +discovered by trial-and-error. Specifically, it's somewhat odd that +TransactionSearch is used with the parameter of 'ProfileID' with the value +set to a specific TransactionID to find the ProfileID via the "Created" +transaction. Then, in turn, that ProfileID can find the subscription payments +related to the original transaction. + +This works, and seems to be correct, albeit odd. + +=cut + +open(SUBSCRIPTION_PAY_HTML, ">", "subscription-payment.html") + or die "unable to open subscription-payment.html: $!"; +print SUBSCRIPTION_PAY_HTML <<_SUBSCRIPTION_PAYMENT_DATA_ + + +
+ + + + + + + + + + + + + + +
+ + +_SUBSCRIPTION_PAYMENT_DATA_ + ; +close(SUBSCRIPTION_PAY_HTML); die "unable to write subscription-payment.html: $!" if ($? != 0); + +use Cwd; my $cwd = getcwd; + +print STDERR <<"_PROFILEID_"; +Please note the next series of tests will not succeeed unless there is at +least one transaction that is part of a subscription payments in your business +account. + +if you haven't made one yet, you can visit: + file:///$cwd/subscription-payment.html + +and use the sandbox buyer account to make the payment. +_PROFILEID_ + +my $startdate = '1998-01-01T01:45:10.00Z'; + +my $ts = new Business::PayPal::API::TransactionSearch( %args ); + +my $resp = $ts->TransactionSearch(StartDate => $startdate); + +use Data::Dumper; + +ok(scalar @{$resp} > 0, "Some transactions found"); + +my($profileID, %possibleTransactionIDs); +foreach my $record (@{$resp}) { + if ($record->{Type} =~ /Recurring/) { + if ($record->{Status} =~ /Completed/) { + $possibleTransactionIDs{$record->{TransactionID}} = $record; + } elsif ($record->{Status} =~ /Created/) { + $profileID = $record->{TransactionID}; + } + } +} +ok(defined $profileID, "Subscription Payment Creation Record and ProfileID Found"); +ok(scalar(keys %possibleTransactionIDs) > 0, "Subscription Payment Transactions Found"); + +$resp = $ts->TransactionSearch(StartDate => $startdate, + ProfileID => $profileID); + +my $foundAtLeastOne = 0; +foreach my $record (@{$resp}) { + # One of these will need to be in the possibleTransactionID list (i.e., + # we're assuming that at least one payment has occured in this repeating). + if (defined $possibleTransactionIDs{$record->{TransactionID}}) { + $foundAtLeastOne = 1; last; + } +} +ok($foundAtLeastOne, "Found one payment transaction under the given Profile ID"); From 9045d3d5115da7353027a334c6fb9d79d1ff4585 Mon Sep 17 00:00:00 2001 From: "Bradley M. Kuhn" Date: Fri, 2 Jan 2015 11:42:10 -0500 Subject: [PATCH 4/6] Switch to use autodie to simplify code. @oalders suggests in a pull request comment: > If we use autodie then we won't need to check for success on open(). I've made this change to accommodate that suggestion. --- t/SubscriptionPayments.t | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/t/SubscriptionPayments.t b/t/SubscriptionPayments.t index 91cff12..2a197bd 100644 --- a/t/SubscriptionPayments.t +++ b/t/SubscriptionPayments.t @@ -1,6 +1,8 @@ # -*- mode: cperl -*- use Test::More; use strict; +use autodie qw(:all); + if ( !$ENV{WPP_TEST} || !-f $ENV{WPP_TEST} ) { plan skip_all => 'No WPP_TEST env var set. Please see README to run tests'; @@ -30,8 +32,8 @@ This works, and seems to be correct, albeit odd. =cut -open(SUBSCRIPTION_PAY_HTML, ">", "subscription-payment.html") - or die "unable to open subscription-payment.html: $!"; +open(SUBSCRIPTION_PAY_HTML, ">", "subscription-payment.html"); + print SUBSCRIPTION_PAY_HTML <<_SUBSCRIPTION_PAYMENT_DATA_ @@ -55,7 +57,7 @@ print SUBSCRIPTION_PAY_HTML <<_SUBSCRIPTION_PAYMENT_DATA_ _SUBSCRIPTION_PAYMENT_DATA_ ; -close(SUBSCRIPTION_PAY_HTML); die "unable to write subscription-payment.html: $!" if ($? != 0); +close(SUBSCRIPTION_PAY_HTML); use Cwd; my $cwd = getcwd; From 7aeeb15fcf04dde62e2b84157c6d6713dbe96f7b Mon Sep 17 00:00:00 2001 From: "Bradley M. Kuhn" Date: Fri, 2 Jan 2015 11:43:21 -0500 Subject: [PATCH 5/6] Consolidate use's to top of file. @oalders suggests in a comment on my pull request: > Could we move this use up to to the top of the file with the others? So I've done so here. --- t/SubscriptionPayments.t | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/t/SubscriptionPayments.t b/t/SubscriptionPayments.t index 2a197bd..f4aa8b6 100644 --- a/t/SubscriptionPayments.t +++ b/t/SubscriptionPayments.t @@ -2,6 +2,7 @@ use Test::More; use strict; use autodie qw(:all); +use Cwd; if ( !$ENV{WPP_TEST} || !-f $ENV{WPP_TEST} ) { plan skip_all => @@ -59,7 +60,7 @@ _SUBSCRIPTION_PAYMENT_DATA_ ; close(SUBSCRIPTION_PAY_HTML); -use Cwd; my $cwd = getcwd; +my $cwd = getcwd; print STDERR <<"_PROFILEID_"; Please note the next series of tests will not succeeed unless there is at From dd503a3080d187ab66d2368001595c306c32b16a Mon Sep 17 00:00:00 2001 From: "Bradley M. Kuhn" Date: Fri, 2 Jan 2015 11:44:02 -0500 Subject: [PATCH 6/6] Remove unnecessary use floating around in code. @oalders noted in patch review on a pull request: > Looks like this might be left over from debugging? And he was indeed correct. ;) I've removed the use. Data::Dumper isn't used by this test. --- t/SubscriptionPayments.t | 2 -- 1 file changed, 2 deletions(-) diff --git a/t/SubscriptionPayments.t b/t/SubscriptionPayments.t index f4aa8b6..82876b7 100644 --- a/t/SubscriptionPayments.t +++ b/t/SubscriptionPayments.t @@ -79,8 +79,6 @@ my $ts = new Business::PayPal::API::TransactionSearch( %args ); my $resp = $ts->TransactionSearch(StartDate => $startdate); -use Data::Dumper; - ok(scalar @{$resp} > 0, "Some transactions found"); my($profileID, %possibleTransactionIDs);