<?
require_once("../inc/config.php");
require_once("../inc/funcs.php");
require_once("../inc/money_config.php");
require_once("../inc/yandex/paycashlib.php");
require_once("../inc/yandex/sysunit.php");

/* CHECK IP HERE */
if($_SERVER["REMOTE_ADDR"]!=$YM["CashRegisterIP"]){
	@mail($SUPPORT_EMAIL,"Ошибка в YANDEX скрипте. IP неверен!", "IP ".$_SERVER["REMOTE_ADDR"],"From:".$SETTINGS['site_name']." System<$SUPPORT_EMAIL>");
	exit;
}



// signature status
$ssNoSignature   = 1;
$ssUnknown       = 2;
$ssError         = 3;
$ssInvalid       = 4;
$ssUnknownPeriod = 5;
$ssOutOfPeriod   = 6;
$ssValid         = 7;


// resource flags
define("rcfCompressed", 1);

// header of HTTP-request, within which Web Adapter sends the data from Cash Register
//to Shop's server scripts
// (in coded form) (default value: ahw_data)
define("EncryptedHTTPRequestParameter", "ahw_data");

// header of HTTP-reply, within which the Shop's server scripts send the data of reply
// to Cash Register via Web Adapter
// (in coded form)
define("EncryptedHTTPResponseParameter", "ahw_data");

// prefix of paid link user's parameters sent to server side via Web Adapter
// (precedes the name of user parameter to distinguish it from call parameter of //PrepareToPurchaseGoods function)(default value: user_)
define("UserParameterPrefix", "user_");

// UnpackerErrorField - header of HTTP-reply, in which an error code of function
// processing at server side is sent (default value: ahw_error)
define("UnpackerErrorField", "ahw_error");

$Packet = "";

//------------------------------------------------------------------------------
// sending error message text in reply header
function ReturnErrorResponse($ErrorMsg)
{
 header(UnpackerErrorField . ": $ErrorMsg");
 return false;
}

//------------------------------------------------------------------------------
//  $ResourceType = 1 - no resource, 2 - HTML-reply, 3 - HTTP-reply, 4 - URL
function CreateReplyResource($Message, $ResourceCachePeriod=0, $ResourceType=2)
{
 global $Packet;
 $Packet->SetParam("Out_ReplyResource_ResourceType", $ResourceType);
 $Packet->SetParam("Out_ReplyResource_ResourceCachePeriod", $ResourceCachePeriod);
 $Packet->SetParam("Out_ReplyResource_ResourceBody", $Message);
}

function SendReplyResource($Message, $ResourceCachePeriod=0, $ResourceType=2)
{
  CreateReplyResource($Message, $ResourceCachePeriod, $ResourceType);
  AHWDone();
}

//------------------------------------------------------------------------------
// returning value for parameter with a specified name
function AHWGetParam($Name)
{
   global $Packet;
   $val = @$Packet->GetParam($Name);
   if (!$val)
           return "";
   else
           return $val;
}

function AHWGetParamHex($Name)
{
   global $Packet;
   $val = @$Packet->GetParamHex($Name);
   if (!$val)
           return "";
   else
           return $val;
}

function AHWGetSumParam($Name, $CurrencyID)
{
   global $Packet;
   $val = @$Packet->GetSumParam($Name, $CurrencyID);
   if (!$val)
           return "";
   else
           return $val;
}

function AHWGetTimeParam($Name)
{
   global $Packet;
   $val = @$Packet->GetTimeParam($Name);
   if (!$val)
           return "";
   else
           return $val;
}

//------------------------------------------------------------------------------
// saving parameter name and its value
function AHWSetParam($Name, $Value)
{
   global $Packet;
   $Packet->SetParam($Name, $Value);
}

