Ejegg has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/399841 )

Change subject: WIP Amazon: automatic retry on TransactionTimedOut
......................................................................

WIP Amazon: automatic retry on TransactionTimedOut

Donor services has been doing this by hand

Bug: T183429
Change-Id: Ia959ac2e6efc27ddd2527d8aa38b153946132ff8
---
A PaymentProviders/Amazon/Actions/RetryAuthorization.php
M PaymentProviders/Amazon/AmazonListener.php
M PaymentProviders/Amazon/ExpatriatedMessages/AmazonMessage.php
A PaymentProviders/Amazon/ExpatriatedMessages/AuthorizationDeclined.php
A PaymentProviders/Amazon/ExpatriatedMessages/PaymentAuthorization.php
A PaymentProviders/Amazon/ReasonCode.php
A PaymentProviders/Amazon/Tests/Data/IPN/AuthorizationDeclined.json
7 files changed, 189 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/wikimedia/fundraising/SmashPig 
refs/changes/41/399841/1

diff --git a/PaymentProviders/Amazon/Actions/RetryAuthorization.php 
b/PaymentProviders/Amazon/Actions/RetryAuthorization.php
new file mode 100644
index 0000000..e81324b
--- /dev/null
+++ b/PaymentProviders/Amazon/Actions/RetryAuthorization.php
@@ -0,0 +1,66 @@
+<?php namespace SmashPig\PaymentProviders\Amazon\Actions;
+
+use Exception;
+use PayWithAmazon\PaymentsClientInterface;
+use SmashPig\Core\Actions\IListenerMessageAction;
+use SmashPig\Core\Context;
+use SmashPig\Core\Logging\Logger;
+use SmashPig\Core\Messages\ListenerMessage;
+use SmashPig\PaymentProviders\Amazon\ExpatriatedMessages\AuthorizationDeclined;
+use SmashPig\PaymentProviders\Amazon\ReasonCode;
+
+class RetryAuthorization implements IListenerMessageAction {
+
+       public function execute( ListenerMessage $msg ) {
+               // only retry declined authorizations
+               if ( !( $msg instanceof AuthorizationDeclined ) ) {
+                       return true;
+               }
+               // and only when the reason is TransactionTimedOut
+               if ( !( $msg->getReasonCode() === 
ReasonCode::TRANSACTION_TIMED_OUT ) ) {
+                       return true;
+               }
+               $config = Context::get()->getProviderConfiguration();
+
+               /**
+                * @var PaymentsClientInterface $client
+                */
+               $client = $config->object( 'payments-client', true );
+
+               $orderReferenceId = $msg->getOrderReferenceId();
+
+               Logger::info(
+                       "Retrying timed-out authorization on order reference 
$orderReferenceId"
+               );
+
+               try {
+                       $response = $client->authorize(
+                               [
+                                       'amazon_order_reference_id' => 
$orderReferenceId,
+                                       'authorization_amount' => 
$msg->getGross(),
+                                       'currency_code' => $msg->getCurrency(),
+                                       'capture_now' => true, // combine 
authorize and capture steps
+                                       'authorization_reference_id' => 
$msg->getOrderId(),
+                                       'transaction_timeout' => 1440, // whole 
day to retry
+                               ]
+                       )->toArray();
+
+                       if ( !empty( $response['Error'] ) ) {
+                               Logger::warning(
+                                       "Error retrying auth on order reference 
$orderReferenceId: " .
+                                       $response['Error']['Code'] . ': ' .
+                                       $response['Error']['Message']
+                               );
+                               return false;
+                       }
+               } catch ( Exception $ex ) {
+                       Logger::warning(
+                               "Error retrying auth on order reference 
$orderReferenceId: " .
+                               $ex->getMessage()
+                       );
+                       return false;
+               }
+
+               return true;
+       }
+}
diff --git a/PaymentProviders/Amazon/AmazonListener.php 
b/PaymentProviders/Amazon/AmazonListener.php
index d40a6e7..1351e2c 100644
--- a/PaymentProviders/Amazon/AmazonListener.php
+++ b/PaymentProviders/Amazon/AmazonListener.php
@@ -21,6 +21,9 @@
                        'Completed' => 
