jenkins-bot has submitted this change and it was merged.

Change subject: Adyen audit processor
......................................................................


Adyen audit processor

A lot like AstroPay's. Handles donations, refunds, and chargebacks.

Bug: T121129
Change-Id: Icbdbe3fa2c0537c622a4621095527b3d4a7c1769
---
M Core/UtcDate.php
A PaymentProviders/Adyen/Audit/AdyenAudit.php
M PaymentProviders/Adyen/ExpatriatedMessages/ReportAvailable.php
A PaymentProviders/Adyen/Jobs/DownloadReportJob.php
D PaymentProviders/Adyen/Jobs/ProcessAccountingReportJob.php
A PaymentProviders/Adyen/ReferenceData.php
A PaymentProviders/Adyen/Tests/Data/chargeback.csv
A PaymentProviders/Adyen/Tests/Data/donation.csv
A PaymentProviders/Adyen/Tests/Data/refund.csv
A PaymentProviders/Adyen/Tests/phpunit/AuditTest.php
M config_defaults.php
M phpunit.xml
12 files changed, 461 insertions(+), 158 deletions(-)

Approvals:
  XenoRyet: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/Core/UtcDate.php b/Core/UtcDate.php
index 11c1701..b2ef976 100644
--- a/Core/UtcDate.php
+++ b/Core/UtcDate.php
@@ -6,9 +6,9 @@
 use SmashPig\Core\Logging\Logger;
 
 class UtcDate {
-       public static function getUtcTimestamp( $dateString ) {
+       public static function getUtcTimestamp( $dateString, $timeZone = 'UTC' 
) {
                try {
-                       $obj = new DateTime( $dateString, new DateTimeZone( 
'UTC' ) );
+                       $obj = new DateTime( $dateString, new DateTimeZone( 
$timeZone ) );
                        return $obj->getTimestamp();
                } catch ( Exception $ex ) {
                        Logger::warning ( 'Caught date exception: ' . 
$ex->getMessage(), $dateString );
diff --git a/PaymentProviders/Adyen/Audit/AdyenAudit.php 
b/PaymentProviders/Adyen/Audit/AdyenAudit.php
new file mode 100644
index 0000000..42f9dda
--- /dev/null
+++ b/PaymentProviders/Adyen/Audit/AdyenAudit.php
@@ -0,0 +1,175 @@
+<?php namespace SmashPig\PaymentProviders\Adyen\Audit;
+
+use OutOfBoundsException;
+use SmashPig\Core\UtcDate;
+use SmashPig\PaymentProviders\Adyen\ReferenceData;
+
+/**
+ * Class AdyenAudit
+ * @package SmashPig\PaymentProviders\Adyen\Audit
+ * Processes Adyen's Settlement Detail Reports.
+ * Sends donations, chargebacks, and refunds to queue.
+ * 
https://docs.adyen.com/manuals/reporting-manual/settlement-detail-report-structure/settlement-detail-report-journal-types
+ */
+class AdyenAudit {
+
+       protected $columnHeaders;
+       protected $ignoredStatuses;
+       protected $fileData = array();
+       protected static $ignoredTypes = array(
+               'Fee',
+               'MiscCosts',
+               'MerchantPayout',
+               'ChargebackReversed', // oh hey, we could try to handle these
+               'RefundedReversed',
+               'DepositCorrection',
+               'InvoiceDeduction',
+               'MatchedStatement',
+               'ManualCorrected',
+               'AuthorisationSchemeFee',
+               'BankInstructionReturned',
+               'InternalCompanyPayout',
+               'EpaPaid',
+               'BalanceTransfer',
+               'PaymentCost',
+               'SettleCost',
+               'PaidOut',
+               'PaidOutReversed',
+       );
+
+       public function __construct() {
+               $this->columnHeaders = array(
+                       'Company Account',
+                       'Merchant Account',
+                       'Psp Reference',
+                       'Merchant Reference',
+                       'Payment Method',
+                       'Creation Date',
+                       'TimeZone',
+                       'Type',
+                       'Modification Reference',
+                       'Gross Currency',
+                       'Gross Debit (GC)',
+                       'Gross Credit (GC)',
+                       'Exchange Rate',
+                       'Net Currency',
+                       'Net Debit (NC)',
+                       'Net Credit (NC)',
+                       'Commission (NC)',
+                       'Markup (NC)',
+                       'Scheme Fees (NC)',
+                       'Interchange (NC)',
+                       'Payment Method Variant',
+                       'Modification Merchant Reference',
+                       'Batch Number',
+                       'Reserved4',
+                       'Reserved5',
+                       'Reserved6',
+                       'Reserved7',
+                       'Reserved8',
+                       'Reserved9',
+                       'Reserved10',
+               );
+       }
+
+       // TODO base class this?
+       public function parseFile( $path ) {
+               $this->path = $path;
+               $this->file = fopen( $path, 'r' );
+
+               $ignoreLines = 1;
+               for ( $i = 0; $i < $ignoreLines; $i++ ) {
+                       fgets( $this->file );
+               }
+
+               while ( $line = fgetcsv( $this->file, 0, ',', '"', '\\' ) ) {
+                       try {
+                               $this->parseLine( $line );
+                       } catch ( NormalizationException $ex ) {
+                               // TODO: actually throw these below
+                               Logger::error( $ex->getMessage() );
+                       }
+               }
+               fclose( $this->file );
+
+               return $this->fileData;
+       }
+
+       protected function parseLine( $line ) {
+               $row = array_combine( $this->columnHeaders, $line );
+               $type = $row['Type'];
+               if ( in_array( $type, self::$ignoredTypes ) ) {
+                       return;
+               }
+
+               $msg = array(
+                       'gateway' => 'adyen',
+                       'log_id' => $row['Merchant Reference'],
+                       'date' => $this->getDate( $row ),
+               );
+               $parts = explode( '.', $row['Merchant Reference'] );
+               $msg['contribution_tracking_id'] = $parts[0];
+
+               switch( $type ) {
+                       case 'Settled':
+                               $this->parseDonation( $row, $msg );
+                               break;
+                       case 'Chargeback':
+                       case 'Refunded':
+                               $this->parseRefund( $row, $msg );
+                               break;
+                       default:
+                               throw new OutOfBoundsException( "Unknown audit 
line type {$row['Type']}." );
+               }
+
+               $this->fileData[] = $msg;
+       }
+
+       protected function parseRefund( array $row, array &$msg ) {
+               $msg['gross'] = $row['Gross Debit (GC)']; // Actually paid to 
donor
+               $msg['gross_currency'] = $row['Gross Currency'];
+               // 'Net Debit (NC)' is the amount we paid including fees
+               // 'Net Currency' is the currency we paid in
+               // Deal with these when queue consumer can understand them
+
+               $msg['gateway_parent_id'] = $row['Psp Reference'];
+               $msg['gateway_refund_id'] = $row['Modification Reference'];
+               if ( $row['Type'] === 'Chargeback' ) {
+                       $msg['type'] = 'chargeback';
+               } else {
+                       $msg['type'] = 'refund';
+               }
+       }
+
+       protected function parseDonation( array $row, array &$msg ) {
+               $msg['gateway_txn_id'] = $row['Psp Reference'];
+
+               $msg['currency'] = $row['Gross Currency'];
+               $msg['gross'] = $row['Gross Credit (GC)'];
+               // fee is given in settlement currency
+               // but queue consumer expects it in original
+               $exchange = $row['Exchange Rate'];
+               $fee = $row['Commission (NC)'] +
+                       $row['Markup (NC)'] +
+                       $row['Scheme Fees (NC)'] +
+                       $row['Interchange (NC)'];
+               $msg['fee'] = round( $fee / $exchange, 2 );
+
+               // shouldn't this be settled_net or settled_amount?
+               $msg['settled_gross'] = $row['Net Credit (NC)'];
+               $msg['settled_currency'] = $row['Net Currency'];
+               $msg['settled_fee'] = $fee;
+
+               list( $method, $submethod ) = 
ReferenceData::decodePaymentMethod(
+                       $row['Payment Method'], $row['Payment Method Variant']
+               );
+               $msg['payment_method'] = $method;
+               $msg['payment_submethod'] = $submethod;
+       }
+
+       protected function getDate( $row ) {
+               $local = $row['Creation Date'];
+               $zone = $row['TimeZone'];
+               return UtcDate::getUtcTimestamp( $local, $zone );
+       }
+}
diff --git a/PaymentProviders/Adyen/ExpatriatedMessages/ReportAvailable.php 
b/PaymentProviders/Adyen/ExpatriatedMessages/ReportAvailable.php
index 06189c7..d9996e4 100644
--- a/PaymentProviders/Adyen/ExpatriatedMessages/ReportAvailable.php
+++ b/PaymentProviders/Adyen/ExpatriatedMessages/ReportAvailable.php
@@ -2,7 +2,7 @@
 
 use SmashPig\Core\Context;
 use SmashPig\Core\Logging\Logger;
-use SmashPig\PaymentProviders\Adyen\Jobs\ProcessAccountingReportJob;
+use SmashPig\PaymentProviders\Adyen\Jobs\DownloadReportJob;
 
 class ReportAvailable extends AdyenMessage {
        /**
@@ -21,9 +21,9 @@
                );
 
                $jobQueueObj = Context::get()->getConfiguration()->obj( 
'data-store/jobs' );
-               if ( strpos( $this->pspReference, 'payments_accounting_report' 
) === 0 ) {
+               if ( strpos( $this->pspReference, 'settlement_detail_report' ) 
=== 0 ) {
                        $jobQueueObj->addObject(
-                               ProcessAccountingReportJob::factory(
+                               DownloadReportJob::factory(
                                        $this->merchantAccountCode,
                                        $this->reason
                                )
diff --git a/PaymentProviders/Adyen/Jobs/DownloadReportJob.php 
b/PaymentProviders/Adyen/Jobs/DownloadReportJob.php
new file mode 100644
index 0000000..2f566c1
--- /dev/null
+++ b/PaymentProviders/Adyen/Jobs/DownloadReportJob.php
@@ -0,0 +1,84 @@
+<?php namespace SmashPig\PaymentProviders\Adyen\Jobs;
+
+use SmashPig\Core\Context;
+use SmashPig\Core\DataFiles\HeadedCsvReader;
+use SmashPig\Core\Logging\TaggedLogger;
+use SmashPig\Core\SmashPigException;
+use SmashPig\Core\Jobs\RunnableJob;
+
+/**
+ * Download Adyen settlement detail reports. These reports are named
+ * settlement_detail_report_batch_[n].csv
+ *
+ * @package SmashPig\PaymentProviders\Adyen\Jobs
+ */
+class DownloadReportJob extends RunnableJob {
+
+       /** @var TaggedLogger */
+       protected $logger;
+
+       protected $account;
+       protected $reportUrl;
+
+       protected $downloadLoc;
+
+       public static function factory( $account, $url ) {
+               $obj = new DownloadReportJob();
+
+               $obj->account = $account;
+               $obj->reportUrl = $url;
+
+               return $obj;
+       }
+
+       public function execute() {
+               $this->logger = new TaggedLogger( __CLASS__ );
+               $c = Context::get()->getConfiguration();
+
+               // Construct the temporary file path
+               $fileName = basename( $this->reportUrl );
+               $this->downloadLoc =
+                       $c->val( 
"payment-provider/adyen/accounts/{$this->account}/report-location" ) . '/' .
+                       $fileName;
+
+               $user = $c->val( 
"payment-provider/adyen/accounts/{$this->account}/report-username" );
+               $pass = $c->val( 
"payment-provider/adyen/accounts/{$this->account}/report-password" );
+
+               $this->logger->info(
+                       "Beginning report download from {$this->reportUrl} 
using username {$user} into {$this->downloadLoc}"
+               );
+
+               $fp = fopen( $this->downloadLoc, 'w' );
+               if ( !$fp ) {
+                       $str = "Could not open {$this->downloadLoc} for 
writing! Will not download report.";
+                       $this->logger->error( $str );
+                       throw new SmashPigException( $str );
+               }
+
+               $ch = curl_init();
+               curl_setopt($ch, CURLOPT_URL, $this->reportUrl);
+
+               curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
+               curl_setopt($ch, CURLOPT_FILE, $fp );
+
+               curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
+
+               curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
+               curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
+               curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY );
+               curl_setopt($ch, CURLOPT_USERPWD, "{$user}:{$pass}" );
+
+               $result = curl_exec($ch);
+               $httpCode = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
+               $error = curl_error( $ch );
+               curl_close( $ch );
+
+               if ( $result === false ) {
+                       $this->logger->error( "Could not download report due to 
cURL error {$error}" );
+                       throw new SmashPigException( "Could not download 
report." );
+               } elseif ( $httpCode !== 200 ) {
+                       $this->logger->error( "Report downloaded(?), but with 
incorrect HTTP code: {$httpCode}" );
+                       throw new SmashPigException( "Could not download 
report." );
+               }
+       }
+}
diff --git a/PaymentProviders/Adyen/Jobs/ProcessAccountingReportJob.php 
b/PaymentProviders/Adyen/Jobs/ProcessAccountingReportJob.php
deleted file mode 100644
index 4366ed9..0000000
--- a/PaymentProviders/Adyen/Jobs/ProcessAccountingReportJob.php
+++ /dev/null
@@ -1,150 +0,0 @@
-<?php namespace SmashPig\PaymentProviders\Adyen\Jobs;
-
-use SmashPig\Core\Context;
-use SmashPig\Core\DataFiles\HeadedCsvReader;
-use SmashPig\Core\Logging\TaggedLogger;
-use SmashPig\Core\SmashPigException;
-use SmashPig\Core\Jobs\RunnableJob;
-
-/**
- * Process Adyen end of day payment reports. These reports are named
- * payments_accounting_report_[yyyy]_[mm]_[dd].csv
- *
- * @package SmashPig\PaymentProviders\Adyen\Jobs
- */
-class ProcessAccountingReportJob extends RunnableJob {
-
-       /** @var TaggedLogger */
-       protected $logger;
-
-       protected $account;
-       protected $reportUrl;
-
-       protected $downloadLoc;
-
-       public static function factory( $account, $url ) {
-               $obj = new ProcessAccountingReportJob();
-
-               $obj->account = $account;
-               $obj->reportUrl = $url;
-
-               return $obj;
-       }
-
-       public function execute() {
-               $this->logger = new TaggedLogger( __CLASS__ );
-               $c = Context::get()->getConfiguration();
-
-               // Construct the temporary file path
-               $fileName = basename( $this->reportUrl );
-               $this->downloadLoc =
-                       $c->val( 
"payment-provider/adyen/accounts/{$this->account}/report-location" ) . '/' .
-                       $fileName;
-
-               // Actually get the file
-               $this->downloadLog();
-
-               // Now iterate through; finding all the ones marked Authorised 
and SentForSettle
-               // The Authorised entries at the end that do not have a 
SentForSettle need to be
-               // reviewed in the payment console.
-               // TODO: we should confirm settled transactions like the rest 
of the
-               // audit parsers.
-               $this->logger->debug( "Finding uncaptured authorizations" );
-               $f = new HeadedCsvReader( $this->downloadLoc );
-               $tempQueue = array();
-
-               foreach ( $f as $row ) {
-                       switch ( $f->extractCol( 'Record Type', $row ) ) {
-                               case 'Authorised':
-                                       $tempQueue[$f->extractCol( 'Psp 
Reference', $row )] = $row;
-                                       break;
-
-                               case 'SentForSettle':
-                                       unset( $tempQueue[$f->extractCol( 'Psp 
Reference', $row )] );
-                                       // TODO: Audit this row; probably send 
it to an audit queue
-                                       break;
-
-                               default:
-                                       // Don't care :)
-                                       break;
-                       }
-               }
-
-               $tqc = count( $tempQueue );
-               $this->logger->debug(
-                       "Of {$f->key()} rows, {$tqc} need to be reprocessed.",
-                       array( 'headers' => $f->headers(), 'values' => 
$tempQueue )
-               );
-
-               foreach ( $tempQueue as $pspRef => $row ) {
-                       $correlationId = 'adyen-' . $f->extractCol( 'Merchant 
Reference', $row );
-                       $this->logger->enterContext( "$correlationId" );
-
-                       $currency = $f->extractCol( 'Payment Currency', $row );
-                       $amount = floatval( $f->extractCol( 'Authorised (PC)', 
$row ) );
-                       $account = $f->extractCol( 'Merchant Account', $row );
-
-                       $this->logger->info(
-                               "Please review authorization for {$currency} 
{$amount} with id {$correlationId} and " .
-                               "psp reference {$pspRef}."
-                       );
-
-                       $this->logger->leaveContext(); // Must be the last line 
in this loop
-               }
-
-               // OK; we're done here, move the file to the archive folder
-               try {
-                       $archiveLocation =
-                               $c->val( 
"payment-provider/adyen/accounts/{$this->account}/report-archive-location" );
-                       rename( $this->downloadLoc, $archiveLocation . '/' . 
$fileName );
-               } catch ( ConfigurationKeyException $ex ) {
-                       $this->logger->warning( 'Report archive location not 
configured!' );
-               }
-
-               return true;
-       }
-
-       protected function downloadLog() {
-               $c = Context::get()->getConfiguration();
-
-               $user = $c->val( 
"payment-provider/adyen/accounts/{$this->account}/report-username" );
-               $pass = $c->val( 
"payment-provider/adyen/accounts/{$this->account}/report-password" );
-
-               $this->logger->info(
-                       "Beginning log download from {$this->reportUrl} using 
username {$user} into {$this->downloadLoc}"
-               );
-
-               $fp = fopen( $this->downloadLoc, 'w' );
-               if ( !$fp ) {
-                       $str = "Could not open {$this->downloadLoc} for 
writing! Will not download/process report.";
-                       $this->logger->error( $str );
-                       throw new SmashPigException( $str );
-               }
-
-               $ch = curl_init();
-               curl_setopt($ch, CURLOPT_URL, $this->reportUrl);
-
-               curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
-               curl_setopt($ch, CURLOPT_FILE, $fp );
-
-               curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
-
-               curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
-               curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
-               curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY );
-               curl_setopt($ch, CURLOPT_USERPWD, "{$user}:{$pass}" );
-
-               $result = curl_exec($ch);
-               $httpCode = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
-               $error = curl_error( $ch );
-               curl_close( $ch );
-
-               if ( $result === false ) {
-                       $this->logger->error( "Could not download report due to 
cURL error {$error}" );
-                       throw new SmashPigException( "Could not download 
report." );
-               } elseif ( $httpCode !== 200 ) {
-                       $this->logger->error( "Report downloaded(?), but with 
incorrect HTTP code: {$httpCode}" );
-                       throw new SmashPigException( "Could not download 
report." );
-               }
-       }
-}
diff --git a/PaymentProviders/Adyen/ReferenceData.php 
b/PaymentProviders/Adyen/ReferenceData.php
new file mode 100644
index 0000000..872dea7
--- /dev/null
+++ b/PaymentProviders/Adyen/ReferenceData.php
@@ -0,0 +1,104 @@
+<?php namespace SmashPig\PaymentProviders\Adyen;
+
+use OutOfBoundsException;
+
+class ReferenceData {
+
+       static $methods = array(
+               'alipay' => array(
+                       'method' => 'ew',
+                       'submethod' => 'ew_alipay',
+               ),
+               'amex' => array(
+                       'method' => 'cc',
+                       'submethod' => 'amex',
+               ),
+               // International Bank Transfer (IBAN)
+               'banktransfer_IBAN' => array(
+                       'method' => 'bt',
+                       'submethod' => 'iban',
+               ),
+               // China Union Pay
+               'cup' => array(
+                       'method' => 'cc',
+                       'submethod' => 'cup',
+               ),
+               'diners' => array(
+                       'method' => 'cc',
+                       'submethod' => 'dc',
+               ),
+               // Sofortüberweisung
+               'directEbanking' => array(
+                       'method' => 'rtbt',
+                       'submethod' => 'rtbt_sofortuberweisung',
+               ),
+               'discover' => array(
+                       'method' => 'cc',
+                       'submethod' => 'discover',
+               ),
+               'dotpay' => array(
+                       'method' => 'ew',
+                       'submethod' => 'ew_dotpay',
+               ),
+               'ideal' => array(
+                       'method' => 'rtbt',
+                       'submethod' => 'rtbt_ideal',
+               ),
+               'mc' => array(
+                       'method' => 'cc',
+                       'submethod' => 'mc',
+                       'variants' => array(
+                               'mcdebit' => 'mc-debit',
+                       ),
+               ),
+               'multibanco' => array(
+                       'method' => 'rtbt',
+                       'submethod' => 'rtbt_multibanco',
+               ),
+               'safetypay' => array(
+                       'method' => 'rtbt',
+                       'submethod' => 'rtbt_safetypay',
+               ),
+               'sepadirectdebit' => array(
+                       'method' => 'dd',
+                       'submethod' => 'dd_sepa',
+               ),
+               'tenpay' => array(
+                       'method' => 'ew',
+                       'submethod' => 'ew_tenpay',
+               ),
+               'trustly' => array(
+                       'method' => 'obt',
+                       'submethod' => 'trustly',
+               ),
+               'visa' => array(
+                       'method' => 'cc',
+                       'submethod' => 'visa',
+                       'variants' => array(
+                               'visabeneficial' => 'visa-beneficial', // 
guessing at Adyen code
+                               'visadebit' => 'visa-debit',
+                               'visaelectron' => 'visa-electron', // guessing 
at Adyen code
+                       )
+               ),
+       );
+
+       /**
+        * @param string $method Adyen's 'Payment Method'
+        * @param string $variant Adyen's 'Payment Method Variant'
+        * @returns array first entry is our payment_method, second is our 
payment_submethod
+        */
+       public static function decodePaymentMethod( $method, $variant ) {
+               if ( !array_key_exists( $method, self::$methods ) ) {
+                       throw new OutOfBoundsException( "Unknown Payment Method 
$method " );
+               }
+               $entry = self::$methods[$method];
+               $ourMethod = $entry['method'];
+               if ( $variant && array_key_exists( 'variants', $entry ) &&
+                       array_key_exists( $variant, $entry['variants'] ) ) {
+                       $ourSubmethod = $entry['variants'][$variant];
+               } else {
+                       $ourSubmethod = $entry['submethod'];
+               }
+               return array( $ourMethod, $ourSubmethod );
+       }
+}
\ No newline at end of file
diff --git a/PaymentProviders/Adyen/Tests/Data/chargeback.csv 
b/PaymentProviders/Adyen/Tests/Data/chargeback.csv
new file mode 100644
index 0000000..66dfe8f
--- /dev/null
+++ b/PaymentProviders/Adyen/Tests/Data/chargeback.csv
@@ -0,0 +1,4 @@
+Company Account,Merchant Account,Psp Reference,Merchant Reference,Payment 
Method,Creation Date,TimeZone,Type,Modification Reference,Gross Currency,Gross 
Debit (GC),Gross Credit (GC),Exchange Rate,Net Currency,Net Debit (NC),Net 
Credit (NC),Commission (NC),Markup (NC),Scheme Fees (NC),Interchange 
(NC),Payment Method Variant,Modification Merchant Reference,Batch 
Number,Reserved4,Reserved5,Reserved6,Reserved7,Reserved8,Reserved9,Reserved10
+Wikimedia,WikimediaCOM,4555568860022701,92598318.0,visa,2016-02-10 
10:25:36,PST,Chargeback,4555568869855336,USD,1.00,,1,USD,3.00,,2.00,,,,visaclassic,,3,,,,,,,
+Wikimedia,WikimediaCOM,,,,2016-02-15 21:29:37,PST,Fee,Transaction Fees 
February  2016,EUR,,,,USD,1.80,,,,,,,,3,,,,,,,
+Wikimedia,WikimediaCOM,,,,2016-02-15 
21:29:37,PST,MerchantPayout,"TX3488899933XT batch 3, WikimediaCOM batch 3, 
WikimediaCOM",EUR,,,,USD,4.03,,,,,,,,3,,,,,,,
diff --git a/PaymentProviders/Adyen/Tests/Data/donation.csv 
b/PaymentProviders/Adyen/Tests/Data/donation.csv
new file mode 100644
index 0000000..e21deef
--- /dev/null
+++ b/PaymentProviders/Adyen/Tests/Data/donation.csv
@@ -0,0 +1,3 @@
+Company Account,Merchant Account,Psp Reference,Merchant Reference,Payment 
Method,Creation Date,TimeZone,Type,Modification Reference,Gross Currency,Gross 
Debit (GC),Gross Credit (GC),Exchange Rate,Net Currency,Net Debit (NC),Net 
Credit (NC),Commission (NC),Markup (NC),Scheme Fees (NC),Interchange 
(NC),Payment Method Variant,Modification Merchant Reference,Batch 
Number,Reserved4,Reserved5,Reserved6,Reserved7,Reserved8,Reserved9,Reserved10
+Wikimedia,WikimediaCOM,5364893193133131,33992337.0,visa,2016-02-18 
16:10:51,PST,Settled,5364893193133131,USD,,1.00,1,USD,,0.76,,,0.02,0.22,visadebit,,2,,,,,,,
+Wikimedia,WikimediaCOM,,,,2016-02-18 
19:53:26,PST,MerchantPayout,"TX2342222277XT batch 2, WikimediaCOM batch 2, 
WikimediaCOM",EUR,,,,USD,0.76,,,,,,,,2,,,,,,,
diff --git a/PaymentProviders/Adyen/Tests/Data/refund.csv 
b/PaymentProviders/Adyen/Tests/Data/refund.csv
new file mode 100644
index 0000000..ba36903
--- /dev/null
+++ b/PaymentProviders/Adyen/Tests/Data/refund.csv
@@ -0,0 +1,4 @@
+Company Account,Merchant Account,Psp Reference,Merchant Reference,Payment 
Method,Creation Date,TimeZone,Type,Modification Reference,Gross Currency,Gross 
Debit (GC),Gross Credit (GC),Exchange Rate,Net Currency,Net Debit (NC),Net 
Credit (NC),Commission (NC),Markup (NC),Scheme Fees (NC),Interchange 
(NC),Payment Method Variant,Modification Merchant Reference,Batch 
Number,Reserved4,Reserved5,Reserved6,Reserved7,Reserved8,Reserved9,Reserved10
+Wikimedia,WikimediaCOM,4522268860022701,92598312.0,visa,2016-02-10 
10:25:36,PST,Refunded,4522268869855336,USD,1.00,,1,USD,1.00,,,,,,visaclassic,92598312.0,3,,,,,,,
+Wikimedia,WikimediaCOM,,,,2016-02-15 21:29:37,PST,Fee,Transaction Fees 
February  2016,EUR,,,,USD,1.80,,,,,,,,3,,,,,,,
+Wikimedia,WikimediaCOM,,,,2016-02-15 
21:29:37,PST,MerchantPayout,"TX3488899933XT batch 3, WikimediaCOM batch 3, 
WikimediaCOM",EUR,,,,USD,4.03,,,,,,,,3,,,,,,,
diff --git a/PaymentProviders/Adyen/Tests/phpunit/AuditTest.php 
b/PaymentProviders/Adyen/Tests/phpunit/AuditTest.php
new file mode 100644
index 0000000..f94d4d5
--- /dev/null
+++ b/PaymentProviders/Adyen/Tests/phpunit/AuditTest.php
@@ -0,0 +1,78 @@
+<?php namespace SmashPig\PaymentProviders\Adyen\Test;
+
+use SmashPig\PaymentProviders\Adyen\Audit\AdyenAudit;
+
+/**
+ * Verify Adyen audit file processor functions
+ */
+class AuditTest extends \BaseSmashPigUnitTestCase {
+       /**
+        * Normal donation
+        */
+       public function testProcessDonation() {
+               $processor = new AdyenAudit();
+               $output = $processor->parseFile( __DIR__ . 
'/../Data/donation.csv' );
+               $this->assertEquals( 1, count( $output ), 'Should have found 
one donation' );
+               $actual = $output[0];
+               $expected = array(
+                       'gateway' => 'adyen',
+                       'gross' => '1.00',
+                       'contribution_tracking_id' => '33992337',
+                       'currency' => 'USD',
+                       'gateway_txn_id' => '5364893193133131',
+                       'log_id' => '33992337.0',
+                       'payment_method' => 'cc',
+                       'payment_submethod' => 'visa-debit',
+                       'date' => 1455840651,
+                       'settled_currency' => 'USD',
+                       'fee' => '0.24',
+                       'settled_gross' => '0.76',
+                       'settled_fee' => '0.24',
+               );
+               $this->assertEquals( $expected, $actual, 'Did not parse 
donation correctly' );
+       }
+
+       /**
+        * Now try a refund
+        */
+       public function testProcessRefund() {
+               $processor = new AdyenAudit();
+               $output = $processor->parseFile( __DIR__ . 
'/../Data/refund.csv' );
+               $this->assertEquals( 1, count( $output ), 'Should have found 
one refund' );
+               $actual = $output[0];
+               $expected = array(
+                       'gateway' => 'adyen',
+                       'contribution_tracking_id' => '92598312',
+                       'date' => 1455128736,
+                       'gross' => '1.00',
+                       'gateway_parent_id' => '4522268860022701',
+                       'gateway_refund_id' => '4522268869855336',
+                       'gross_currency' => 'USD',
+                       'log_id' => '92598312.0',
+                       'type' => 'refund',
+               );
+               $this->assertEquals( $expected, $actual, 'Did not parse refund 
correctly' );
+       }
+
+       /**
+        * And a chargeback
+        */
+       public function testProcessChargeback() {
+               $processor = new AdyenAudit();
+               $output = $processor->parseFile( __DIR__ . 
'/../Data/chargeback.csv' );
+               $this->assertEquals( 1, count( $output ), 'Should have found 
one chargeback' );
+               $actual = $output[0];
+               $expected = array(
+                       'gateway' => 'adyen',
+                       'contribution_tracking_id' => '92598318',
+                       'date' => 1455128736,
+                       'gross' => '1.00',
+                       'gateway_parent_id' => '4555568860022701',
+                       'gateway_refund_id' => '4555568869855336',
+                       'gross_currency' => 'USD',
+                       'log_id' => '92598318.0',
+                       'type' => 'chargeback',
+               );
+               $this->assertEquals( $expected, $actual, 'Did not parse 
chargeback correctly' );
+       }
+}
diff --git a/config_defaults.php b/config_defaults.php
index 5abbb66..841294a 100644
--- a/config_defaults.php
+++ b/config_defaults.php
@@ -126,8 +126,7 @@
                                         * The ws- credentials should be a user 
authorized to make
                                         * API calls, and the report- 
credentials should be a user
                                         * authorized to download reports. 
Reports will be
-                                        * downloaded to the location specified 
in report-location
-                                        * and moved to report-archive-location 
after processing.
+                                        * downloaded to the location specified 
in report-location.
                                         *
                                         * At least one account and all subkeys 
are required.
                                         *
@@ -137,7 +136,6 @@
                                         *   'report-username' => '',
                                         *   'report-password' => '',
                                         *   'report-location' => '/tmp',
-                                        *   'report-archive-location' => 
'/var/spool/audit/adyen/completed',
                                         * )
                                         **/
                                ),
diff --git a/phpunit.xml b/phpunit.xml
index 6a7c8e0..01a15ec 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -4,6 +4,9 @@
     bootstrap="Tests/bootstrap-phpunit.php">
 
     <testsuites>
+      <testsuite name="Adyen tests">
+        <directory>PaymentProviders/Adyen/Tests/phpunit</directory>
+      </testsuite>
       <testsuite name="Amazon tests">
         <directory>PaymentProviders/Amazon/Tests/phpunit</directory>
       </testsuite>

-- 
To view, visit https://gerrit.wikimedia.org/r/270457
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Icbdbe3fa2c0537c622a4621095527b3d4a7c1769
Gerrit-PatchSet: 7
Gerrit-Project: wikimedia/fundraising/SmashPig
Gerrit-Branch: master
Gerrit-Owner: Cdentinger <cdentin...@wikimedia.org>
Gerrit-Reviewer: Awight <awi...@wikimedia.org>
Gerrit-Reviewer: Cdentinger <cdentin...@wikimedia.org>
Gerrit-Reviewer: Ejegg <eeggles...@wikimedia.org>
Gerrit-Reviewer: XenoRyet <dkozlow...@wikimedia.org>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to