//------------------------------------------------------------------------------
// returning a textual description of unpacker's error
function AHWGetPacketErrorStr($Value)
{
   switch ($Value)
   {
      case 0:
        return "no errors";
        break;
      case 1:
        return "an exception have occurred";
        break;
      case 2:
        return "incorrect HEX line value for conversion";
        break;
      case 3:
        return "unknown key type";
        break;
      case 4:
        return "unknown type of packing in package";
        break;
      case 5:
        return "unknown type of compression in package";
        break;
      case 6:
        return "impossible to read the received data";
        break;
      case 7:
        return "the received package structure is ruined (it might be an unknown type of key)";
        break;
      case 8:
        return "key is not found";
        break;
      case 9:
        return "object already has the encoding key, which you are about to deliver to the object";
        break;
      case 10:
        return "incorrect key line";
        break;
      case 11:
        return "forbidden key identifier";
        break;
      case 12:
        return "key identifier format error";
        break;
      case 13:
        return "incorrect reply";
        break;
      case 14:
        return "incorrect request";
        break;
   }
}

//------------------------------------------------------------------------------
// forming an incoming package
function AHWDone()
{
   global $Packet;

   $data = $Packet->GetPacket(false);

   if ($Packet->ErrorCode())
     return ReturnErrorResponse("PayCashLib.Packet.GetPacket failed: " . AHWGetPacketErrorStr($Packet->ErrorCode()));

//   Header(EncryptedHTTPResponseParameter . ": " . $data);
   print($data);

   return true;
}


//------------------------------------------------------------------------------
// initializing
function AHWInit($EncryptionKey)
{
   global $Packet;
   global $YM;

   // having an IP-address, from which the money request came, we are checking if it      //is an allowed address?
   if ($YM["CashRegisterIP"])
   {
     $IPs = explode(";", $YM["CashRegisterIP"]);
     $AllowedIP = false;
     foreach($IPs as $value)
      if ($_SERVER["REMOTE_ADDR"] == $value)
      {
        $AllowedIP = true;
        break;
      };

     if (!$AllowedIP)
      return ReturnErrorResponse("IP-address '{$_SERVER['REMOTE_ADDR']}' is not allowed");
   }

   $Packet = @new Crypto();

   if (!$Packet)
     return ReturnErrorResponse("Unable to create COM object 'PayCashLib.Packet'");

   $Packet->SetKey($EncryptionKey);
   if ($Packet->ErrorCode())
     return ReturnErrorResponse("PayCashLib.Packet.SetKey failed: " . AHWGetPacketErrorStr($Packet->ErrorCode()));

   $Packet->SetDateTimeType($YM["dbtype"]);
   $Packet->SetDecSeparator(".");

   $Packet->SetPacket($_REQUEST[EncryptedHTTPRequestParameter]);
   if ($Packet->ErrorCode())
     return ReturnErrorResponse("PayCashLib.Packet.SetPacket failed: " . AHWGetPacketErrorStr($Packet->ErrorCode()));

   if ($Packet->GetParam("IN_TEST_CONNECTION"))
   {
     $Packet->SetParam("TestPassed", "OK");
     foreach($_SERVER as $Key=>$Value)
       $Packet->SetParam($Key, $Value);
     AHWDone();
     exit;
   }

   return true;
}

// currency codes and their shifts
$CurrencyTable = array(
// demo currencies
  array("10643", 1, "*rub" ), // toy ruble
  array("10840", 2, "*usd" ), // toy dollar
  array("10392", 0, "*jpy" ), // toy yen
  array("10380",-1, "*itl" ), // toy lira
  array("10980", 1, "*uah" ), // toy hryvnia
  array("10428", 2, "*lvl" ), // toy lat

// real currencies
  array("124",   2, "CAD" ),  // Canadian dollar
  array("233",   1, "EEK" ),  // Estonian kroon
  array("978",   2, "EUR" ),  // Euro
  array("250",   1, "FRF" ),  // French franc
  array("280",   2, "DEM" ),  // German mark
  array("826",   2, "GBP" ),  // British pound
  array("380",  -1, "ITL" ),  // Italian lira
  array("392",   0, "JPY" ),  // Japanese yen
  array("428",   2, "LVL" ),  // Latvian lat
  array("440",   1, "LTL" ),  // Lithuanian lita
  array("643",   1, "RUB" ),  // Russian ruble
  array("702",   2, "SGD" ),  // Singapore dollar
  array("724",   0, "ESP" ),  // Spanish peseta
  array("756",   2, "CHF" ),  // Swiss franc
  array("980",   1, "UAH" ),  // Ukraine hryvnia
  array("840",   2, "USD" )); // US dollar

