Not receive response from paypal on success - php

I have integrate paypal with my Laravel application. I'm able to make payment successfully from Paypal, but after successful payment I'm not able to receive any type of response in my site.
My code is as below:
public function aCoolFunction(CreateDistrictRequest $request)
{
$data = $request->only('city_id', 'name', 'latitude', 'longitude');
$district = $this->districtRepository->create($data);
$payment = 'sandbox';
$values = [
'charest' => 'utf-8',
'lc' => 'US',
'cmd' => '_xclick',
'amount' => $product->price, // PRICE
'business' => 'test-facilitator#gmail.com', // PAYPAL EMAIL
'item_name' => $product->name, // NAME
'item_number' => $product->id, // ITEM ID
'currency_code' => 'USD',
'no_note' => '0',
'tax_rate' => 0, // 0- TO NOT ADD ANY FEES
'no_shipping' => 1, // NO ADDRESS
'rm' => '1',
'page_style' => 'paypal',
'custom' => '1', // ANY VALUES TO RETURN IT AFTER PAYMENT SUCCESS
'return' => url('payment-status'), // RETURN - MUST BE A VALID URL
'cancel_return' => url('payment-cancel'),
'notify_url' => url('payment-ipn') // IPN PAYPAL - CHECK IF IS PAID
];
$pay_url = "https://www.paypal.com/cgi-bin/webscr";
// CREATE $payment TO CHECK IF IS SANDBOX or LIVE - FROM CONFIG FILE FOR EXAMPLE
if ($payment == 'sandbox') :
$pay_url = "https://www.sandbox.paypal.com/cgi-bin/webscr";
endif;
return view('paypalpayment', ['pay_url' => $pay_url, 'values' => $values]);
}
public function paymentInfo(Request $request)
{
$myfile = fopen("paypalog.txt", "w") or die('Cannot open file: ' . $my_file);
$data = 'Transaction id = ' . $request;
fwrite($myfile, $data);
if ($request->tx)
{
if ($payment = Payment::where('transaction_id', $request->tx)->first())
{
$payment_id = $payment->id;
}
else
{
$payment = new Payment;
$payment->item_number = $request->item_number;
$payment->transaction_id = $request->tx;
$payment->currency_code = $request->cc;
$payment->payment_status = $request->st;
$payment->save();
$payment_id = $payment->id;
}
return 'Pyament has been done and your payment id is : ' . $payment_id;
}
else
{
return 'Payment has failed';
}
}
public function payment_success(Request $req)
{
$myfile = fopen("paypalog1.txt", "w") or die('Cannot open file: ' . $my_file);
$data = 'Transaction id = ' . $request->tx;
fwrite($myfile, $data);
}
from above code paymentinfo() is call in success or failure of payment from paypal. but here I'am not able to get any type of response from Paypal regarding payment.
This are my routes
Route::get('payment-status',array('as'=>'payment.status','uses'=>'PaymentController#paymentInfo'));
Route::get('payment',array('as'=>'payment','uses'=>'PaymentController#payment'));
Route::get('payment-cancel', function () {
return 'Payment has been canceled';
});
Route::get('payment-success' , 'PaymentController#payment_success');
Can anyone help me to solve this issue?

While dealing with PayPal you have to implement the IPN (Instant payment Notification) to get the status of the payment whether it is successful or failed.
For that you have to activate the IPN under the setting in your PayPal account and provide an url of your system to receive the IPN data, and that url must be of post type.
If I am not wrong, you have created this url for the same:
Route::get('payment-success' , 'PaymentController#payment_success');
but the issue is, it is of get type, so change it to 'post' and try again. If this url is not for the same purpose then create a url for the same.
P.S.: for testing purpose, PayPal provides an IPN simulator to test the same process, use that one it will be very helpful.
IPN simulator reference

Related

Cant tell if IPN is working because its not writing to sqlDatabase

