David Ericsson
David Ericsson

Reputation: 2660

Sha-out sign not matching in Ogone

I'm trying to make a payment plugin for my webshop for Ogone ideal payments. I can make a payment, but when I return I cannot get the SHA-signs to match.

I have the following get request on return:

orderID=476&amount=90%2E82&PM=iDEAL&ACCEPTANCE=0000000000&STATUS=9&PAYID=43934127&NCERROR=0&BRAND=iDEAL&SHASIGN=5AB0A065BAA83C5D807249A66E661ACBB6709B8F

According to the documentation, I have to order the keys alphabetically and only hash those that are allowed.

These are the allowed keys:

['AAVADDRESS', 'AAVCHECK', 'AAVZIP', 'ACCEPTANCE', 'ALIAS', 'AMOUNT', 'BRAND', 'CARDNO', 'CCCTY', 'CN', 'COMPLUS', 'CURRENCY', 'CVCCHECK', 'DCC_COMMPERCENTAGE', 'DCC_CONVAMOUNT', 'DCC_CONVCCY', 'DCC_EXCHRATE', 'DCC_EXCHRATESOURCE', 'DCC_EXCHRATETS', 'DCC_INDICATOR', 'DCC_MARGINPERCENTAGE', 'DCC_VALIDHOUS', 'DIGESTCARDNO', 'ECI', 'ED', 'ENCCARDNO', 'IP', 'IPCTY', 'NBREMAILUSAGE', 'NBRIPUSAGE', 'NBRIPUSAGE_ALLTX', 'NBRUSAGE', 'NCERROR', 'ORDERID', 'PAYID', 'PM', 'SCO_CATEGORY', 'SCORING', 'STATUS', 'TRXDATE', 'VC'];

I made this method to make the hash:

/**
 * @return string
 */
protected function getShaOutSign()
{
    $hash = '';
    $values = \Input::all();
    $values = array_change_key_case($values, CASE_UPPER);
    ksort($values);

    foreach ($values as $key => $value) {
        if (in_array($key, $this->shaOut)) {

            if(!empty($value))
            {
                $hash .= $key . '=' . $values[$key] . $this->settings->shaout;
            }
        }
    }

    return  strtoupper(sha1($hash));
}

I'm 100% sure the SHA out key is correct.

The string it makes before I do SHA1:

ACCEPTANCE=0000000000abcDEFghj1234560987654AMOUNT=90.82abcDEFghj1234560987654BRAND=iDEALabcDEFghj1234560987654ORDERID=476abcDEFghj1234560987654PAYID=43934127abcDEFghj1234560987654PM=iDEALabcDEFghj1234560987654STATUS=9abcDEFghj1234560987654

And the final hash I get is:

68E459CB933E04B582A5D564CE6F591D5819B7F1

No matter what I try, I just can't get it to match it with the one in the $_GET request.

My sha-out key: abcDEFghj1234560987654

What can I try next?

Upvotes: 1

Views: 1215

Answers (3)

Alex Melnikov
Alex Melnikov

Reputation: 83

Anyone still uses legacy Ogone/Ingenico/Wordline nowdays? ;)

The solution by @DarkBee is correct, however could be simplified:

private function calculateHash($secret, $fields)
{
    $hash = '';

    ksort($fields, SORT_STRING | SORT_FLAG_CASE);
    $fields = array_change_key_case($fields, CASE_UPPER);

    foreach ($fields as $key => $field) {
        if (!empty($field)) {
            $hash .= sprintf('%s=%s%s', $key, $field, $secret);
        }
    }

    return strtoupper(sha1($hash));
}

First you need sort the array of fields "as is" keeping the current keys case. Then convert those keys to upper case. And only after that concatenate the result array to calculate hash.

Upvotes: 0

Laars
Laars

Reputation: 11

The problem is clearly that part:

if(!empty($value))
{
    $hash .= $key . '=' . $values[$key] . $this->settings->shaout;
}

Your request contains '...&NCERROR=0...'.

So the value is 0. And 0 is empty.

I had the same problem. But I used array_filter() function:

$parameters = array_filter($parameters);

Also array_filter() removed my 'empty' ncerror field.

Upvotes: 1

DarkBee
DarkBee

Reputation: 15650

The sha out calculation is wrong. This is the code I use in my projects to calculate it, $sha_parms is the full response of Ogone. So $_POST or $_GET

            /**
            * Function to calculate the sha that is received from Ogone
            */
            public function getShaOut($sha_parms, $sha_out = null) {
                    $sha_out = $sha_out ?: self::PASS_PHRASE_OUT;
                    $sha_parms = $this->ogoneSort($sha_parms);

                    $sha_string = '';
                    foreach ($sha_parms as $key => $value) {
                            if ($key != 'SHASIGN' && $value != '') {
                                    $sha_string .= $key . '=' . $value . $sha_out;
                            }
                    }

                    //return($sha_string);
                    return strtoupper(sha1($sha_string));
            }              

            /**
            *
            *
            **/
            private function ogoneSort($array) {
                    $arrayToSort = array();
                    $origArray = array();
                    foreach ($array as $key => $value) {
                            $arrayToSort[strtolower($key)] = $value;
                            //stores the original value in an array
                            $origArray[strtolower($key)] = $key;
                    }

                    ksort($arrayToSort);

                    $sortedArray = array();
                    foreach($arrayToSort as $key => $value) {
                            //switch the lowercase keys back to their originals
                            $key = strtoupper($origArray[$key]);
                            $sortedArray[$key] = $value;
                    }

                    return $sortedArray;
            }

Upvotes: 1

Related Questions