//------------------------------------------------------------------------------
function SumToPreciseSum($Sum, $CurrencyCode)
{
  global $CurrencyTable;

  $Shift      = 0;
  $ShiftFound = false;
  // finding currency shift
  for ($i = 0; $i < count($CurrencyTable); $i++)
  {
     if ($CurrencyCode == $CurrencyTable[$i][0])
     {
        $Shift = 4 + $CurrencyTable[$i][1];
        $ShiftFound = true;
        break;
     }
  }

  $Sum = str_replace(",", ".", $Sum);
  $SumParts = explode(".", $Sum);

  $RemainderStr = (isset($SumParts[1])) ? $SumParts[1] : "";
  $RemainderStr = substr($RemainderStr . str_repeat("0", 10), 0, $Shift);

  return (ltrim($SumParts[0], "0") . $RemainderStr);
}

//------------------------------------------------------------------------------
function GetCurrencyOption($Sum, $CurrencyCode)
{
 return $CurrencyCode . "," . SumToPreciseSum($Sum, $CurrencyCode);
}

/*
  function HexToNumericStr($Value)
  {
      $Result = 0;

      $j = 0;
      for ($i = 0; $i < (strlen($Value)); $i += 2)
      {
          $Result += (int) hexdec($Value{$i} . $Value{$i + 1}) << (8 * $j);
          $j++;
      }

      return sprintf("%u", $Result);
  }
*/
function CharArrayToNumber($value)
{
  $Result = 0;
  $j = 0;

  for ($i = 0; $i < (strlen($value)); $i++)
  {
    $Result += (int) ord($value[$i]) << (8 * $j);
    $j++;
  }

  return sprintf("%u", $Result);
}



// Заглушки для функций магазина

// Описание структуры пакета см. в файле Docs/WebAdapterAPI.htm

  $unpackedRequest = base64_decode($_REQUEST[EncryptedHTTPRequestParameter]);
  $Version = CharArrayToNumber(substr($unpackedRequest, 0, 4));
  $UserID = CharArrayToNumber(substr($unpackedRequest, 4, 4));
  $EncryptionKey = GetUserParam($UserID, "EncryptionKey");
  AHWInit($EncryptionKey);

  $tmp_str="";
  foreach ($Packet->decoded_params as $key => $value) {
   $tmp_str.="Key: $key;    Value: $value\n";
  }