I cant tell if its working since theirs no log or way to see a error since the server handles it all and i'm very new to these languages. As far as I can tell paypal sandbox sends the ipn but im not sure what works after that all I know is it does not show up in the DataBase. I know the password and everything is configed correctly and the database is set up. Im also following this tutorial here if it helps https://www.evoluted.net/thinktank/web-development/paypal-php-integration
im just to mush of a noob to php to follow it correctly.
heres the script that sends and receives ipn
<?php
// For test payments we want to enable the sandbox mode. If you want to put live
// payments through then this setting needs changing to `false`.
$enableSandbox = true;
// Database settings. Change these for your database configuration.
$dbConfig = [
'host' => 'sql106.epizy.com',
'username' => 'hidden',
'password' => 'hidden',
'name' => 'epiz_23648301_rod'
];
// PayPal settings. Change these to your account details and the relevant URLs
// for your site.
$paypalConfig = [
'email' => 'hidden#gmail.com',
'return_url' => 'http://rod.rf.gd/payment-successful.php',
'cancel_url' => 'http://rod.rf.gd/payment-cancelled.php',
'notify_url' => 'http://rod.rf.gd/payments.php'
];
$paypalUrl = $enableSandbox ? 'https://www.sandbox.paypal.com/cgi-bin/webscr' : 'https://www.paypal.com/cgi-bin/webscr';
// Product being purchased.
$itemName = 'Token';
$itemAmount = 1;
// Include Functions
require 'functions.php';
// Check if paypal request or response
if (!isset($_POST["txn_id"]) && !isset($_POST["txn_type"])) {
// Grab the post data so that we can set up the query string for PayPal.
// Ideally we'd use a whitelist here to check nothing is being injected into
// our post data.
$data = [];
foreach ($_POST as $key => $value) {
$data[$key] = stripslashes($value);
}
// Set the PayPal account.
$data['business'] = $paypalConfig['email'];
// Set the PayPal return addresses.
$data['return'] = stripslashes($paypalConfig['return_url']);
$data['cancel_return'] = stripslashes($paypalConfig['cancel_url']);
$data['notify_url'] = stripslashes($paypalConfig['notify_url']);
// Set the details about the product being purchased, including the amount
// and currency so that these aren't overridden by the form data.
$data['item_name'] = $itemName;
$data['amount'] = $itemAmount;
$data['currency_code'] = 'USD';
// Add any custom fields for the query string.
//$data['custom'] = USERID;
// Build the query string from the data.
$queryString = http_build_query($data);
// Redirect to paypal IPN
header('location:' . $paypalUrl . '?' . $queryString);
exit();
} else {
// Handle the PayPal response.
// Create a connection to the database.
$db = new mysqli($dbConfig['host'], $dbConfig['username'], $dbConfig['password'], $dbConfig['name']);
// Assign posted variables to local data array.
$data = [
'item_name' => $_POST['item_name'],
'item_number' => $_POST['item_number'],
'payment_status' => $_POST['payment_status'],
'payment_amount' => $_POST['mc_gross'],
'payment_currency' => $_POST['mc_currency'],
'txn_id' => $_POST['txn_id'],
'receiver_email' => $_POST['receiver_email'],
'payer_email' => $_POST['payer_email'],
'custom' => $_POST['custom'],
];
// We need to verify the transaction comes from PayPal and check we've not
// already processed the transaction before adding the payment to our
// database.
if (verifyTransaction($_POST) && checkTxnid($data['txn_id'])) {
if (addPayment($data) !== false) {
// Payment successfully added.
}
}
}
heres the addPayment func
function addPayment($data) {
global $db;
if (is_array($data)) {
$stmt = $db->prepare('INSERT INTO `payments` (txnid, payment_amount, payment_status, itemid, createdtime) VALUES(?, ?, ?, ?, ?)');
$stmt->bind_param(
'sdsss',
$data['txn_id'],
$data['payment_amount'],
$data['payment_status'],
$data['item_number'],
date('Y-m-d H:i:s')
);
$stmt->execute();
$stmt->close();
return $db->insert_id;
}
return false;
}

How can I receive form data in callback with post value in controller?

