Awight has submitted this change and it was merged.

Change subject: Follow composer.lock
......................................................................


Follow composer.lock

Change-Id: I4cecb6d850fd7c6a4f00985fb4be7e3e5cc35467
---
A coderkungfu/php-queue/.gitreview
M composer/autoload_classmap.php
M composer/installed.json
M wikimedia/donation-interface/gateway_common/FinalStatus.php
M wikimedia/donation-interface/gateway_common/PaymentResult.php
M wikimedia/donation-interface/gateway_common/PaymentTransactionResponse.php
M wikimedia/donation-interface/gateway_common/gateway.adapter.php
M wikimedia/donation-interface/gateway_common/i18n/interface/et.json
M wikimedia/donation-interface/gateway_common/i18n/interface/ko.json
M wikimedia/donation-interface/gateway_common/i18n/interface/qqq.json
M wikimedia/donation-interface/gateway_common/i18n/interface/sah.json
M wikimedia/donation-interface/gateway_common/i18n/interface/tt-cyrl.json
M wikimedia/donation-interface/globalcollect_gateway/globalcollect.adapter.php
A wikimedia/donation-interface/globalcollect_gateway/scripts/refund.php
M wikimedia/donation-interface/tests/Adapter/Worldpay/WorldpayTest.php
15 files changed, 560 insertions(+), 245 deletions(-)

Approvals:
  Awight: Verified; Looks good to me, approved



diff --git a/coderkungfu/php-queue/.gitreview b/coderkungfu/php-queue/.gitreview
new file mode 100644
index 0000000..ffb389a
--- /dev/null
+++ b/coderkungfu/php-queue/.gitreview
@@ -0,0 +1,6 @@
+[gerrit]
+host=gerrit.wikimedia.org
+port=29418
+project=wikimedia/fundraising/php-queue.git
+defaultbranch=master
+defaultrebase=0
diff --git a/composer/autoload_classmap.php b/composer/autoload_classmap.php
index aeb8b25..1ca0e38 100644
--- a/composer/autoload_classmap.php
+++ b/composer/autoload_classmap.php
@@ -29,6 +29,7 @@
     'GlobalCollectGatewayResult' => $vendorDir . 
'/wikimedia/donation-interface/globalcollect_gateway/globalcollect_resultswitcher.body.php',
     'GlobalCollectOrphanAdapter' => $vendorDir . 
'/wikimedia/donation-interface/globalcollect_gateway/orphan.adapter.php',
     'GlobalCollectOrphanRectifier' => $vendorDir . 
'/wikimedia/donation-interface/globalcollect_gateway/GlobalCollectOrphanRectifier.php',
+    'GlobalCollectRefundMaintenance' => $vendorDir . 
'/wikimedia/donation-interface/globalcollect_gateway/scripts/refund.php',
     'LCRun3' => $vendorDir . '/zordius/lightncandy/src/lightncandy.php',
     'LightnCandy' => $vendorDir . '/zordius/lightncandy/src/lightncandy.php',
     'LogPrefixProvider' => $vendorDir . 
