-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Issue #2843999 by mglaman, bojanz, vasike: Implement IPN handler. #4
base: 8.x-1.x
Are you sure you want to change the base?
Changes from 2 commits
6e9ac25
a0d50f4
0bac0a3
b31423e
d2a1306
3fc64be
79125fa
45540f7
7285d56
e3570ac
10ad9d0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
<?php | ||
|
||
namespace Drupal\commerce_paypal\Plugin\Commerce\PaymentGateway; | ||
|
||
use Symfony\Component\HttpFoundation\Request; | ||
|
||
/** | ||
* Provides common methods to be used by PayPal payment gateways. | ||
*/ | ||
trait PaypalPaymentGatewayTrait { | ||
|
||
/** | ||
* Loads the payment for a given remote id. | ||
* | ||
* @param string $remote_id | ||
* The remote id property for a payment. | ||
* | ||
* @return \Drupal\commerce_payment\Entity\PaymentInterface | ||
* Payment object. | ||
*/ | ||
public function loadPaymentByRemoteId($remote_id) { | ||
/** @var \Drupal\commerce_payment\PaymentStorage $storage */ | ||
$storage = \Drupal::service('entity_type.manager')->getStorage('commerce_payment'); | ||
$payment_by_remote_id = $storage->loadByProperties(['remote_id' => $remote_id]); | ||
return reset($payment_by_remote_id); | ||
} | ||
|
||
/** | ||
* Processes an incoming IPN request. | ||
* | ||
* @param Request $request | ||
* The request. | ||
* | ||
* @return mixed | ||
* The request data array or FALSE. | ||
*/ | ||
public function processIpnRequest(Request $request) { | ||
// Validate and get IPN request data. | ||
$ipn_data = $this->getIpnRequestValidate($request); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since this method is pretty empty, let's just keep validation in here as part of the process. We can always split out later if needed. Otherwise we'd just need to call "validate". |
||
|
||
// ToDo other general validations for IPN data. | ||
return $ipn_data; | ||
} | ||
|
||
/** | ||
* Validate an incoming IPN request and return the request data for extra | ||
* processing. | ||
* | ||
* @param Request $request | ||
* The request. | ||
* | ||
* @return mixed | ||
* The request data array or FALSE. | ||
*/ | ||
public function getIpnRequestValidate(Request $request) { | ||
// Get IPN request data. | ||
$ipn_data = $this->getRequestDataArray($request->getContent()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be in process, if we keep both methods. Process gets data, then sends it to be validated. |
||
|
||
// Exit now if the $_POST was empty. | ||
if (empty($ipn_data)) { | ||
\Drupal::logger('commerce_paypal')->warning('IPN URL accessed with no POST data submitted.'); | ||
return FALSE; | ||
} | ||
|
||
// Make PayPal request for IPN validation. | ||
$url = $this->getIpnValidationUrl($ipn_data); | ||
$validate_ipn = 'cmd=_notify-validate&' . $request->getContent(); | ||
$request = \Drupal::httpClient()->post($url, [ | ||
'body' => $validate_ipn, | ||
])->getBody(); | ||
$paypal_response = $this->getRequestDataArray($request->getContents()); | ||
|
||
// If the IPN was invalid, log a message and exit. | ||
if (isset($paypal_response['INVALID'])) { | ||
\Drupal::logger('commerce_paypal')->alert('Invalid IPN received and ignored.'); | ||
return FALSE; | ||
} | ||
return $ipn_data; | ||
} | ||
|
||
/** | ||
* Get data array from a request content. | ||
* | ||
* @param string $request_content | ||
* The Request content. | ||
* | ||
* @return array | ||
* The request data array. | ||
*/ | ||
public function getRequestDataArray($request_content) { | ||
parse_str(html_entity_decode($request_content), $ipn_data); | ||
return $ipn_data; | ||
} | ||
|
||
/** | ||
* Gets the IPN URL to be used for validation for IPN data. | ||
* | ||
* @param array $ipn_data | ||
* The IPN request data from PayPal. | ||
* | ||
* @return string | ||
* The IPN validation URL. | ||
*/ | ||
public function getIpnValidationUrl(array $ipn_data) { | ||
if (!empty($ipn_data['test_ipn']) && $ipn_data['test_ipn'] == 1) { | ||
return 'https://www.sandbox.paypal.com/cgi-bin/webscr'; | ||
} | ||
else { | ||
return 'https://www.paypal.com/cgi-bin/webscr'; | ||
} | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there an issue to port this to the payment storage? If so, let's make a
@todo
referencing it. If not, make the issue and make the@todo
:)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
new issue and patch for Commerce
https://www.drupal.org/node/2856209
and i'll put in a comment as suggested
thanks