I'm trying verify online payment.
After I connect to bank getway by using function actionToken and pay, bank send me some information to verify payment with POST method, but I can't receive the information with POST method.
Here is my payment controller, function actionToken is for send data from my website such as amount ,and function actionVerify is for verifying payment that I have receive bank information. Here is my problem, that I don't know what do I have to do.
<?php
namespace frontend\controllers;
use Yii;
use common\models\Order;
class PaymentController extends \yii\web\Controller {
public function actionRequest() {
include_once('lib/nusoap.php');
$terminalId = "xxxx"; // Terminal ID
$userName = "xxxx"; // Username
$userPassword = "xxxxxxx"; // Password
$orderId = time(); // Order ID
$amount = $amount.'0'; // Price / Rial
$localDate = date('Ymd'); // Date
$localTime = date('Gis'); // Time
$additionalData = $model['notes'];
$callBackUrl = "http://dastsazkala.com/payment/verify?id=".$id; // Callback URL
$payerId = $id;
$parameters = [
'terminalId' => $terminalId,
'userName' => $userName,
'userPassword' => $userPassword,
'orderId' => $orderId,
'amount' => $amount,
'localDate' => $localDate,
'localTime' => $localTime,
'additionalData' => $additionalData,
'callBackUrl' => $callBackUrl,
'payerId' => $payerId];
$client = new \nusoap_client('https://bpm.shaparak.ir/pgwchannel/services/pgw?wsdl');
$namespace='http://interfaces.core.sw.bps.com/';
$result = $client->call('bpPayRequest', $parameters, $namespace);
}
public function actionVerify($id = null, $check = null) {
//my promblem is in this function, that I cant receive posts.
if ($_POST['ResCode'] == '0') {
//payment is correct
include_once('lib/nusoap.php');
$client = new nusoap_client('https://bpm.shaparak.ir/pgwchannel/services/pgw?wsdl');
$namespace='http://interfaces.core.sw.bps.com/';
$terminalId = "xxxx"; // Terminal ID
$userName = "xxxxx"; // Username
$userPassword = "xxxxx"; // Password
$orderId = $_POST['SaleOrderId']; // Order ID
$verifySaleOrderId = $_POST['SaleOrderId'];
$verifySaleReferenceId = $_POST['SaleReferenceId'];
$parameters = [
'terminalId' => $terminalId,
'userName' => $userName,
'userPassword' => $userPassword,
'orderId' => $orderId,
'saleOrderId' => $verifySaleOrderId,
'saleReferenceId' => $verifySaleReferenceId];
// Call the SOAP method
$result = $client->call('bpVerifyRequest', $parameters, $namespace);
if($result == 0) {
//verify is correct
echo 'The transaction was successful';
} else {
//error in pyament
}
} else {
//error in pyament
}
}
}
In this function I receive nothing.
Do I have to do something in behavior of my controller or something else?
Why I can't receive any posts in my controller?
General chrome:
Request URL: http://dastsazkala.com/payment/verify
Request Method: POST
Status Code: 301 Moved Permanently
Remote Address: 138.201.30.123:80
Referrer Policy: no-referrer-when-downgrade
Here what I receive:
The problem was this: my website url has www in the beginning, but there was no www in callBackUrl.
So I changed
$callBackUrl = "http://www.dastsazkala.com/payment/verify?id=".$id; //add www. in the beginning
instead of
$callBackUrl = "http://dastsazkala.com/payment/verify?id=".$id;
and I can receive Form Data with POST method from bank getway.
dastsazkala.com/payment/verify Redirects to www.dastsazkala.com/payment/verify notice the www!
the query result:
Status Code: 301 Moved Permanently
clearly hints that there might be a redirection going on

Event though my Braintree transaction is successful, there's no redirect to success page in Codeigniter