'/wikimedia/donation-interface/gateway_common/gateway.adapter.php',
diff --git a/composer/installed.json b/composer/installed.json
index 362878c..3a77b7b 100644
--- a/composer/installed.json
+++ b/composer/installed.json
@@ -418,6 +418,104 @@
         ]
     },
     {
+        "name": "zordius/lightncandy",
+        "version": "v0.18",
+        "version_normalized": "0.18.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/zordius/lightncandy.git";,
+            "reference": "24be6909c37391f4648ce1fdf19036b11bd56d05"
+        },
+        "dist": {
+            "type": "zip",
+            "url": 
"https://api.github.com/repos/zordius/lightncandy/zipball/24be6909c37391f4648ce1fdf19036b11bd56d05";,
+            "reference": "24be6909c37391f4648ce1fdf19036b11bd56d05",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.3.0"
+        },
+        "require-dev": {
+            "phpunit/phpunit": "4.0.17"
+        },
+        "time": "2015-01-01 04:37:19",
+        "type": "library",
+        "installation-source": "dist",
+        "autoload": {
+            "classmap": [
+                "src/lightncandy.php"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/";,
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Zordius Chen",
+                "email": "[email protected]"
+            }
+        ],
+        "description": "An extremely fast PHP implementation of handlebars ( 
http://handlebarsjs.com/ ) and mustache ( http://mustache.github.io/ ).",
+        "homepage": "https://github.com/zordius/lightncandy";,
+        "keywords": [
+            "handlebars",
+            "logicless",
+            "mustache",
+            "php",
+            "template"
+        ]
+    },
+    {
+        "name": "wikimedia/smash-pig",
+        "version": "dev-master",
+        "version_normalized": "9999999-dev",
+        "source": {
+            "type": "git",
+            "url": 
"https://gerrit.wikimedia.org/r/wikimedia/fundraising/SmashPig.git";,
+            "reference": "955d5147b36a2f6bbfdd9aaf35fa5539d016c89b"
+        },
+        "require": {
+            "fusesource/stomp-php": "2.*",
+            "php": ">=5.3.3",
+            "phpmailer/phpmailer": "5.2.6",
+            "symfony/event-dispatcher": ">=2.1,<2.4-dev",
+            "symfony/http-foundation": ">=2.1,<2.4-dev"
+        },
+        "time": "2015-07-31 19:10:19",
+        "type": "library",
+        "installation-source": "source",
+        "autoload": {
+            "psr-4": {
+                "SmashPig\\": "./"
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/";,
+        "license": [
+            "GPLv2"
+        ],
+        "authors": [
+            {
+                "name": "Katie Horn",
+                "email": "[email protected]"
+            },
+            {
+                "name": "Matthew Walker",
+                "email": "[email protected]"
+            },
+            {
+                "name": "Adam Roses Wight",
+                "email": "[email protected]"
+            }
+        ],
+        "description": "The open source PHP flexible payments library and 
frontend/backend mediator.",
+        "homepage": "http://smashpig.org";,
+        "keywords": [
+            "donations",
+            "payments"
+        ]
+    },
+    {
         "name": "coderkungfu/php-queue",
         "version": "dev-master",
         "version_normalized": "9999999-dev",
@@ -534,6 +632,118 @@
         ]
     },
     {
+        "name": "symfony/event-dispatcher",
+        "version": "v2.3.30",
+        "version_normalized": "2.3.30.0",
+        "target-dir": "Symfony/Component/EventDispatcher",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/symfony/EventDispatcher.git";,
+            "reference": "af8fba40bdab97fc666173a8c2087e02445c231c"
+        },
+        "dist": {
+            "type": "zip",
+            "url": 
"https://api.github.com/repos/symfony/EventDispatcher/zipball/af8fba40bdab97fc666173a8c2087e02445c231c";,
+            "reference": "af8fba40bdab97fc666173a8c2087e02445c231c",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.3.3"
+        },
+        "require-dev": {
+            "symfony/dependency-injection": "~2.0,>=2.0.5",
+            "symfony/phpunit-bridge": "~2.7"
+        },
+        "suggest": {
+            "symfony/dependency-injection": "",
+            "symfony/http-kernel": ""
+        },
+        "time": "2015-05-15 13:28:34",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "2.3-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-0": {
+                "Symfony\\Component\\EventDispatcher\\": ""
+            }
+        },
+        "notification-url": "https://packagist.org/downloads/";,
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Fabien Potencier",
+                "email": "[email protected]"
+            },
+            {
+                "name": "Symfony Community",
+                "homepage": "https://symfony.com/contributors";
+            }
+        ],
+        "description": "Symfony EventDispatcher Component",
+        "homepage": "https://symfony.com";
+    },
+    {
+        "name": "symfony/http-foundation",
+        "version": "v2.3.30",
+        "version_normalized": "2.3.30.0",
+        "target-dir": "Symfony/Component/HttpFoundation",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/symfony/HttpFoundation.git";,
+            "reference": "a2223f6d2202af50ac2029bc9e2fa770de84fa3f"
+        },
+        "dist": {
+            "type": "zip",
+            "url": 
"https://api.github.com/repos/symfony/HttpFoundation/zipball/a2223f6d2202af50ac2029bc9e2fa770de84fa3f";,
+            "reference": "a2223f6d2202af50ac2029bc9e2fa770de84fa3f",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.3.3"
+        },
+        "require-dev": {
+            "symfony/phpunit-bridge": "~2.7"
+        },
+        "time": "2015-05-20 08:53:09",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "2.3-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "psr-0": {
+                "Symfony\\Component\\HttpFoundation\\": ""
+            },
+            "classmap": [
+                "Symfony/Component/HttpFoundation/Resources/stubs"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/";,
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "Fabien Potencier",
+                "email": "[email protected]"
+            },
+            {
+                "name": "Symfony Community",
+                "homepage": "https://symfony.com/contributors";
+            }
+        ],
+        "description": "Symfony HttpFoundation Component",
+        "homepage": "https://symfony.com";
+    },
+    {
         "name": "twig/twig",
         "version": "v1.18.2",
         "version_normalized": "1.18.2.0",
@@ -593,223 +803,13 @@
         ]
     },
     {
-        "name": "zordius/lightncandy",
-        "version": "v0.18",
-        "version_normalized": "0.18.0.0",
-        "source": {
-            "type": "git",
-            "url": "https://github.com/zordius/lightncandy.git";,
-            "reference": "24be6909c37391f4648ce1fdf19036b11bd56d05"
-        },
-        "dist": {
-            "type": "zip",
-            "url": 
"https://api.github.com/repos/zordius/lightncandy/zipball/24be6909c37391f4648ce1fdf19036b11bd56d05";,
-            "reference": "24be6909c37391f4648ce1fdf19036b11bd56d05",
-            "shasum": ""
-        },
-        "require": {
-            "php": ">=5.3.0"
-        },
-        "require-dev": {
-            "phpunit/phpunit": "4.0.17"
-        },
-        "time": "2015-01-01 04:37:19",
-        "type": "library",
-        "installation-source": "dist",
-        "autoload": {
-            "classmap": [
-                "src/lightncandy.php"
-            ]
-        },
-        "notification-url": "https://packagist.org/downloads/";,
-        "license": [
-            "MIT"
-        ],
-        "authors": [
-            {
-                "name": "Zordius Chen",
-                "email": "[email protected]"
-            }
-        ],
-        "description": "An extremely fast PHP implementation of handlebars ( 
http://handlebarsjs.com/ ) and mustache ( http://mustache.github.io/ ).",
-        "homepage": "https://github.com/zordius/lightncandy";,
-        "keywords": [
-            "handlebars",
-            "logicless",
-            "mustache",
-            "php",
-            "template"
-        ]
-    },
-    {
-        "name": "symfony/http-foundation",
-        "version": "v2.3.30",
-        "version_normalized": "2.3.30.0",
-        "target-dir": "Symfony/Component/HttpFoundation",
-        "source": {
-            "type": "git",
-            "url": "https://github.com/symfony/HttpFoundation.git";,
-            "reference": "a2223f6d2202af50ac2029bc9e2fa770de84fa3f"
-        },
-        "dist": {
-            "type": "zip",
-            "url": 
"https://api.github.com/repos/symfony/HttpFoundation/zipball/a2223f6d2202af50ac2029bc9e2fa770de84fa3f";,
-            "reference": "a2223f6d2202af50ac2029bc9e2fa770de84fa3f",
-            "shasum": ""
-        },
-        "require": {
-            "php": ">=5.3.3"
-        },
-        "require-dev": {
-            "symfony/phpunit-bridge": "~2.7"
-        },
-        "time": "2015-05-20 08:53:09",
-        "type": "library",
-        "extra": {
-            "branch-alias": {
-                "dev-master": "2.3-dev"
-            }
-        },
-        "installation-source": "dist",
-        "autoload": {
-            "psr-0": {
-                "Symfony\\Component\\HttpFoundation\\": ""
-            },
-            "classmap": [
-                "Symfony/Component/HttpFoundation/Resources/stubs"
-            ]
-        },
-        "notification-url": "https://packagist.org/downloads/";,
-        "license": [
-            "MIT"
-        ],
-        "authors": [
-            {
-                "name": "Fabien Potencier",
-                "email": "[email protected]"
-            },
-            {
-                "name": "Symfony Community",
-                "homepage": "https://symfony.com/contributors";
-            }
-        ],
-        "description": "Symfony HttpFoundation Component",
-        "homepage": "https://symfony.com";
-    },
-    {
-        "name": "symfony/event-dispatcher",
-        "version": "v2.3.30",
-        "version_normalized": "2.3.30.0",
-        "target-dir": "Symfony/Component/EventDispatcher",
-        "source": {
-            "type": "git",
-            "url": "https://github.com/symfony/EventDispatcher.git";,
-            "reference": "af8fba40bdab97fc666173a8c2087e02445c231c"
-        },
-        "dist": {
-            "type": "zip",
-            "url": 
"https://api.github.com/repos/symfony/EventDispatcher/zipball/af8fba40bdab97fc666173a8c2087e02445c231c";,
-            "reference": "af8fba40bdab97fc666173a8c2087e02445c231c",
-            "shasum": ""
-        },
-        "require": {
-            "php": ">=5.3.3"
-        },
-        "require-dev": {
-            "symfony/dependency-injection": "~2.0,>=2.0.5",
-            "symfony/phpunit-bridge": "~2.7"
-        },
-        "suggest": {
-            "symfony/dependency-injection": "",
-            "symfony/http-kernel": ""
-        },
-        "time": "2015-05-15 13:28:34",
-        "type": "library",
-        "extra": {
-            "branch-alias": {
-                "dev-master": "2.3-dev"
-            }
-        },
-        "installation-source": "dist",
-        "autoload": {
-            "psr-0": {
-                "Symfony\\Component\\EventDispatcher\\": ""
-            }
-        },
-        "notification-url": "https://packagist.org/downloads/";,
-        "license": [
-            "MIT"
-        ],
-        "authors": [
-            {
-                "name": "Fabien Potencier",
-                "email": "[email protected]"
-            },
-            {
-                "name": "Symfony Community",
-                "homepage": "https://symfony.com/contributors";
-            }
-        ],
-        "description": "Symfony EventDispatcher Component",
-        "homepage": "https://symfony.com";
-    },
-    {
-        "name": "wikimedia/smash-pig",
-        "version": "dev-master",
-        "version_normalized": "9999999-dev",
-        "source": {
-            "type": "git",
-            "url": 
"https://gerrit.wikimedia.org/r/wikimedia/fundraising/SmashPig.git";,
-            "reference": "955d5147b36a2f6bbfdd9aaf35fa5539d016c89b"
-        },
-        "require": {
-            "fusesource/stomp-php": "2.*",
-            "php": ">=5.3.3",
-            "phpmailer/phpmailer": "5.2.6",
-            "symfony/event-dispatcher": ">=2.1,<2.4-dev",
-            "symfony/http-foundation": ">=2.1,<2.4-dev"
-        },
-        "time": "2015-07-31 19:10:19",
-        "type": "library",
-        "installation-source": "source",
-        "autoload": {
-            "psr-4": {
-                "SmashPig\\": "./"
-            }
-        },
-        "notification-url": "https://packagist.org/downloads/";,
-        "license": [
-            "GPLv2"
-        ],
-        "authors": [
-            {
-                "name": "Katie Horn",
-                "email": "[email protected]"
-            },
-            {
-                "name": "Matthew Walker",
-                "email": "[email protected]"
-            },
-            {
-                "name": "Adam Roses Wight",
-                "email": "[email protected]"
-            }
-        ],
-        "description": "The open source PHP flexible payments library and 
frontend/backend mediator.",
-        "homepage": "http://smashpig.org";,
-        "keywords": [
-            "donations",
-            "payments"
-        ]
-    },
-    {
         "name": "wikimedia/donation-interface",
         "version": "dev-master",
         "version_normalized": "9999999-dev",
         "source": {
             "type": "git",
             "url": 
"https://gerrit.wikimedia.org/r/mediawiki/extensions/DonationInterface.git";,
-            "reference": "74f4e078c48a44a90c9e8563ff365e679deb8c75"
+            "reference": "1971cbbc12b967ff776399e57f5098de04785637"
         },
         "require": {
             "coderkungfu/php-queue": "dev-master",
diff --git a/wikimedia/donation-interface/gateway_common/FinalStatus.php 
b/wikimedia/donation-interface/gateway_common/FinalStatus.php
index 062d080..2ae09cf 100644
--- a/wikimedia/donation-interface/gateway_common/FinalStatus.php
+++ b/wikimedia/donation-interface/gateway_common/FinalStatus.php
@@ -9,4 +9,6 @@
        const PENDING = 'pending';
        const PENDING_POKE = 'pending-poke';
        const REVISED = 'revised';
+       const REFUNDED = 'refunded';
+       const CANCELLED = 'cancelled';
 }
diff --git a/wikimedia/donation-interface/gateway_common/PaymentResult.php 
b/wikimedia/donation-interface/gateway_common/PaymentResult.php
index 5360a2e..e160d8d 100644
--- a/wikimedia/donation-interface/gateway_common/PaymentResult.php
+++ b/wikimedia/donation-interface/gateway_common/PaymentResult.php
@@ -64,9 +64,10 @@
                return $response;
        }
 
