EDIT: The first version (ppext.tar.gz / ppext.zip in this post) has faulty IPN-code,
please download from the url above.
I am developing an event based PayPal extension for Yii, and would like to know it there is any interest in this? Feedback and feature requests are very welcome.
Features so far:
Button manager (you specify settings using an array of NVP-values)
PDT handler
IPN handler
Logging via Yii::log()
EXAMPLE USAGE
PDT- and IPN listeners (see src-code for a better example, including some payment processing)
class MinimalController extends Controller
{
public function actionPdt() {
$pdt = new PPPdtAction($this, "pdt");
// Process payment
$pdt->onRequest = function($event) {
$this->onSuccess($event);
};
// Notify user on success
$pdt->onSuccess = function($event) {
$event->sender->controller->renderText("Success");
};
// Notify user on failure
$pdt->onFailure = function($event) {
$event->sender->controller->renderText("Failure");
};
$pdt->run();
}
public function actionIpn() {
$ipn = new PPIpnAction($this,"ipn");
// Process payment
$ipn->onRequest = function($event) {
$event->setMsg("Received payment.");
$ipn->onSuccess($event);
};
// Log success
$ipn->onSuccess = function($event) {
Yii::log($event->msg, "info", "payPal.controllers.DefaultController");
};
// Log failure
$ipn->onFailure = function($event) {
Yii::log($event->msg, "error", "payPal.controller.DefaultController");
};
$ipn->run();
}
}
I have done some refactoring and cleaned up the IPN and PDT functionality.
All IPN and PDT events are logged (success and failure)
Moved ipnRequest and pdtRequest from PPUtils into IPN- and PDT actions
Details about events (payments usually) is now stored in PPEvent::details
The new event class:
class PPEvent extends CEvent {
public $responseAr = array(); // HTTP Response from PayPal
public $requestAr = array(); // HTTP Request sent to PayPal
public $details = array(); // Verified payment details (assoc array)
public $msg = ""; // Description of event
}
Version 0.2 will be uploaded as soon as I have finished a couple of additional improvements, and testing.
The run method in PPIpnAction class check that txn_id exist otherwise it is consider the notification as failure without even doing the validation with Paypal.
I think it should validation the notification with Paypal no matter what. And log any invalidate notification as hack attempt.
Also there are notification that does not contain txn_id. For example subscr_cancel or the subscription update. Maybe we should check both subscr_id and txn_id before marking the notification as failure.
I think it’s sensible to remove the txn_id check. Then all requests will be validated (failures are also logged) and txn_id / subscr_id can be checked by a simple isset() in onRequest.
EDIT: I have made the changes, check out version 0.4.
Thank you very much. I copy PPDefaultLegacyController to protected/controllers/PayController.php Instant Payment Notification Preferences i set http://mydomain.com/pay/ipn/ and everything become good, my site receive payments results. but there is another question, how to send for example user_id to paypal and then receive this user_id to make some actions on my site. I read about “custom” but can’t create button with “custom” parametr and don’t know how to receive this parametr from paypal.
To create buttons with the "custom" parameter set to $userId, you can include the following code in your controller (use getButtonForm($id,$userId) instead of $buttonManager->getButton($id)->webSiteCode in your actions):
/**
* Get button form (HTML code) for button $id including
* custom field with $userId as value.
*
* @param string $id Button id
* @param string $userId User id
* @return string HTML Form
*/
public function getButtonForm($id,$userId) {
if ( ($button = $this->buttonManager->getButton($id)) !== false)
return self::addHiddenField('custom',$userId,$button->webSiteCode);
else return false;
}
/**
* Add hidden field to form.
*
* @param string $name Field name (e.g. 'custom')
* @param string $value Field value (e.g. 'My custom value')
* @param string $form Form (e.g. $button->webSiteCode)
* @return string Form with hidden an extra hidden field
*/
public static function addHiddenField($name,$value,$form) {
return preg_replace(
'/< *\/form *>/i',
'<input type="hidden" name="'.$name.'" value="'.$value.'" />'."\n</form>\n",
$form
);
}
When you receive the IPN- and PDT notifications from PayPal, the user id can be found in $event->details[‘custom’].
I will include a better mechanism for this sort of thing in the next version.