I'm struggling with a piece of code for more than a week.
I implemented Braintree, using the PHP SDK, in my Codeigniter app and I have this issue:
The user selects the product he wants, enters the shipping method then the Credit Card info;
The Credit Card is processed on the Braintree servers and returns a success or error flag;
If successful the order is added in the Database and a confirmation email is sent both to the merchant and the customer
Finally, the user is redirected to the success page or the error page if the transaction failed.
Everything works as expected in sandbox mode but when I go into production mode, the redirect fails, the page is redirected back to the order confirmation, even though the CC was charged and both emails sent.
Here is my controller:
function order_confirmation()
{
require_once('application/libraries/braintree/lib/Braintree.php');
Braintree_Configuration::environment('production');
Braintree_Configuration::merchantId('MY_MERCHANT_ID');
Braintree_Configuration::publicKey('MY_PUBLIC_KEY');
Braintree_Configuration::privateKey('MY_PRIVATE_KEY');
if ($this->input->post('checkout'))
{
$price = 24.99;
$quantity = 1;
if ($this->input->post('shipping') == 1)
$shipping_price = 0;
elseif ($this->input->post('shipping') == 2)
$shipping_price = 6.99;
$amount = $price * $quantity + $shipping_price;
//BrainTree payment process
$result = Braintree_Transaction::sale(array(
'amount' => $amount,
'creditCard' => array(
'number' => $this->input->post('credit_card_number'),
'expirationDate' => $this->input->post('expiration_month') . '/' . $this->input->post('expiration_year'),
'cvv' => $this->input->post('cvv')
),
'options' => [
'submitForSettlement' => True
]
));
if ($result->success)
{
// I left only the first and last name field to save up space
$first_name = $this->db->escape($this->session->userdata('first_name'));
$last_name = $this->db->escape($this->session->userdata('last_name'));
$date_created = $this->db->escape(time());
// Add the order
$this->shop_model->add_order($first_name, $last_name, $transaction_id, $date_created);
$order_id = $this->db->insert_id();
$product_id = $this->db->escape($this->input->post('product_id'));
// Add the order items
$this->shop_model->add_order_items($order_id, $product_id, $quantity, $price);
$data['site_name'] = $this->config->item('website_name');
$data['order'] = $this->shop_model->get_order($order_id);
$data['order_items'] = $this->shop_model->get_order_items($order_id);
$customer_email = $this->session->userdata('email');
// Send the email notification to the merchant
send_html_email('order_confirmation_merchant', $this->config->item('primary_email'), $this->config->item('website_name'), $this->config->item('primary_email'), 'shop', $data);
// Send the order confirmation to the customer
send_html_email('order_confirmation_customer', $this->config->item('primary_email'), $this->config->item('website_name'), $customer_email, 'shop', $data);
redirect(SHOP . '/checkout-success');
// header("Location: checkout-success");
// echo '<script language="JavaScript">document.location.href="' . base_url() . SHOP . '/checkout-success' . '"</script>' . "\n";
}
else
{
redirect(SHOP . '/checkout-error');
}
}
$this->template->set_template('no_sidebar');
$this->template->write('meta_description', 'Order confirmation');
$this->template->write('meta_keywords', 'Order confirmation');
$this->template->write('title', 'Order confirmation');
$this->template->write_view('header', 'frontend/header');
$this->template->write_view('section', 'frontend/shop/order_confirmation'/*, $data*/);
$this->template->write_view('footer', 'frontend/footer');
$this->template->render();
}
As you can see I tried serveral redirect methods (Codeigniter redirect(), native PHP, Javascript) with no success. As mentioned before, I do see the success page in sandbox mode and the error page if I enter a bogus CC, but no success page, only my order confirmation form, in production mode, even though the CC is charged, the order added in the database and the emails sent.
I would like to mention that the website has a SSL certificate and I tested using Mozilla Firefox, Google Chrome, Microsoft Edge. There are no JS errors, no PHP warnings.
Any answer would be greatly appreciated.
Thank you!

PayPal Adaptive Payments IMPLICIT Pay API