-       static public function newFailure() {
+       static public function newFailure( $errors = array() ) {
                $response = new PaymentResult();
                $response->failed = true;
+               $response->errors = $errors;
                return $response;
        }
 
@@ -113,7 +114,7 @@
         */
        static public function fromResults( PaymentTransactionResponse 
$response, $finalStatus ) {
                if ( $finalStatus === FinalStatus::FAILED ) {
-                       return PaymentResult::newFailure();
+                       return PaymentResult::newFailure( 
$response->getErrors() );
                }
                if ( !$response ) {
                        return PaymentResult::newEmpty();
diff --git 
a/wikimedia/donation-interface/gateway_common/PaymentTransactionResponse.php 
b/wikimedia/donation-interface/gateway_common/PaymentTransactionResponse.php
index a137579..a116db3 100644
--- a/wikimedia/donation-interface/gateway_common/PaymentTransactionResponse.php
+++ b/wikimedia/donation-interface/gateway_common/PaymentTransactionResponse.php
@@ -14,7 +14,7 @@
         * If there weren't any, this should be present and empty after a
         * transaction.
         */
-       protected $errors;
+       protected $errors = array();
 
        /**
         * @var string Raw return data from the cURL transaction
diff --git a/wikimedia/donation-interface/gateway_common/gateway.adapter.php 
b/wikimedia/donation-interface/gateway_common/gateway.adapter.php
index 87a8549..52ce7ce 100644
--- a/wikimedia/donation-interface/gateway_common/gateway.adapter.php
+++ b/wikimedia/donation-interface/gateway_common/gateway.adapter.php
@@ -3163,7 +3163,7 @@
         * want to do yet, like assigning order ID and saving contribution 
tracking.
         */
        protected function session_resetOnSwitch() {
-               if ( !$this->session_exists() ) {
+               if ( $this->isBatchProcessor() || !$this->session_exists() ) {
                        return;
                }
                $oldData = $this->session_getData( 'Donor' );
diff --git a/wikimedia/donation-interface/gateway_common/i18n/interface/et.json 
b/wikimedia/donation-interface/gateway_common/i18n/interface/et.json
index 8e12361..aa55289 100644
--- a/wikimedia/donation-interface/gateway_common/i18n/interface/et.json
+++ b/wikimedia/donation-interface/gateway_common/i18n/interface/et.json
@@ -185,7 +185,7 @@
        "donate_interface-error-msg-account_number": "Konto number",
        "donate_interface-error-msg-captcha": "Sisestatud robotilõksu kood ei 
sobi. Palun proovi uuesti.",
        "donate_interface-error-msg-captcha-please": "Palun sisesta turvalisuse 
tagamiseks ülalolevad märgid.",
-       "donate_interface-error-msg-cookies": "Palun luba võrgulehitsejad 
küpsised.",
+       "donate_interface-error-msg-cookies": "Palun luba veebilehitsejas 
küpsised.",
        "donate_interface-error-msg-genaricrequired": "See väli on kohustuslik",
        "donate_interface-error-msg-country-calc": "Tõrge. Praegu pole võimalik 
sinu annetust vastu võtta.",
        "donate_interface-donate-error-try-a-different-card": "Palun proovi [$1 
teistsugust kaarti], [$2 muud annetusviisi] või võta ühendust aadressil $3.",
@@ -211,7 +211,7 @@
        "donate_interface-middle": "Keskmine nimi",
        "donate_interface-last": "Perekonnanimi",
        "donate_interface-other": "Muu",
-       "donate_interface-noscript-msg": "Nähtavasti pole sul JavaScript 
lubatud või su võrgulehitsejal puudub selle tugi.\nTurvaliseks ja meeldivaks 
kasutamiseks on meie annetamisvormi jaoks vaja JavaScripti.",
+       "donate_interface-noscript-msg": "Nähtavasti pole sul JavaScript 
lubatud või su veebilehitsejal puudub selle tugi.\nTurvaliseks ja meeldivaks 
kasutamiseks on meie annetamisvormi jaoks vaja JavaScripti.",
        "donate_interface-noscript-redirect-msg": "Kui sa ei saa või ei soovi 
JavaScripti lubada, saad ikkagi annetada sellel võrgulehel:",
        "donate_interface-anon-message": "Palun näita avalikus annetajate 
nimekirjas minu nime.",
        "donate_interface-donate-wikipedia": "Anneta Wikipediale",
diff --git a/wikimedia/donation-interface/gateway_common/i18n/interface/ko.json 
b/wikimedia/donation-interface/gateway_common/i18n/interface/ko.json
index 4aa1bfb..eb56185 100644
--- a/wikimedia/donation-interface/gateway_common/i18n/interface/ko.json
+++ b/wikimedia/donation-interface/gateway_common/i18n/interface/ko.json
@@ -228,7 +228,7 @@
        "donate_interface-cc-form-header-payment": "결제 정보",
        "donate_interface-make-your-donation": "지금 기부해주세요",
        "donate_interface-state-in-us": "미국 내 거주하시는 경우",
-       "donate_interface-comment": "덧글",
+       "donate_interface-comment": "댓글",
        "donate_interface-first": "이름",
        "donate_interface-middle": "중간",
        "donate_interface-last": "성",
diff --git 
a/wikimedia/donation-interface/gateway_common/i18n/interface/qqq.json 
b/wikimedia/donation-interface/gateway_common/i18n/interface/qqq.json
index 0e720f1..0ec8d6f 100644
--- a/wikimedia/donation-interface/gateway_common/i18n/interface/qqq.json
+++ b/wikimedia/donation-interface/gateway_common/i18n/interface/qqq.json
@@ -23,7 +23,8 @@
                        "Pcoombe",
                        "James D. Forrester",
                        "Liuxinyu970226",
-                       "Amire80"
+                       "Amire80",
+                       "Nemo bis"
                ]
        },
        "donate_interface": "{{Identical|Support Wikimedia}}",
@@ -167,7 +168,7 @@
        "donate_interface-donor-island": "Label for field with dropdown list of 
islands.\n{{Identical|Island}}",
        "donate_interface-donor-state": "The donor is to select either a U.S. 
state or \"Outside the U.S.\" \n{{Identical|State}}",
        "donate_interface-donor-province": "Label for province selection.",
-       "donate_interface-donor-zip": "Placeholder for zip code field. This 
should be 7 characters maximum.\n{{Identical|Zip}}",
+       "donate_interface-donor-zip": "Placeholder for zip code field. This 
should be 10 characters maximum.\n{{Identical|Zip}}",
        "donate_interface-donor-postal": "Label for field to input postal 
code.\n{{Identical|Postal code}}",
        "donate_interface-donor-postcode": "{{optional}}\n{{Identical|Postal 
code}}",
        "donate_interface-donor-country": "Label for field with dropdown list 