'SmashPig\PaymentProviders\Amazon\ExpatriatedMessages\RefundCompleted',
                        'Declined' => 
'SmashPig\PaymentProviders\Amazon\ExpatriatedMessages\RefundDeclined',
                ],
+               'PaymentAuthorize' => [
+                       'Declined' => 
'SmashPig\PaymentProviders\Amazon\ExpatriatedMessages\AuthorizationDeclined',
+               ]
        ];
 
        protected function parseEnvelope( Request $request ) {
@@ -87,6 +90,8 @@
                                return 
$values['CaptureDetails']['CaptureStatus']['State'];
                        case 'PaymentRefund':
                                return 
$values['RefundDetails']['RefundStatus']['State'];
+                       case 'PaymentAuthorize':
+                               return 
$values['AuthorizationDetails']['AuthorizationStatus']['State'];
                        default:
                                return false;
                }
diff --git a/PaymentProviders/Amazon/ExpatriatedMessages/AmazonMessage.php 
b/PaymentProviders/Amazon/ExpatriatedMessages/AmazonMessage.php
index 2939874..43b0273 100644
--- a/PaymentProviders/Amazon/ExpatriatedMessages/AmazonMessage.php
+++ b/PaymentProviders/Amazon/ExpatriatedMessages/AmazonMessage.php
@@ -34,6 +34,14 @@
                return true;
        }
 
+       public function getCurrency() {
+               return $this->currency;
+       }
+
+       public function getGross() {
+               return $this->gross;
+       }
+
        protected function setGatewayIds( $amazonId ) {
                $this->gateway_txn_id = $amazonId;
        }
