I'm trying to make automatic payment system, where users can top up their accounts using PerfectMoney. Their site has SCI form generator, which generates this form:
<form action="https://perfectmoney.is/api/step1.asp" method="POST">
<input type="hidden" name="PAYEE_ACCOUNT" value="E1089920">
<input type="hidden" name="PAYEE_NAME" value="Test account">
<input type='hidden' name='PAYMENT_ID' value='<?=time() ?>'>
<input type="text" name="PAYMENT_AMOUNT" value=""><BR>
<input type="hidden" name="PAYMENT_UNITS" value="EUR">
<input type="hidden" name="STATUS_URL" value="http://dev.limited.rs/status.php">
<input type="hidden" name="PAYMENT_URL" value="http://dev.limited.rs/complete.php">
<input type="hidden" name="PAYMENT_URL_METHOD" value="POST">
<input type="hidden" name="NOPAYMENT_URL" value="http://dev.limited.rs/failed.php">
<input type="hidden" name="NOPAYMENT_URL_METHOD" value="POST">
<input type="hidden" name="SUGGESTED_MEMO" value="">
<input type="hidden" name="BAGGAGE_FIELDS" value="IDENT"><br>
<input type="submit" name="PAYMENT_METHOD" value="Pay Now!" class="tabeladugme"><br><br>
</form>
A regular form that sends data to PerfectMoney site. In turn, PerfectMoney will send data back to me via POST method two times, once when the payment is done, and once when user is redirected back to the site. When the payment is completed, I simply take all the data and store in the database, just so I can check it when users get back to the site, like this:
<?php
ob_start();
session_start();
require 'config.php';
if (!isset($_POST['PAYMENT_ID']) || !isset($_POST['PAYEE_ACCOUNT']) || !isset($_POST['PAYMENT_AMOUNT']) || !isset($_POST['PAYMENT_UNITS']) || !isset($_POST['PAYMENT_BATCH_NUM']) || !isset($_POST['PAYER_ACCOUNT']) || !isset($_POST['TIMESTAMPGMT']))
{
header("location:uploadfunds.php");
exit();
}
if (isset($_POST['PAYMENT_ID']) || isset($_POST['PAYEE_ACCOUNT']) || isset($_POST['PAYMENT_AMOUNT']) || isset($_POST['PAYMENT_UNITS']) || isset($_POST['PAYMENT_BATCH_NUM']) || isset($_POST['PAYER_ACCOUNT']) || isset($_POST['TIMESTAMPGMT']))
{
$sum=$_POST['PAYMENT_AMOUNT'];
$passphrase=strtoupper(md5("<passphrase here>"));
$hash=$_POST['PAYMENT_ID'].':'.$_POST['PAYEE_ACCOUNT'].':'.
$_POST['PAYMENT_AMOUNT'].':'.$_POST['PAYMENT_UNITS'].':'.
$_POST['PAYMENT_BATCH_NUM'].':'.
$_POST['PAYER_ACCOUNT'].':'.$passphrase.':'.
$_POST['TIMESTAMPGMT'];
$hash2=strtoupper(md5($hash));
$pending = "Pending";
$sqlcheck1 = "SELECT * FROM payments WHERE Hash = '$hash' AND Status = '$pending'";
$rescheck1 = mysql_query($sqlcheck1);
if (mysql_num_rows($rescheck1) != 0)
{
if($hash2==$_POST['V2_HASH'])
{
echo "Hash2 = V2_HASH";
$method = "Uploaded funds";
$completed = "Completed";
$today = date('Y-m-d');
$type = "Perfect Money";
$addfunds = "UPDATE balance SET Balance = Balance + '$sum' WHERE User = '$uploader'";
$addhistory = "INSERT INTO bank (User,Amount,Method,Transdate,Type,Status) VALUES ('$me','$sum','$method','$today','$type','$status')";
$updatepayment = "UPDATE payments SET Status = '$completed' WHERE Hash = '$hash' AND User = '$uploader'";
mysql_query($addfunds);
mysql_query($addhistory);
mysql_query($updatepayment);
header("bank.php");
exit();
}
if($hash2!=$_POST['V2_HASH'])
{
echo "hash2 != V2_HASH";
header("location:error.php?id=2");
exit();
}
}
?>
So I'm literally comparing the data I got 2 seconds before to the data I get now, it should match and it did. 10 days after I wrote the script, it starts failing, I'm getting error 500. No log ANYWHERE for me to figure what's going on, and from debugging the code, it all seems to work.
Right so I found the answer and even though it's shameful.. header("Location:bank.php");
instead of header("bank.php");
Yes, it took me a long time to find this. Life does that.