of countries/regions.",
diff --git 
a/wikimedia/donation-interface/gateway_common/i18n/interface/sah.json 
b/wikimedia/donation-interface/gateway_common/i18n/interface/sah.json
index 3bf9439..92f368c 100644
--- a/wikimedia/donation-interface/gateway_common/i18n/interface/sah.json
+++ b/wikimedia/donation-interface/gateway_common/i18n/interface/sah.json
@@ -3,7 +3,8 @@
                "authors": [
                        "HalanTul",
                        "Jsoby",
-                       "Pcoombe"
+                       "Pcoombe",
+                       "Исмаил Садуев"
                ]
        },
        "donate_interface": "Викимедианы өйүөххэйиҥ!",
@@ -165,7 +166,7 @@
        "donate_interface-cvv2": "CVV2",
        "donate_interface-cvv-number": "CVV нүөмэрэ",
        "donate_interface-verification-number": "Бигэргэтэр нүөмэрэ",
-       "donate_interface-what-is-this": "Бу тугуй?",
+       "donate_interface-what-is-this": "ХӀара хӀун ду?",
        "donate_interface-do-not-include-dashes": "Бука диэн, тирены туттума",
        "donate_interface-please-donate-today": "Бука диэн билигин сиэртибэлээ",
        "donate_interface-donate-now": "Билигин сиэртибэлииргэ",
