thephpleague / omnipay-common

Core components for the Omnipay PHP payment processing library
MIT License
329 stars 242 forks source link

Symfony request converts some characters in server request #194

Open judgej opened 6 years ago

judgej commented 6 years ago

This is Omnipay 3.x that uses Symfony\Component\HttpFoundation\Request to deliver the server request in a notification handler.

To get the POST data normally you would use $this->getRequest()->request->all(). This will returns an array of POST parameters.

However, it follows PHP's historical conversion of parameter keys to be compatible with variable names. So a parameter billingAddress.city ends up arriving as billingAddress_city. Spaces in key names also get converted to underscores. This can make the handling of data from some gateways very difficult.

Now, the policy was set in 2014 that Symfony will not "work around what PHP does by default". I personally disagree with this - a request class should be delivering what the HTTP standards are sending, not what PHP did when register_globals was still a thing.

Anyway - I think since we are dealing with APIs here - pure data - Omnipay should perhaps provide its own parsing of Form POST data, and making the explicit policy that what is presented to the gateway is the POST data that is sent.

Any opinions on this?

I'm using this method to parse the POST data in a new driver:

    public function parsePostData($postStr)
    {
        $data = [];

        $paramPairs = explode('&', $postStr);

        foreach ($paramPairs as $paramPair) {
            if (strpos($paramPair, '=') === false) {
                // A parameter does not need to have a value.
                $data[urldecode($paramPair)] = '';
            } else {
                list($key, $value) = explode('=', $paramPair, 2);

                $data[urldecode($key)] = urldecode($value);
            }
        }

        return $data;
    }

That will parse a (string)$this->httpRequest->getContent() string into an array. It works for me, but it may need some UTF-8 or other encoding tweaks, but I'm just posting it for the discussion.

That parser does not try to expand posted parameters any further (such as foo[] to an array) but that's probably just as well, as gateways tend not to use PHP-specific parameter names.