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