@@ -187,24 +188,8 @@
        "donate_interface-email-receipt": "Квитанцияны эл. почтаҕа ыытарга",
        "donate_interface-monthly-donation": "Ый аайы ыытыы",
        "donate_interface-via-paypal": "(PayPal нөҥүө)",
-       "donate_interface-shirt-size": "Футболка кээмэйэ:",
-       "donate_interface-shirt-size-2": "Футболка кээмэйэ: $1",
-       "donate_interface-language": "Тыла:",
-       "donate_interface-front": "Иннэ",
-       "donate_interface-back": "Кэннэ",
-       "donate_interface-front-of-shirt": "Футболка иннэ",
-       "donate_interface-back-of-shirt": "Футболка кэннэ",
-       "donate_interface-select-a-size": "Бука диэн, размергын тал",
        "donate_interface-select": "Размер:",
-       "donate_interface-shipping-address": "Почта аадырыһа",
-       "donate_interface-shipping-address-different": "Почтам аадырыһа төлүүр 
аадырыспыттан ураты.",
-       "donate_interface-shipping-address-same": "Почтам аадырыһа төлүүр сирим 
аадырыһын кытта биир.",
-       "donate_interface-only-billing-address": "Төлүүр сир аадырыһыгар эрэ 
ыытыллыан сөп.",
        "donate_interface-donation-must-equal": "Сиэртибэ кээмэйэ мантан $1 
кыра буолуо суохтаах.",
        "donate_interface-thank-you": "Махтанабыт! Сиэртибэҥ киирдэ.",
-       "donate_interface-wikipedia-translation": "Болҕойуҥ, ырбаахы сиэҕигэр 
суруллар «Wikipedia» диэн сурук тылбаастаныа суоҕа, ойуу быһыытынан маннык 
көстүө: «Wikipedia 10».",
-       "donate_interface-on-the-back": "Ону тэҥэ кэннигэр:",
-       "donate_interface-tshirt-confirmation": "Эйиэхэ бу тылынан суруктаах, 
маннык кээмэйдээх футболка ыытыллыа:",
-       "donate_interface-donation-tshirt": "Сиэртибэлээһин (футболка ыытабыт)",
        "donate_interface-state-dropdown-XX": "АХШ таһыгар"
 }
diff --git 
a/wikimedia/donation-interface/gateway_common/i18n/interface/tt-cyrl.json 
b/wikimedia/donation-interface/gateway_common/i18n/interface/tt-cyrl.json
index eb07bdc..6e0c308 100644
--- a/wikimedia/donation-interface/gateway_common/i18n/interface/tt-cyrl.json
+++ b/wikimedia/donation-interface/gateway_common/i18n/interface/tt-cyrl.json
@@ -3,7 +3,8 @@
                "authors": [
                        "Jsoby",
                        "Ильнар",
-                       "Pcoombe"
+                       "Pcoombe",
+                       "Исмаил Садуев"
                ]
        },
        "donate_interface": "Викимедиа Фондына ярдәм итик!",
@@ -41,7 +42,7 @@
        "donate_interface-cc-button": "кредит картагыз ярдәмендә иганә ясагыз",
        "donate_interface-card-legend": "Крдеит картасы турында мәгълүмат",
        "donate_interface-amount-legend": "Иганә күләме",
-       "donate_interface-cvv-link": "Кайда бу?",
+       "donate_interface-cvv-link": "Стенгахь ю и?",
        "donate_interface-donor-legend": "Иганә турында мәгълүмат",
        "donate_interface-donor-amount": "Сумма:",
        "donate_interface-donor-currency-label": "Акча берәмлеге:",
diff --git 
a/wikimedia/donation-interface/globalcollect_gateway/globalcollect.adapter.php 
b/wikimedia/donation-interface/globalcollect_gateway/globalcollect.adapter.php
index 22aa518..e7b6fef 100644
--- 
a/wikimedia/donation-interface/globalcollect_gateway/globalcollect.adapter.php
+++ 
b/wikimedia/donation-interface/globalcollect_gateway/globalcollect.adapter.php
@@ -367,7 +367,9 @@
                        'OK' => true,
                        'NOK' => false,
                );
