jenkins-bot has submitted this change and it was merged. (
https://gerrit.wikimedia.org/r/399841 )
Change subject: Amazon: automatic retry on TransactionTimedOut
......................................................................
Amazon: automatic retry on TransactionTimedOut
Donor services has been doing this by hand. Let's make things easier
for them! This should go out along with the DonationInterface patch
that makes sure these donors see the thank you page.
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
M PaymentProviders/Amazon/Tests/phpunit/ActionsTest.php
8 files changed, 219 insertions(+), 1 deletion(-)
Approvals:
XenoRyet: Looks good to me, approved
jenkins-bot: Verified
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..4490b96 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 ) {
@@ -72,7 +75,9 @@
$secureLog->debug( 'Created message', $message
);
$messages[] = $message;
} else {
- Logger::info( "Message ignored: status =
{$status}" );
+ Logger::info(
+ "Message ignored: notificationType =
{$type}, status = {$status}"
+ );
}
} else {
Logger::info( "Message ignored: notificationType =
{$type}" );
@@ -87,6 +92,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"
+}
diff --git a/PaymentProviders/Amazon/Tests/phpunit/ActionsTest.php
b/PaymentProviders/Amazon/Tests/phpunit/ActionsTest.php
index 9b34964..03257b1 100644
--- a/PaymentProviders/Amazon/Tests/phpunit/ActionsTest.php
+++ b/PaymentProviders/Amazon/Tests/phpunit/ActionsTest.php
@@ -2,6 +2,8 @@
namespace SmashPig\PaymentProviders\Amazon\Tests;
use SmashPig\PaymentProviders\Amazon\Actions\ReconstructMerchantReference;
+use SmashPig\PaymentProviders\Amazon\Actions\RetryAuthorization;
+use SmashPig\PaymentProviders\Amazon\ExpatriatedMessages\AuthorizationDeclined;
use SmashPig\PaymentProviders\Amazon\ExpatriatedMessages\CaptureCompleted;
class ActionsTest extends AmazonTestCase {
@@ -28,4 +30,29 @@
$this->assertEquals( '98765432-1', $message->getOrderId() );
$this->assertEmpty( $this->mockClient->calls );
}
+
+ /**
+ * Retry auths declined because TransactionTimedOut
+ */
+ public function testRetryAuthorizationTimedOut() {
+ $authDeclined = $this->loadJson( __DIR__ .
"/../Data/IPN/AuthorizationDeclined.json" );
+ $message = new AuthorizationDeclined( $authDeclined );
+ $action = new RetryAuthorization();
+ $action->execute( $message );
+ $this->assertArrayHasKey( 'authorize', $this->mockClient->calls
);
+ $params = $this->mockClient->calls['authorize'][0];
+ $originalDetails = $authDeclined['AuthorizationDetails'];
+ $this->assertEquals(
+ $originalDetails['AuthorizationAmount']['Amount'],
+ $params['authorization_amount']
+ );
+ $this->assertEquals(
+ $originalDetails['AuthorizationReferenceId'],
+ $params['authorization_reference_id']
+ );
+ $this->assertEquals(
+ $message->getOrderReferenceId(),
+ $params['amazon_order_reference_id']
+ );
+ }
}
--
To view, visit https://gerrit.wikimedia.org/r/399841
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Ia959ac2e6efc27ddd2527d8aa38b153946132ff8
Gerrit-PatchSet: 2
Gerrit-Project: wikimedia/fundraising/SmashPig
Gerrit-Branch: master
Gerrit-Owner: Ejegg <[email protected]>
Gerrit-Reviewer: Mepps <[email protected]>
Gerrit-Reviewer: Siebrand <[email protected]>
Gerrit-Reviewer: XenoRyet <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits