/**
  * Validates callback
  *
  * @param       PaymentTransaction      $paymentTransaction     Payment transaction
  * @param       CallbackResponse        $callbackResponse       Callback from PaynetEasy
  *
  * @throws      ValidationException                             Validation error
  */
 protected function validateCallback(PaymentTransaction $paymentTransaction, CallbackResponse $callbackResponse)
 {
     $this->validateQueryConfig($paymentTransaction);
     $this->validateSignature($paymentTransaction, $callbackResponse);
     if (!in_array($callbackResponse->getStatus(), static::$allowedStatuses)) {
         throw new ValidationException("Invalid callback status: '{$callbackResponse->getStatus()}'");
     }
     $errorMessage = '';
     $missedFields = array();
     $unequalValues = array();
     foreach (static::$callbackFieldsDefinition as $fieldDefinition) {
         list($fieldName, $propertyPath) = $fieldDefinition;
         if (empty($callbackResponse[$fieldName])) {
             $missedFields[] = $fieldName;
         } elseif ($propertyPath) {
             $propertyValue = PropertyAccessor::getValue($paymentTransaction, $propertyPath, false);
             $callbackValue = $callbackResponse[$fieldName];
             if ($propertyValue != $callbackValue) {
                 $unequalValues[] = "CallbackResponse field '{$fieldName}' value '{$callbackValue}' does not " . "equal PaymentTransaction property '{$propertyPath}' value '{$propertyValue}'";
             }
         }
     }
     if (!empty($missedFields)) {
         $errorMessage .= "Some required fields missed or empty in CallbackResponse: \n" . implode(', ', $missedFields) . ".\n";
     }
     if (!empty($unequalValues)) {
         $errorMessage .= "Some fields from CallbackResponse unequal properties from PaymentTransaction: \n" . implode("\n", $unequalValues) . " \n";
     }
     if (!empty($errorMessage)) {
         throw new ValidationException($errorMessage);
     }
 }
 /**
  * Generates the control code is used to ensure that it is a particular
  * Merchant (and not a fraudster) that initiates the transaction.
  *
  * @param       PaymentTransaction      $paymentTransaction     Payment transaction to generate control code
  *
  * @return      string                                          Generated control code
  */
 protected function createSignature(PaymentTransaction $paymentTransaction)
 {
     $controlCode = '';
     foreach (static::$signatureDefinition as $propertyPath) {
         $controlCode .= PropertyAccessor::getValue($paymentTransaction, $propertyPath);
     }
     return sha1($controlCode);
 }