-               $this->addCodeRange( 'GET_ORDERSTATUS', 'STATUSID', 
FinalStatus::PENDING, 0, 70 );
+               $this->addCodeRange( 'GET_ORDERSTATUS', 'STATUSID', 
FinalStatus::PENDING, 0, 10 );
+               $this->addCodeRange( 'GET_ORDERSTATUS', 'STATUSID', 
FinalStatus::FAILED, 15 ); // Refund failed
+               $this->addCodeRange( 'GET_ORDERSTATUS', 'STATUSID', 
FinalStatus::PENDING, 20, 70 );
                $this->addCodeRange( 'GET_ORDERSTATUS', 'STATUSID', 
FinalStatus::FAILED, 100, 180 );
                $this->addCodeRange( 'GET_ORDERSTATUS', 'STATUSID', 
FinalStatus::PENDING_POKE, 200 ); //The cardholder was successfully 
authenticated... but we have to DO_FINISHPAYMENT
                $this->addCodeRange( 'GET_ORDERSTATUS', 'STATUSID', 
FinalStatus::FAILED, 220, 280 );
@@ -380,9 +382,12 @@
                $this->addCodeRange( 'GET_ORDERSTATUS', 'STATUSID', 
FinalStatus::PENDING, 625, 650 );
                $this->addCodeRange( 'GET_ORDERSTATUS', 'STATUSID', 
FinalStatus::COMPLETE, 800, 975 ); //these are all post-authorized, but 
technically pre-settled...
                $this->addCodeRange( 'GET_ORDERSTATUS', 'STATUSID', 
FinalStatus::COMPLETE, 1000, 1050 );
-               $this->addCodeRange( 'GET_ORDERSTATUS', 'STATUSID', 
FinalStatus::FAILED, 1100, 99999 );
-               $this->addCodeRange( 'GET_ORDERSTATUS', 'STATUSID', 
FinalStatus::FAILED, 100000, 999999 ); // 102020 - ACTION 130 IS NOT ALLOWED 
FOR MERCHANT NNN, IPADDRESS NNN.NNN.NNN.NNN
-
+               $this->addCodeRange( 'GET_ORDERSTATUS', 'STATUSID', 
FinalStatus::FAILED, 1100, 1520 );
+               $this->addCodeRange( 'GET_ORDERSTATUS', 'STATUSID', 
FinalStatus::REFUNDED, 1800 );
+               $this->addCodeRange( 'GET_ORDERSTATUS', 'STATUSID', 
FinalStatus::FAILED, 1810, 2220 );
+               // FIXME: not sure what this comment is about:
+               // 102020 - ACTION 130 IS NOT ALLOWED FOR MERCHANT NNN, 
IPADDRESS NNN.NNN.NNN.NNN
+               $this->addCodeRange( 'GET_ORDERSTATUS', 'STATUSID', 
FinalStatus::CANCELLED, 99999 );
 
                $this->defineGoToThankYouOn();
        }
@@ -530,6 +535,57 @@
                        ),
                );
 
+               $this->transactions['DO_REFUND'] = array(
+                       'request' => array(
+                               'REQUEST' => array(
+                                       'ACTION',
+                                       'META' => array(
+                                               'MERCHANTID',
+                                               'IPADDRESS',
+                                               'VERSION'
+                                       ),
+                                       'PARAMS' => array(
+                                               'PAYMENT' => array(
+                                                       'PAYMENTPRODUCTID',
+                                                       'ORDERID',
+                                                       'MERCHANTREFERENCE',
+                                                       'AMOUNT',
+                                                       'CURRENCYCODE',
+                                                       'COUNTRYCODE',
+                                               )
+                                       )
+                               )
+                       ),
+                       'values' => array(
+                               'ACTION' => 'DO_REFUND',
+                               'VERSION' => '1.0',
+                       ),
+               );
+
+               $this->transactions['SET_REFUND'] = array(
+                       'request' => array(
+                               'REQUEST' => array(
+                                       'ACTION',
+                                       'META' => array(
+                                               'MERCHANTID',
+                                               'IPADDRESS',
+                                               'VERSION'
+                                       ),
+                                       'PARAMS' => array(
+                                               'PAYMENT' => array(
+                                                       'PAYMENTPRODUCTID',
+                                                       'ORDERID',
+                                                       'EFFORTID',
+                                               )
+                                       )
+                               )
+                       ),
+                       'values' => array(
+                               'ACTION' => 'SET_REFUND',
+                               'VERSION' => '1.0',
+                       ),
+               );
+
                $this->transactions['TEST_CONNECTION'] = array(
                        'request' => array(
                                'REQUEST' => array(
@@ -670,6 +726,52 @@
                                'VERSION' => '1.0',
                                'HOSTEDINDICATOR' => '0',
                                'AUTHENTICATIONINDICATOR' => '0',
+                       ),
+               );
+
+               // Cancel a recurring transaction if all payment attempts can 
be canceled
+               $this->transactions['CANCEL_ORDER'] = array(
+                       'request' => array(
+                               'REQUEST' => array(
+                                       'ACTION',
+                                       'META' => array(
+                                               'MERCHANTID',
+                                               'IPADDRESS',
+                                               'VERSION',
+                                       ),
+                                       'PARAMS' => array(
+                                               'ORDER' => array(
+                                                       'ORDERID',
+                                               ),
+                                       )
+                               )
+                       ),
+                       'values' => array(
+                               'ACTION' => 'CANCEL_ORDER',
+                               'VERSION' => '1.0',
+                       ),
+               );
+
+               // End a recurring transaction, disallowing further payment 
attempts
+               $this->transactions['END_ORDER'] = array(
+                       'request' => array(
+                               'REQUEST' => array(
+                                       'ACTION',
+                                       'META' => array(
+                                               'MERCHANTID',
+                                               'IPADDRESS',
+                                               'VERSION',
+                                       ),
+                                       'PARAMS' => array(
+                                               'ORDER' => array(
+                                                       'ORDERID',
+                                               ),
+                                       )
+                               )
+                       ),
+                       'values' => array(
+                               'ACTION' => 'END_ORDER',
+                               'VERSION' => '1.0',
                        ),
                );
        }
