First solution than I found, also some PayPal support guy has mentioned something similar but he could not offer details as he said he is not an expert.
Basically you have to run a TRANSACTION of type INQUIRY with the received PNREF from SILENT POST, if the response returns ORIGRESULT equal to 0 then the transaction exists in PayPal database under your account.
I also send the SECURE TOKEN ID and SECURE TOKEN with the inquiry, I do not know if it helps or not, I saw this as a solution somewhere and I tried sending just TOKEN and TOKEN ID without ORIGID and sometimes it worked sometimes not.
On the developer reference from PayPal is specified that on a TRXTYPE=I (INQUIRY TRANSACTION) the ORIGID must be specified.
Code below:
//GET POST DATA FROM SILENT POST
$data = $_POST;
$result = $data['RESULT'];
$pnref = $data['PNREF'];
$secure_token = $data['SECURETOKEN'];
$secure_token_id = $data['SECURETOKENID'];
$fee_amount = $data['AMT'];
if(!isset($result) || $result != '0'){
//DO TRANSACTION FAILED OPERATIONS
exit;
}
//CHECK IF PNREF ID EXISTS ON PAYPAL
$post_data = "PARTNER=yourpartnerid"
."&VENDOR=your_vendor"
."&USER=your_user"
."&PWD=your_password"
."&SECURETOKENID=" . $secure_token_id
."&SECURETOKEN=" . $secure_token
."&ORIGID=" . $pnref
."&TRXTYPE=I"
."&VERBOSITY=HIGH";
$ch = curl_init('https://payflowpro.paypal.com');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
$resp = curl_exec($ch);
$inquiry = array();
parse_str($resp, $inquiry);
//IF ORIGRESULT is 0 then PNREF/transaction exists.
if($inquiry['ORIGRESULT'] == '0' && $inquiry['RESPMSG'] == 'Approved'){ $validated = true; }
else{ $validated = false; }
if($result != 0 || $amount != 'your_correct_fee' || $validated == false){
// DO TRANSACTION NOT VALID OR HAS FAILED OPERATIONS
exit;
}
//DO TRANSACTION SUCCESSFULL OPERATIONS
The response from a INQUIRY looks this way:
RESULT=0&PNREF=ETHPC0BBF5FB&TRANSSTATE=8&ORIGRESULT=0&ORIGPNREF=ELFPB0E766F5&RESPMSG=Approved&AVSADDR=N&AVSZIP=N&ORIGPPREF=8GT035513B296200N&CORRELATIONID=97306f6456378&SETTLE_DATE=2014-07-09 14:11:36&TRANSTIME=2014-07-09 14:11:36&FIRSTNAME=John&LASTNAME=doe&AMT=0.0
Another way of doing it is checking the IP from which the SILENT POST is coming.
I noticed all SILENT POST data comes from 173.0.81.65
$ip_address = $_SERVER['REMOTE_ADDR'];
if($ip_address != '173.0.81.65'){ exit; }
@Andrew Angel
SILENT POST and NotifyURL is not the same thing.
From the NotifyURL you can use IPN and data verification it is done very differently there because you receive different kind of post data string back.
I talked with PayPal support and they said NotifyURL and IPN is not available for PayPal Advanced Payments only for PayPal Payments Pro.
Indeed they both do the same function, but they are different things and source validation is done differently.
Hope this helps someone, waiting on opinions.