Yii and PayPal IPN (400 Bad Request via IPN Simulator)

Hi,

Does anyone here have any experience with setting up a PayPal IPN receiver with Yii, as I’ve hit a problem that’s rather difficult to trace.

If I go to the PayPal sandbox site, and enter -any- URL on the site that uses the Yii framework, I get a “400 Bad Request” message back. If I load any file which doesn’t use the Yii framework, the IPN message is sent successfully.

I haven’t gotten very far in terms of tracing it, but if I go to the main index.php and comment out this line:

Then the IPN Simulator says the request was sent successfully. The request never reaches the controller, as any database logging calls I add on SiteController.actionPayPalIPN do not get run. Thus, the error must be occuring somewhere within the Yii Framework itself, possibly as a result of all the POST variables sent from the IPN Simulator. I’ve already checked the URL that gets invoked, and it’s exactly the same was what I enter on the tester, with no get parameters tacked on.

Has anyone else run into this issue before?

Did you allow actionPayPalIPN in accessControl?

/Tommy

Not specifically, no, I’m using SiteController, which by default doesn’t have any accessRules.

I did find something more concrete though. I did a local implementation of what the IPN Simulator is sending, and I got this out:

So the guilty party is the enabling of Csrf Validation in the config:

I added that as per the security guidelines. Disabling it gets rid of the error, but then weakens the site’s security.

Is there a way to specify that the validation shouldn’t be done on requests to the SiteController.actionPayPalIPN, or is there a way to set certain URLs as trusted, etc, etc?

Seems you need to derive a new class from CHttpRequest and override its validateCsrfToken() method:




class MyHttpRequest extends CHttpRequest

{

  public validateCsrfToken(CEvent $event)

  {

    if (!isTrustedRequest())

      parent::validateCsrfToken( $event );

  }


  /**

   * Whatever you think is appropriate...

   * (referrer, action, anything payPal sends to authenticate itself?)

   */

  protected isTrustedRequest()

  {

    [...]

  }

}



Then, in your config:




'request' => array(

  'class' => 'path.to.MyHttpRequest',

  [...]

),



This is not safe but this is what I had to put in my controller to make it work


  public $enableCsrfValidation = false;