diff --git 
a/PaymentProviders/Amazon/ExpatriatedMessages/AuthorizationDeclined.php 
b/PaymentProviders/Amazon/ExpatriatedMessages/AuthorizationDeclined.php
new file mode 100644
index 0000000..91dc48a
--- /dev/null
+++ b/PaymentProviders/Amazon/ExpatriatedMessages/AuthorizationDeclined.php
@@ -0,0 +1,19 @@
+<?php namespace SmashPig\PaymentProviders\Amazon\ExpatriatedMessages;
+
+class AuthorizationDeclined extends PaymentAuthorization {
+
+       /**
+        * @var string should be one of the constants in ReasonCode
+        */
+       protected $reasonCode;
+
+       public function __construct( $values ) {
+               parent::__construct( $values );
+               $details = $values['AuthorizationDetails'];
+               $this->reasonCode = 
$details['AuthorizationStatus']['ReasonCode'];
+       }
+
+       public function getReasonCode() {
+               return $this->reasonCode;
+       }
+}
diff --git 
a/PaymentProviders/Amazon/ExpatriatedMessages/PaymentAuthorization.php 
b/PaymentProviders/Amazon/ExpatriatedMessages/PaymentAuthorization.php
new file mode 100644
index 0000000..7c46a44
--- /dev/null
+++ b/PaymentProviders/Amazon/ExpatriatedMessages/PaymentAuthorization.php
@@ -0,0 +1,43 @@
+<?php namespace SmashPig\PaymentProviders\Amazon\ExpatriatedMessages;
+
+use SmashPig\Core\UtcDate;
+
+abstract class PaymentAuthorization extends AmazonMessage {
+
+       protected $order_id;
+       protected $contribution_tracking_id;
+       protected $amount;
+
+       public function __construct( $values ) {
+               parent::__construct();
+               $details = $values['AuthorizationDetails'];
+
+               $captureReferenceId = $details['AuthorizationReferenceId'];
+
+               $this->setOrderId( $captureReferenceId );
+
+               $this->date = UtcDate::getUtcTimestamp( 
$details['CreationTimestamp'] );
+
+               $this->currency = 
$details['AuthorizationAmount']['CurrencyCode'];
+               $this->gross = $details['AuthorizationAmount']['Amount'];
+       }
+
+       /**
+        * Set fields derived from the order ID
+        *
+        * @param string $orderId
+        */
+       public function setOrderId( $orderId ) {
+               $this->order_id = $orderId;
+
+               $parts = explode( '-', $orderId );
+               $this->contribution_tracking_id = $parts[0];
+       }
+
+       /**
+        * @return string
+        */
+       public function getOrderId() {
+               return $this->order_id;
+       }
+}
diff --git a/PaymentProviders/Amazon/ReasonCode.php 
b/PaymentProviders/Amazon/ReasonCode.php
new file mode 100644
index 0000000..f4422fc
--- /dev/null
+++ b/PaymentProviders/Amazon/ReasonCode.php
@@ -0,0 +1,11 @@
+<?php
+
+namespace SmashPig\PaymentProviders\Amazon;
+
+class ReasonCode {
+       const TRANSACTION_TIMED_OUT = 'TransactionTimedOut';
+       const INVALID_PAYMENT_METHOD = 'InvalidPaymentMethod';
+       const AMAZON_REJECTED = 'AmazonRejected';
+       const PROCESSING_FAILURE = 'ProcessingFailure';
+       const MAX_CAPTURES_PROCESSED = 'MaxCapturesProcessed';
+}
diff --git a/PaymentProviders/Amazon/Tests/Data/IPN/AuthorizationDeclined.json 
b/PaymentProviders/Amazon/Tests/Data/IPN/AuthorizationDeclined.json
new file mode 100644
index 0000000..fa9bebf
--- /dev/null
+++ b/PaymentProviders/Amazon/Tests/Data/IPN/AuthorizationDeclined.json
@@ -0,0 +1,37 @@
+{
+    "NotificationReferenceId": "1111111-1111-11111-1111-11111EXAMPLE",
+    "NotificationType": "PaymentAuthorize",
+    "IsSample": true,
+    "SellerId": "AYIWJDULFQUMA",
+    "ReleaseEnvironment": "Sandbox",
+    "Version": "2013-01-01",
+    "AuthorizationDetails": {
+        "AuthorizationAmount": {
+            "Amount": "10.0",
+            "CurrencyCode": "USD"
+        },
+        "CapturedAmount": {
+            "Amount": "0",
+            "CurrencyCode": "USD"
+        },
+        "SoftDescriptor": "AMZ*softDescriptor",
+        "ExpirationTimestamp": "2013-01-01T01:01:01.001Z",
+        "SoftDecline": false,
+        "AuthorizationStatus": {
+            "State": "Declined",
+            "LastUpdateTimestamp": "2013-01-01T01:01:01.001Z",
+            "ReasonCode": "TransactionTimedOut"
+        },
+        "AuthorizationFee": {
+            "Amount": "0.0",
+            "CurrencyCode": "USD"
+        },
+        "CaptureNow": true,
+        "CreationTimestamp": "2013-01-01T01:01:01.001Z",
+        "AmazonAuthorizationId": "P01-0000000-0000000-000000",
+        "AuthorizationReferenceId": "1234567-1"
+    },
+    "Type": "Notification",
+    "MessageId": "f10a0798-672d-564b-8312-49f2f5c2db3b",
+    "TopicArn": 
"arn:aws:sns:us-east-1:291180941288:A3BXB0YN3XH17HAYIWJDULFQUMA"
+}

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ia959ac2e6efc27ddd2527d8aa38b153946132ff8
Gerrit-PatchSet: 1
Gerrit-Project: wikimedia/fundraising/SmashPig
Gerrit-Branch: master
Gerrit-Owner: Ejegg <ej...@ejegg.com>

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

Reply via email to