I am basically trying to use the PAY call of Adaptive Payments to programmatically and immediately send funds from my own paypal account to other accounts. According to the documentation, so long as I specify the senderEmail (my own paypal address, used to set up the Adaptive Payments), this should work verbatim.
However, when I make the call, I always get result "CREATED" instead of "COMPLETED". Created means the system still wants me to manually log into PayPal and approve the payments. I really need these payments to occur automatically on the spot. Any help would be appreciated.
Here is my request string:
currencyCode=USD&
returnUrl=http%3A%2F%2Fwww.website.com%2F&
actionType=PAY&
cancelUrl=http%3A%2F%2Fwww.website.com%2F&
receiverList.receiver%280%29.email=receiver%40gmail.com&
receiverList.receiver%280%29.amount=1.00&
requestEnvelope.senderEmail=me%40gmail.com&
clientDetails.deviceId=mydevice&
clientDetails.ipAddress=127.0.0.1&
clientDetails.applicationId=APP-ZZZZZZZZZZZZZ&
requestEnvelope.errorLanguage=en_US&
memo=memo&
feesPayer=EACHRECEIVER&
ipnNotificationUrl=http%3A%2F%2Fwww.website.com%2Fpay.php
And here is the response from PayPal:
[responseEnvelope.timestamp] => 2012-03-01T19:09:57.290-08:00
[responseEnvelope.ack] => Success
[responseEnvelope.correlationId] => 71efd416a2100
[responseEnvelope.build] => 2486531
[payKey] => AP-ZZZZZZZZZZZZZZZ
[paymentExecStatus] => CREATED
Forget everything I said earlier. The problem isn't an inconsistency between Sandbox and Live either, but rather a wrong parameter for 'senderEmail'.
Simply change:
requestEnvelope.senderEmail=me#gmail.com&
To:
senderEmail=me#gmail.com&
For example, the following returns a 'COMPLETED' implicit payment.
<?php
function AdaptiveCall($bodyparams, $method, $payKey) {
try
{
$body_data = http_build_query($bodyparams, "", chr(38));
$url = trim("https://svcs.sandbox.paypal.com/AdaptivePayments/".$method."");
$params = array("http" => array(
"method" => "POST",
"content" => $body_data,
"header" => "X-PAYPAL-SECURITY-USERID: xxxxxxxxx\r\n" .
"X-PAYPAL-SECURITY-SIGNATURE: xxxxxxxxxxx\r\n" .
"X-PAYPAL-SECURITY-PASSWORD: xxxxxxx\r\n" .
"X-PAYPAL-APPLICATION-ID: APP-80W284485P519543T\r\n" .
"X-PAYPAL-REQUEST-DATA-FORMAT: NV\r\n" .
"X-PAYPAL-RESPONSE-DATA-FORMAT: NV\r\n"
)
);
//create stream context
$ctx = stream_context_create($params);
//open the stream and send request
$fp = #fopen($url, "r", false, $ctx);
//get response
$response = stream_get_contents($fp);
//check to see if stream is open
if ($response === false) {
throw new Exception("php error message = " . "$php_errormsg");
}
//close the stream
fclose($fp);
//parse the ap key from the response
$keyArray = explode("&", $response);
foreach ($keyArray as $rVal){
list($qKey, $qVal) = explode ("=", $rVal);
$kArray[$qKey] = $qVal;
}
//print the response to screen for testing purposes
If ( $kArray["responseEnvelope.ack"] == "Success") {
echo "<strong>".$method ."</strong><br>";
foreach ($kArray as $key =>$value){
echo $key . ": " .$value . "<br/>";
}
// Return payKey
global $payKey;
if(!empty($kArray['payKey'])) { $payKey = $kArray['payKey']; return($payKey); }
}
else {
echo 'ERROR Code: ' . $kArray["error(0).errorId"] . " <br/>";
echo 'ERROR Message: ' . urldecode($kArray["error(0).message"]) . " <br/>";
}
}
catch(Exception $e) {
echo "Message: ||" .$e->getMessage()."||";
}
}
//Create Pay body
$bodyparams = array ( "requestEnvelope.errorLanguage" => "en_US",
'actionType' => 'PAY',
'currencyCode' => 'USD',
'receiverList.receiver(0).email' => 'another_account#domain.tld',
'receiverList.receiver(0).amount' => '1.00',
'senderEmail' => 'xxxxxxxxx',
'memo' => 'Test memo',
'ipnNotificationUrl' => 'http://xxxxxxxx',
'cancelUrl' => 'http://xxxxxxxxx',
'returnUrl' => 'http://xxxxxxxxxx'
);
// Call Pay API
AdaptiveCall($bodyparams, "Pay");
?>
Pay response:
responseEnvelope.timestamp: 2012-03-03T09%3A10%3A22.900-08%3A00
responseEnvelope.ack: Success
responseEnvelope.correlationId: 4bc5cfc4a7514
responseEnvelope.build: 2486531
payKey: AP-1XJ7636763429720C
paymentExecStatus: COMPLETED

