22
33namespace Drupal \commerce_paypal \Plugin \Commerce \PaymentGateway ;
44
5+ use Drupal \commerce \TimeInterface ;
56use Drupal \commerce_order \Entity \OrderInterface ;
67use Drupal \commerce_payment \Entity \PaymentInterface ;
78use Drupal \commerce_payment \Exception \InvalidRequestException ;
89use Drupal \commerce_payment \Exception \PaymentGatewayException ;
910use Drupal \commerce_payment \PaymentMethodTypeManager ;
1011use Drupal \commerce_payment \PaymentTypeManager ;
12+ use Drupal \commerce_payment \Plugin \Commerce \PaymentGateway \OffsitePaymentGatewayBase ;
1113use Drupal \commerce_price \Price ;
1214use Drupal \commerce_price \RounderInterface ;
1315use Drupal \Core \Entity \EntityTypeManagerInterface ;
1416use Drupal \Core \Form \FormStateInterface ;
17+ use Drupal \Core \Logger \LoggerChannelFactoryInterface ;
1518use GuzzleHttp \ClientInterface ;
1619use Symfony \Component \HttpFoundation \Request ;
1720use Symfony \Component \DependencyInjection \ContainerInterface ;
3235 * },
3336 * )
3437 */
35- class ExpressCheckout extends PayPalIPNGatewayBase implements ExpressCheckoutInterface {
38+ class ExpressCheckout extends OffsitePaymentGatewayBase implements ExpressCheckoutInterface {
39+
40+ /**
41+ * The logger.
42+ *
43+ * @var \Drupal\Core\Logger\LoggerChannelInterface
44+ */
45+ protected $ logger ;
3646
3747 /**
3848 * The HTTP client.
@@ -42,19 +52,49 @@ class ExpressCheckout extends PayPalIPNGatewayBase implements ExpressCheckoutInt
4252 protected $ httpClient ;
4353
4454 /**
45- * The rounder.
55+ * The price rounder.
4656 *
4757 * @var \Drupal\commerce_price\RounderInterface
4858 */
4959 protected $ rounder ;
5060
5161 /**
52- * {@inheritdoc}
62+ * The time.
63+ *
64+ * @var \Drupal\commerce\TimeInterface
65+ */
66+ protected $ time ;
67+
68+ /**
69+ * Constructs a new PaymentGatewayBase object.
70+ *
71+ * @param array $configuration
72+ * A configuration array containing information about the plugin instance.
73+ * @param string $plugin_id
74+ * The plugin_id for the plugin instance.
75+ * @param mixed $plugin_definition
76+ * The plugin implementation definition.
77+ * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
78+ * The entity type manager.
79+ * @param \Drupal\commerce_payment\PaymentTypeManager $payment_type_manager
80+ * The payment type manager.
81+ * @param \Drupal\commerce_payment\PaymentMethodTypeManager $payment_method_type_manager
82+ * The payment method type manager.
83+ * @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $logger_channel_factory
84+ * The logger channel factory.
85+ * @param \GuzzleHttp\ClientInterface $client
86+ * The client.
87+ * @param \Drupal\commerce_price\RounderInterface $rounder
88+ * The price rounder.
89+ * @param \Drupal\commerce\TimeInterface $time
90+ * The time.
5391 */
54- public function __construct (array $ configuration , $ plugin_id , $ plugin_definition , EntityTypeManagerInterface $ entity_type_manager , PaymentTypeManager $ payment_type_manager , PaymentMethodTypeManager $ payment_method_type_manager , ClientInterface $ client , RounderInterface $ rounder ) {
92+ public function __construct (array $ configuration , $ plugin_id , $ plugin_definition , EntityTypeManagerInterface $ entity_type_manager , PaymentTypeManager $ payment_type_manager , PaymentMethodTypeManager $ payment_method_type_manager , LoggerChannelFactoryInterface $ logger_channel_factory , ClientInterface $ client , RounderInterface $ rounder, TimeInterface $ time ) {
5593 parent ::__construct ($ configuration , $ plugin_id , $ plugin_definition , $ entity_type_manager , $ payment_type_manager , $ payment_method_type_manager );
94+ $ this ->logger = $ logger_channel_factory ->get ('commerce_paypal ' );
5695 $ this ->httpClient = $ client ;
5796 $ this ->rounder = $ rounder ;
97+ $ this ->time = $ time ;
5898 }
5999
60100 /**
@@ -68,8 +108,10 @@ public static function create(ContainerInterface $container, array $configuratio
68108 $ container ->get ('entity_type.manager ' ),
69109 $ container ->get ('plugin.manager.commerce_payment_type ' ),
70110 $ container ->get ('plugin.manager.commerce_payment_method_type ' ),
111+ $ container ->get ('logger.factory ' ),
71112 $ container ->get ('http_client ' ),
72- $ container ->get ('commerce_price.rounder ' )
113+ $ container ->get ('commerce_price.rounder ' ),
114+ $ container ->get ('commerce.time ' )
73115 );
74116 }
75117
@@ -195,13 +237,13 @@ public function onReturn(OrderInterface $order, Request $request) {
195237 $ paypal_response = $ this ->doExpressCheckoutDetails ($ order );
196238
197239 // Nothing to do for failures for now - no payment saved.
198- // ToDo - more about the failures.
240+ // @todo - more about the failures.
199241 if ($ paypal_response ['PAYMENTINFO_0_PAYMENTSTATUS ' ] == 'Failed ' ) {
200242 throw new PaymentGatewayException ($ paypal_response ['PAYMENTINFO_0_LONGMESSAGE ' ], $ paypal_response ['PAYMENTINFO_0_ERRORCODE ' ]);
201243 }
202244
203245 $ payment_storage = $ this ->entityTypeManager ->getStorage ('commerce_payment ' );
204- $ request_time = \Drupal:: service ( ' commerce. time' ) ->getRequestTime ();
246+ $ request_time = $ this -> time ->getRequestTime ();
205247 $ payment = $ payment_storage ->create ([
206248 'state ' => 'authorization ' ,
207249 'amount ' => $ order ->getTotalPrice (),
@@ -214,7 +256,7 @@ public function onReturn(OrderInterface $order, Request $request) {
214256 ]);
215257
216258 // Process payment status received.
217- // ToDo : payment updates if needed.
259+ // @todo payment updates if needed.
218260 // If we didn't get an approval response code...
219261 switch ($ paypal_response ['PAYMENTINFO_0_PAYMENTSTATUS ' ]) {
220262 case 'Voided ' :
@@ -358,7 +400,7 @@ public function onNotify(Request $request) {
358400 // transaction IDs, indicating they are non-payment IPNs such as those used
359401 // for subscription signup requests.
360402 if (empty ($ ipn_data ['txn_id ' ])) {
361- \Drupal:: logger ( ' commerce_paypal ' ) ->alert ('The IPN request does not have a transaction id. Ignored. ' );
403+ $ this -> logger ->alert ('The IPN request does not have a transaction id. Ignored. ' );
362404 return FALSE ;
363405 }
364406 // Exit when we don't get a payment status we recognize.
@@ -372,7 +414,7 @@ public function onNotify(Request $request) {
372414 // If not, bail now because authorization transactions should be created
373415 // by the Express Checkout API request itself.
374416 if (!$ payment ) {
375- \Drupal:: logger ( ' commerce_paypal ' ) ->warning ('IPN for Order @order_number ignored: authorization transaction already created. ' , ['@order_number ' => $ ipn_data ['invoice ' ]]);
417+ $ this -> logger ->warning ('IPN for Order @order_number ignored: authorization transaction already created. ' , ['@order_number ' => $ ipn_data ['invoice ' ]]);
376418 return FALSE ;
377419 }
378420 $ amount = new Price ($ ipn_data ['mc_gross ' ], $ ipn_data ['mc_currency ' ]);
@@ -389,7 +431,7 @@ public function onNotify(Request $request) {
389431
390432 case 'Completed ' :
391433 $ payment ->state = 'capture_completed ' ;
392- $ payment ->setCapturedTime (REQUEST_TIME );
434+ $ payment ->setCapturedTime ($ this -> time -> getRequestTime () );
393435 break ;
394436 }
395437 // Update the remote id.
@@ -399,15 +441,14 @@ public function onNotify(Request $request) {
399441 // Get the corresponding parent transaction and refund it.
400442 $ payment = $ this ->loadPaymentByRemoteId ($ ipn_data ['parent_txn_id ' ]);
401443 if (!$ payment ) {
402- \Drupal:: logger ( ' commerce_paypal ' ) ->warning ('IPN for Order @order_number ignored: the transaction to be refunded does not exist. ' , ['@order_number ' => $ ipn_data ['invoice ' ]]);
444+ $ this -> logger ->warning ('IPN for Order @order_number ignored: the transaction to be refunded does not exist. ' , ['@order_number ' => $ ipn_data ['invoice ' ]]);
403445 return FALSE ;
404446 }
405447 elseif ($ payment ->getState () == 'capture_refunded ' ) {
406- \Drupal:: logger ( ' commerce_paypal ' ) ->warning ('IPN for Order @order_number ignored: the transaction is already refunded. ' , ['@order_number ' => $ ipn_data ['invoice ' ]]);
448+ $ this -> logger ->warning ('IPN for Order @order_number ignored: the transaction is already refunded. ' , ['@order_number ' => $ ipn_data ['invoice ' ]]);
407449 return FALSE ;
408450 }
409- $ amount_number = abs ($ ipn_data ['mc_gross ' ]);
410- $ amount = new Price ((string ) $ amount_number , $ ipn_data ['mc_currency ' ]);
451+ $ amount = new Price ((string ) $ ipn_data ['mc_gross ' ], $ ipn_data ['mc_currency ' ]);
411452 // Check if the Refund is partial or full.
412453 $ old_refunded_amount = $ payment ->getRefundedAmount ();
413454 $ new_refunded_amount = $ old_refunded_amount ->add ($ amount );
@@ -425,7 +466,7 @@ public function onNotify(Request $request) {
425466 else {
426467 // In other circumstances, exit the processing, because we handle those
427468 // cases directly during API response processing.
428- \Drupal:: logger ( ' commerce_paypal ' ) ->notice ('IPN for Order @order_number ignored: this operation was accommodated in the direct API response. ' , ['@order_number ' => $ ipn_data ['invoice ' ]]);
469+ $ this -> logger ->notice ('IPN for Order @order_number ignored: this operation was accommodated in the direct API response. ' , ['@order_number ' => $ ipn_data ['invoice ' ]]);
429470 return FALSE ;
430471 }
431472 if (isset ($ payment )) {
@@ -683,4 +724,23 @@ public function doRequest(array $nvp_data) {
683724 return $ paypal_response ;
684725 }
685726
727+ /**
728+ * Loads the payment for a given remote id.
729+ *
730+ * @param string $remote_id
731+ * The remote id property for a payment.
732+ *
733+ * @return \Drupal\commerce_payment\Entity\PaymentInterface
734+ * Payment object.
735+ *
736+ * @todo: to be replaced by Commerce core payment storage method
737+ * @see https://www.drupal.org/node/2856209
738+ */
739+ protected function loadPaymentByRemoteId ($ remote_id ) {
740+ /** @var \Drupal\commerce_payment\PaymentStorage $storage */
741+ $ storage = $ this ->entityTypeManager ->getStorage ('commerce_payment ' );
742+ $ payment_by_remote_id = $ storage ->loadByProperties (['remote_id ' => $ remote_id ]);
743+ return reset ($ payment_by_remote_id );
744+ }
745+
686746}
0 commit comments