//  mail("support@ExChanger.ru",$order_id,$_SERVER["REMOTE_ADDR"]);	

  switch (AHWGetParam("FunctionName"))
  {
    case "PrepareToPurchaseGoods":
	  $order_id = $Packet->getParam("user_shop_order_id")+0;
	  $req_mode = 1;
	  if(!is_numeric($order_id)){
		$req_mode = 4;
	  }
	  else{
		  $query = "select orders.*, yandex_orders.payee_account,yandex_orders.paymentcurrency from orders inner join yandex_orders on orders.from_order_id = yandex_orders.id where orders.status=1 and yandex_orders.type=0 and yandex_orders.status=1 and orders.from_status=1 and yandex_orders.id=$order_id";

		  $row = @mysql_fetch_object(@mysql_query($query));

		  if($row->id!=""){
			$req_mode = 1;
		  }
		  else{
			$req_mode = 4;
		  }
	  }
      AHWSetParam("Out_RequestMode", $req_mode); // 1 - Request, 2 - contract is paid yet, 3 - money should not be requested, 4 - Shop error
      AHWSetParam("Out_ContractData_ContractSigner", AHWGetParam("IN_CYPHER"));
      AHWSetParam("Out_ContractData_MoneyDestination_AccountNumber", $row->payee_account);
      AHWSetParam("Out_ContractData_CurrencyOptions", GetCurrencyOption($row->amount_from, $row->paymentcurrency));
      AHWSetParam("Out_ContractData_PayeeRegData", $order_id);
	  AHWSetParam("Out_ContractData_ShortDescription", "Заказ # ".$order_id);
      AHWSetParam("Out_ContractData_ContractTerms", "Оплата для завершения операции обмена # ".$row->id." в системе ".$SETTINGS['site_name']);
      AHWSetParam("Out_ContractData_PaymentDelay", "600");
      AHWSetParam("Out_ContractData_ProcessingOptions", "0");
	  break;

    case "ApprovePurchase":
      AHWSetParam("Out_ConfirmAction", 0);
      if (AHWGetParam("IN_ERRORCODE") != 0)
        return SendReplyResource($SITE_URL."/fail.php", 0, 4);
      break;

    case "AcknowledgePayment":
      $ErrorCode = AHWGetParam("IN_PAYMENTAUTHORIZATIONINFO_ERRORCODE");
      if ($ErrorCode != 1)
        return SendReplyResource(GetCashRegisterError($fnAcknowledgePayment, $ErrorCode));
	  
	  $order_id = AHWGetParam("IN_PAYMENTAUTHORIZATIONINFO_PAYEEREGDATA")+0;
	  
	  if(!is_numeric($order_id)){
		  return SendReplyResource($SITE_URL."/fail.php",0, 4);
	  }

	  $query = "select orders.*, yandex_orders.payee_account,yandex_orders.paymentcurrency from orders inner join yandex_orders on orders.from_order_id = yandex_orders.id where orders.status=1 and yandex_orders.type=0 and yandex_orders.status=1 and orders.from_status=1 and yandex_orders.id=$order_id and orders.to_status=1";

	  $row = @mysql_fetch_object(@mysql_query($query));

	  if($row->id==""){
		  return SendReplyResource($SITE_URL."/fail.php", 0, 4);
	  }
	  
	  @mysql_query("update yandex_orders set payer_account_id='".AHWGetParam("IN_PAYMENTAUTHORIZATIONINFO_PAYERACCOUNT_ACCOUNTID")."',  payer_account='".AHWGetParam("IN_PAYMENTAUTHORIZATIONINFO_PAYERACCOUNT_ACCOUNTNUMBER")."',  payer_bank='".AHWGetParam("IN_PAYMENTAUTHORIZATIONINFO_PAYERACCOUNT_BANKID")."',  payee_account_id='".AHWGetParam("IN_PAYMENTAUTHORIZATIONINFO_MONEYDESTINATION_ACCOUNTID")."',  payee_account='".AHWGetParam("IN_PAYMENTAUTHORIZATIONINFO_MONEYDESTINATION_ACCOUNTNUMBER")."',  payee_bank='".AHWGetParam("IN_PAYMENTAUTHORIZATIONINFO_MONEYDESTINATION_BANKID")."',  paymentid='', contractdatetime ='".AHWGetParam("IN_PAYMENTAUTHORIZATIONINFO_CONTRACTDATETIME")."', authorizationtime ='".AHWGetParam("IN_PAYMENTAUTHORIZATIONINFO_AUTHORIZATIONTIME")."', status=0 where id=$order_id and type=0");

	  
	  @mysql_query("update orders set from_status = 0 where id = $row->id");

	  /* tranfering money */

	  /* changing balance */
	  $comments = "Зачисление средств из ".AHWGetParam("IN_PAYMENTAUTHORIZATIONINFO_PAYERACCOUNT_ACCOUNTNUMBER")." в систему. Операция обмена # $row->id.";
	  ChangeBalance($row->ex_currency_from_id,$row->amount_from-$row->ex_currency_from_comission,$comments);

      CompleteExchange($row->id);		

	  AHWSetParam("OUT_REPLYRESOURCE_RESOURCETYPE", "4"); // 1- No resource; 2 - HTML; 3-HTTP; URL-4;
      AHWSetParam("OUT_REPLYRESOURCE_RESOURCEBODY", $SITE_URL."/success.php");
      AHWSetParam("OUT_REPLYRESOURCE_RESOURCECACHEPERIOD", 2);

	  break;
  }

  AHWDone();
?>