Paypal IPN Issue with parallel payment

I'm using this http://www.binpress.com/app/paypal-adaptive-payments-pro-codeigniter-library/140 library and i'm using this as my ipn listener for a codeigniter project - http://pastebin.com/pMb7Zhz3.
Basically i'm doing a parallel transaction using the paypal library above so that when a user makes a payment/donation, it sends money to 2 different accounts. Once a transaction is complete, paypal sends data to my ipn listener and it parses info for 1 customer just fine if I leave this 'IPNNotificationURL' => '' in my code and go into paypal and set the ipn url.
I'm trying to get IPN information for both accounts, without having to have both accounts set the ipn url in their paypal settings. When I set 'IPNNotificationURL' => 'http://example.com/paypal_ipn', I still get the ipn information for the 1 account, but I get this warning Array to string conversion on line 11 of my listener. How can I fix this and if i do, will I get the ipn information from both accounts?
Here's the pay method from the library above that i'm using for the parallel payments
function Pay()
{
// Prepare request arrays
$PayRequestFields = array(
'ActionType' => 'PAY', // Required. Whether the request pays the receiver or whether the request is set up to create a payment request, but not fulfill the payment until the ExecutePayment is called. Values are: PAY, CREATE, PAY_PRIMARY
'CancelURL' => '', // Required. The URL to which the sender's browser is redirected if the sender cancels the approval for the payment after logging in to paypal.com. 1024 char max.
'CurrencyCode' => 'USD', // Required. 3 character currency code.
'FeesPayer' => 'SENDER', // The payer of the fees. Values are: SENDER, PRIMARYRECEIVER, EACHRECEIVER, SECONDARYONLY
'IPNNotificationURL' => '', // The URL to which you want all IPN messages for this payment to be sent. 1024 char max.
'Memo' => '', // A note associated with the payment (text, not HTML). 1000 char max
'Pin' => '', // The sener's personal id number, which was specified when the sender signed up for the preapproval
'PreapprovalKey' => '', // The key associated with a preapproval for this payment. The preapproval is required if this is a preapproved payment.
'ReturnURL' => '', // Required. The URL to which the sener's browser is redirected after approvaing a payment on paypal.com. 1024 char max.
'ReverseAllParallelPaymentsOnError' => '', // Whether to reverse paralel payments if an error occurs with a payment. Values are: TRUE, FALSE
'SenderEmail' => '', // Sender's email address. 127 char max.
'TrackingID' => '' // Unique ID that you specify to track the payment. 127 char max.
);
$ClientDetailsFields = array(
'CustomerID' => '', // Your ID for the sender 127 char max.
'CustomerType' => '', // Your ID of the type of customer. 127 char max.
'GeoLocation' => '', // Sender's geographic location
'Model' => '', // A sub-identification of the application. 127 char max.
'PartnerName' => '' // Your organization's name or ID
);
$FundingTypes = array('ECHECK', 'BALANCE', 'CREDITCARD');
$Receivers = array();
$Receiver = array(
'Amount' => '', // Required. Amount to be paid to the receiver.
'Email' => '', // Receiver's email address. 127 char max.
'InvoiceID' => '', // The invoice number for the payment. 127 char max.
'PaymentType' => '', // Transaction type. Values are: GOODS, SERVICE, PERSONAL, CASHADVANCE, DIGITALGOODS
'PaymentSubType' => '', // The transaction subtype for the payment.
'Phone' => array('CountryCode' => '', 'PhoneNumber' => '', 'Extension' => ''), // Receiver's phone number. Numbers only.
'Primary' => '' // Whether this receiver is the primary receiver. Values are: TRUE, FALSE
);
array_push($Receivers,$Receiver);
$SenderIdentifierFields = array(
'UseCredentials' => '' // If TRUE, use credentials to identify the sender. Default is false.
);
$AccountIdentifierFields = array(
'Email' => '', // Sender's email address. 127 char max.
'Phone' => array('CountryCode' => '', 'PhoneNumber' => '', 'Extension' => '') // Sender's phone number. Numbers only.
);
$PayPalRequestData = array(
'PayRequestFields' => $PayRequestFields,
'ClientDetailsFields' => $ClientDetailsFields,
'FundingTypes' => $FundingTypes,
'Receivers' => $Receivers,
'SenderIdentifierFields' => $SenderIdentifierFields,
'AccountIdentifierFields' => $AccountIdentifierFields
);
$PayPalResult = $this->paypal_adaptive->Pay($PayPalRequestData);
if(!$this->paypal_adaptive->APICallSuccessful($PayPalResult['Ack']))
{
$errors = array('Errors'=>$PayPalResult['Errors']);
$this->load->view('paypal_error',$errors);
}
else
{
$data['result'] = $PayPalResult;
$this->load->view('success', $data);
}
}
and line 11 is this from the pastebin above - $value = urlencode(stripslashes($value));
I figured out how to parse the adaptive payments IPN in PHP.
I used the DecodePayPalIPN() function by donut2d https://www.x.com/developers/paypal/forums/adaptive-payments-api/php-technique-parsing-adaptive-payment-ipn-posts?page=0%2C0%2C0%2C0%2C0%2C0%2C0%2C0%2C0%2C0%2C0%2C0%2C0%2C0%2C0%2C1 in combination with one of the example listeners that is on the paypal website and here is my complete Codeigniter IPN Listener for adaptive payments with a parallel transaction.
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Paypal_ipn extends CI_Controller {
public function index() {
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate&'.file_get_contents("php://input");
$header = null;
// post back to PayPal system to validate
$header .= "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
$fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
$raw_post = file_get_contents("php://input");
$post_array = $this->decodePayPalIPN($raw_post);
//log_message('error', "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
//$log1 = var_export($post_array, true);
//log_message('error', $log1);
//log_message('error', "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
if(isset($post_array['sender_email'])) {
$sender_email = $post_array['sender_email'];
}
if(isset($post_array['status'])) {
$status = $post_array['status'];
}
if(isset($post_array['payment_request_date'])) {
$payment_request_date = $post_array['payment_request_date'];
}
if(isset($post_array['transaction'][0]['receiver'])) {
$receiver0 = $post_array['transaction'][0]['receiver'];
}
if(isset($post_array['transaction'][1]['receiver'])) {
$receiver1 = $post_array['transaction'][1]['receiver'];
}
if(isset($post_array['transaction'][0]['id'])) {
$id0 = $post_array['transaction'][0]['id'];
}
if(isset($post_array['transaction'][1]['id'])) {
$id1 = $post_array['transaction'][1]['id'];
}
if(isset($post_array['transaction'][0]['invoiceId'])) {
$invoiceId0 = $post_array['transaction'][0]['invoiceId'];
}
if(isset($post_array['transaction'][1]['invoiceId'])) {
$invoiceId1 = $post_array['transaction'][1]['invoiceId'];
}
if(isset($post_array['transaction'][0]['amount'])) {
$amount0 = $post_array['transaction'][0]['amount'];
}
if(isset($post_array['transaction'][1]['amount'])) {
$amount1 = $post_array['transaction'][1]['amount'];
}
if(isset($post_array['transaction'][0]['status'])) {
$status0 = $post_array['transaction'][0]['status'];
}
if(isset($post_array['transaction'][1]['status'])) {
$status1 = $post_array['transaction'][1]['status'];
}
if(isset($post_array['transaction'][0]['id_for_sender_txn'])) {
$id_for_sender_txn0 = $post_array['transaction'][0]['id_for_sender_txn'];
}
if(isset($post_array['transaction'][1]['id_for_sender_txn'])) {
$id_for_sender_txn1 = $post_array['transaction'][1]['id_for_sender_txn'];
}
if(isset($post_array['transaction'][0]['status_for_sender_txn'])) {
$status_for_sender_txn0 = $post_array['transaction'][0]['status_for_sender_txn'];
}
if(isset($post_array['transaction'][1]['status_for_sender_txn'])) {
$status_for_sender_txn1 = $post_array['transaction'][1]['status_for_sender_txn'];
}
if(isset($post_array['transaction'][1]['pending_reason'])) {
$pending_reason0 = $post_array['transaction'][1]['pending_reason'];
}
if(isset($post_array['transaction'][1]['pending_reason'])) {
$pending_reason1 = $post_array['transaction'][1]['pending_reason'];
}
if (!$fp) {
// HTTP ERROR
} else {
$counter = 0;
fputs ($fp, $header . $req);
while (!feof($fp)) {
$res = fgets ($fp, 1024);
if (strcmp ($res, "VERIFIED") == 0) {
log_message('error', "sender_email = $sender_email");
log_message('error', "payment_request_date = $payment_request_date");
log_message('error', "status = $status");
log_message('error', "receiver0 = $receiver0");
log_message('error', "receiver1 = $receiver1");
log_message('error', "id0 = $id0");
log_message('error', "id1 = $id1");
log_message('error', "invoiceId0 = $invoiceId0");
log_message('error', "invoiceId1 = $invoiceId1");
log_message('error', "amount0 = $amount0");
log_message('error', "amount1 = $amount1");
log_message('error', "status0 = $status0");
log_message('error', "status1 = $status1");
log_message('error', "id_for_sender_txn0 = $id_for_sender_txn0");
log_message('error', "id_for_sender_txn1 = $id_for_sender_txn1");
log_message('error', "status_for_sender_txn0 = $status_for_sender_txn0");
log_message('error', "status_for_sender_txn1 = $status_for_sender_txn1");
log_message('error', "pending_reason0 = $pending_reason0");
log_message('error', "pending_reason1 = $pending_reason1");
// check the payment_status is Completed
// check that txn_id has not been previously processed
// check that receiver_email is your Primary PayPal email
// check that payment_amount/payment_currency are correct
// process payment
$counter++;
}
else if (strcmp ($res, "INVALID") == 0) {
log_message('error', 'WE INVALIDDDDDDDDDDDDDDDDDD');
$test = var_export($res, true);
$test = str_replace(array("\r","\n"), '', $test);
log_message('error', $test);
log_message('error', "Problem with IPN. res = $test");
}
}
fclose ($fp);
}
}
function decodePayPalIPN($raw_post)
{
//log_message('error', "testing");
if (empty($raw_post)) {
return array();
} # else:
$post = array();
$pairs = explode('&', $raw_post);
foreach ($pairs as $pair) {
list($key, $value) = explode('=', $pair, 2);
$key = urldecode($key);
$value = urldecode($value);
# This is look for a key as simple as 'return_url' or as complex as 'somekey[x].property'
preg_match('/(\w+)(?:\[(\d+)\])?(?:\.(\w+))?/', $key, $key_parts);
switch (count($key_parts)) {
case 4:
# Original key format: somekey[x].property
# Converting to $post[somekey][x][property]
if (!isset($post[$key_parts[1]])) {
$post[$key_parts[1]] = array($key_parts[2] => array($key_parts[3] => $value));
} else if (!isset($post[$key_parts[1]][$key_parts[2]])) {
$post[$key_parts[1]][$key_parts[2]] = array($key_parts[3] => $value);
} else {
$post[$key_parts[1]][$key_parts[2]][$key_parts[3]] = $value;
}
break;
case 3:
# Original key format: somekey[x]
# Converting to $post[somkey][x]
if (!isset($post[$key_parts[1]])) {
$post[$key_parts[1]] = array();
}
$post[$key_parts[1]][$key_parts[2]] = $value;
break;
default:
# No special format
$post[$key] = $value;
break;
}#switch
}#foreach
return $post;
}#decodePayPalIPN()
}

Categories