@@ -1528,6 +1630,132 @@
     }
 
        /**
+        * Refunds a transaction.  Assumes that we're running in batch mode with
+        * payment_method = cc, and that all of these have been set:
+        * order_id, effort_id, country, currency_code, amount, and 
payment_submethod
+        * Also requires merchant_reference to be set to the reference from the
+        * original transaction.  FIXME: store that some place besides the logs
+        * @return PaymentResult
+        */
+       public function doRefund() {
+               $effortId = $this->getData_Unstaged_Escaped( 'effort_id' );
+
+               // Don't want to use standard ct_id staging
+               $this->var_map['MERCHANTREFERENCE'] = 'merchant_reference';
+
+               // Try cancelling first, it's fast and cheap.
+               // TODO: Look into AUTHORIZATIONREVERSALINDICATOR
+               $cancel_payment_response = $this->do_transaction( 
'CANCEL_PAYMENT' );
+
+               if ( $cancel_payment_response->getCommunicationStatus() ) {
+                       // That's all we need!
+                       $this->logger->info( "Canceled payment attempt effort 
$effortId" );
+                       return PaymentResult::fromResults( 
$cancel_payment_response, FinalStatus::COMPLETE );
+               }
+
+               // Get the status and see what we've accomplished so far.
+               $get_orderstatus_response = $this->do_transaction( 
'GET_ORDERSTATUS' );
+               $get_orderstatus_data = $get_orderstatus_response->getData();
+
+               // If we can't even get the status, fail.
+               if ( !$get_orderstatus_response->getCommunicationStatus()
+                       || !isset( $get_orderstatus_data['STATUSID'] )
+               ) {
+                       $this->logger->warning( "Could not get status for 
payment attempt effort $effortId." );
+                       return PaymentResult::fromResults( 
$get_orderstatus_response, FinalStatus::FAILED );
+               }
+
+               $final_status = $this->findCodeAction( 'GET_ORDERSTATUS', 
'STATUSID', $get_orderstatus_data['STATUSID'] );
+
+               // If it's already cancelled or refunded, pat own back.
+               // FIXME: I don't think the original txn goes into refunded 
status, just
+               // the refund txn with the same order id but negated efort ID
+               if ( $final_status === FinalStatus::CANCELLED
+                       || $final_status === FinalStatus::REFUNDED
+               ) {
+                       $this->logger->info( "Payment attempt effort $effortId 
already canceled or refunded." );
+                       return PaymentResult::fromResults( 
$get_orderstatus_response, FinalStatus::COMPLETE );
+               }
+
+               // Refunding a transaction creates another "payment" against 
the same
+               // order id, but with a negated effort id.  Check to see if a 
refund has
+               // already been requested.
+               // TODO: is it always the negative of the original payment's 
effort id?
+               $this->transactions['GET_ORDERSTATUS']['values']['EFFORTID'] =
+                       -1 * intval( $effortId );
+
+               $refund_response = $this->do_transaction( 'GET_ORDERSTATUS' );
+               $refund_data = $refund_response->getData();
+
+               // If there is no existing refund, request one
+               if ( !isset( $refund_data['STATUSID'] ) ) {
+                       $refund_response = $this->do_transaction( 'DO_REFUND' );
+                       $refund_data = $refund_response->getData();
+               }
+
+               if ( !$refund_response->getCommunicationStatus()
+                       || !isset( $refund_data['STATUSID'] )
+               ) {
+                       // No existing refund, and requesting a new one failed
+                       $this->logger->warning( "Could not request refund for 
payment attempt effort $effortId." );
+                       return PaymentResult::fromResults( $refund_response, 
FinalStatus::FAILED );
+               }
+
+               // We should have a refund with a status code by now.
+               // TODO: should refunds have their own set of code maps?  CC 
state diagram
+               // shows a parallel refund track where 800 means 'refund 
ready', 900
+               // means 'refund sent', and 1800 means 'refunded'
+               $refund_status = $this->findCodeAction( 'GET_ORDERSTATUS', 
'STATUSID', $refund_data['STATUSID'] );
+
+               // Done? Good!
+               if ( $refund_status === FinalStatus::COMPLETE || $refund_status 
=== FinalStatus::REFUNDED ) {
+                       $this->logger->info( "Refund request for payment 
attempt effort $effortId is complete." );
+                       return PaymentResult::fromResults( $refund_response, 
FinalStatus::COMPLETE );
+               }
+
+               // If the refund is pending, settle it
+               if ( $refund_status === FinalStatus::PENDING_POKE ) {
+                       
$this->transactions['SET_REFUND']['values']['PAYMENTPRODUCTID'] = 
$refund_data['PAYMENTPRODUCTID'];
+                       $set_refund_response = 
$this->do_transaction('SET_REFUND');
+
+                       if ( !$set_refund_response->getCommunicationStatus() ) {
+                               $this->logger->warning( "Could not settle 
refund request for payment attempt effort $effortId." );
+                               return PaymentResult::fromResults( 
$set_refund_response, FinalStatus::FAILED );
+                       }
+
+                       $this->logger->info( "Settled refund request for 
payment attempt effort $effortId." );
+                       return PaymentResult::fromResults( 
$set_refund_response, FinalStatus::COMPLETE );
+               }
+
+               // What the heck happened?
+               $this->logger->warning( "Refund request for payment attempt 
effort $effortId has unknown status." );
+               return PaymentResult::fromResults( $refund_response, 
FinalStatus::FAILED );
+       }
+
+       /**
+        * Cancel a subscription
+        *
+        * Uses the adapter's internal order ID.
+        *
+        * @return PaymentResult
+        */
+       public function cancelSubscription() {
+               // Try to cancel, in case no payment attempts have been made or 
all
+               // payment attempts can be canceled
+               $response = $this->do_transaction( 'CANCEL_ORDER' );
+
+               if ( !$response->getCommunicationStatus() ) {
+                       // If we can't cancel, end it to disallow future 
attempts
+                       $response = $this->do_transaction( 'END_ORDER' );
+                       if ( !$response->getCommunicationStatus() ) {
+                               return PaymentResult::fromResults( $response, 
FinalStatus::FAILED );
+                       }
+               }
+
+               return PaymentResult::fromResults( $response, 
FinalStatus::COMPLETE );
+       }
+
+       /**
         * Parse the response to get the status. Not sure if this should return 
a bool, or something more... telling.
         *
         * @param DomDocument   $response       The response XML loaded into a 
DomDocument
@@ -1650,6 +1878,7 @@
                                $data['ORDER'] = $this->xmlChildrenToArray( 
$response, 'ORDER' );
                                break;
                        case 'DO_FINISHPAYMENT':
+                       case 'DO_REFUND':
                                $data = $this->xmlChildrenToArray( $response, 
'ROW' );
                                break;
                        case 'DO_PAYMENT':
diff --git 
a/wikimedia/donation-interface/globalcollect_gateway/scripts/refund.php 
b/wikimedia/donation-interface/globalcollect_gateway/scripts/refund.php
new file mode 100644
index 0000000..04e17db
--- /dev/null
+++ b/wikimedia/donation-interface/globalcollect_gateway/scripts/refund.php
@@ -0,0 +1,83 @@
+<?php
+
+$IP = getenv( 'MW_INSTALL_PATH' );
+if ( $IP === false ) {
+       $IP = __DIR__ . '/../../../..';
+}
+
+//If you get errors on this next line, set (and export) your MW_INSTALL_PATH 
var. 
+require_once( "$IP/maintenance/Maintenance.php" );
+
+// Refunds credit card transactions listed in a file.
+// Currently takes a CSV with no header and columns in this order:
+// order_id, merchant_reference, effort_id, payment_submethod, country, 
currency_code, amount
+class GlobalCollectRefundMaintenance extends Maintenance {
+       public function __construct() {
+               parent::__construct();
+
+               $this->addOption( 'file', 'Read refund detail in from a file',
+                       true, true, 'f' );
+               $this->addOption( 'unsubscribe', 'Cancel the subscription this 
charge is a part of',
+                       false, false );
+       }
+
+       public function execute() {
+               global $wgGlobalCollectGatewayEnableCustomFilters;
+
+               // don't run fraud checks for refunds
+               $wgGlobalCollectGatewayEnableCustomFilters = false;
+
+               $isUnsubscribing = $this->getOption( 'unsubscribe' );
+
+               $filename = $this->getOption( 'file' );
+               if( !( $file = fopen( $filename, 'r' ) ) ){
+                       $this->error( 'Could not find refund file: ' . 
$filename, true );
+        }
+               while ( $refund = fgetcsv( $file ) ) {
+                       if ( count( $refund ) !== 7 ) {
+                               $this->error( 'Refund lines must have exactly 7 
fields', true );
+                       }
+                       $oid = $refund[0];
+                       $effort_id = $refund[2];
+                       $gateway_opts = array(
+                               'batch_mode' => true,
+                               'external_data' => array(
+                                       'order_id' => $oid,
+                                       'merchant_reference' => $refund[1],
+                                       'effort_id' => $effort_id,
+                                       'payment_method' => 'cc',
+                                       'payment_submethod' => $refund[3],
+                                       'country' => $refund[4],
+                                       'currency_code' => $refund[5],
+                                       'amount' => $refund[6],
+                               ),
+                       );
+
+                       $this->output( "Refunding transaction $oid\n" );
+                       $adapter = new GlobalCollectAdapter( $gateway_opts );
+                       // FIXME: effort_id is clobbered in setGatewayDefaults
+                       $adapter->addRequestData( array( 'effort_id' => 
$effort_id ) );
+                       $result = $adapter->doRefund();
+
+                       if ( $result->isFailed() ) {
+                               $this->error( "Failed refunding transaction 
$oid" );
+                       } else {
+                               $this->output( "Successfully refunded 
transaction $oid\n" );
+                       }
+
+                       if ( $isUnsubscribing ) {
+                               $result = $adapter->cancelSubscription();
+
+                               if ( $result->isFailed() ) {
+                                       $this->error( "Failed cancelling 
subscription $oid" );
+                               } else {
+                                       $this->output( "Successfully cancelled 
subscription $oid\n" );
+                               }
+                       }
+               }
+               fclose( $file );
+       }
+}
+
+$maintClass = 'GlobalCollectRefundMaintenance';
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git 
a/wikimedia/donation-interface/tests/Adapter/Worldpay/WorldpayTest.php 
b/wikimedia/donation-interface/tests/Adapter/Worldpay/WorldpayTest.php
index 8212a5e..62b29dc 100644
--- a/wikimedia/donation-interface/tests/Adapter/Worldpay/WorldpayTest.php
+++ b/wikimedia/donation-interface/tests/Adapter/Worldpay/WorldpayTest.php
@@ -484,6 +484,12 @@
                $gateway = $this->getFreshGatewayObject( $init );
                $result = $gateway->doPayment();
                $this->assertTrue( $result->isFailed(), 'PaymentResult should 
be failed' );
-               $this->assertEmpty( $result->getErrors(), 'PaymentResult should 
have no errors' );
+               $errors = $result->getErrors();
+
+               $this->assertEquals(
+                       'Failed post-process checks for transaction type 
AuthorizePaymentForFraud.',
+                       $errors['internal-0000']['debugInfo'],
+                       'PaymentResult errors should include fraud check 
failure'
+               );
        }
 }

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I4cecb6d850fd7c6a4f00985fb4be7e3e5cc35467
Gerrit-PatchSet: 1
Gerrit-Project: wikimedia/fundraising/crm/vendor
Gerrit-Branch: master
Gerrit-Owner: Awight <[email protected]>
Gerrit-Reviewer: Awight <[email protected]>
Gerrit-Reviewer: Siebrand <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to