I work with an e-commerce website that uses a PayPal checkout component written in PHP. For accounting purposes I want to retrieve some additional information using the PayPal PHP SOAP API.
I found out how to access the transaction using the transaction id and the GetTransactionDetails object:
// snip - include PayPal libraries and set up APIProfile object -
$trans_details =& PayPal::getType('GetTransactionDetailsRequestType');
$tran_id = $_GET['transactionID'];
$trans_details->setTransactionId($tran_id, 'iso-8859-1');
$caller =& PayPal::getCallerServices($profile);
$response = $caller->GetTransactionDetails($trans_details);
$paymentTransDetails = $response->getPaymentTransactionDetails();
// snip - work with transaction details -
However, I need to enhance this so that I can find out the 12-character string transaction id first by using the invoice id which I have available in a local MySQL database (which is also referenced in the transaction on the PayPal website).
I guess that I have to use Transaction Search for that but I don't know how to do this with the PHP SOAP API. How can I retrieve the transaction id for an invoice id?
I dived into the API documentation and managed to find it out.
// snip - include PayPal libraries and set up APIProfile object (variable: profile) -
$trans_search =& PayPal::getType('TransactionSearchRequestType');
// 01/12/201 as an example date, we always need a start date for the API
$start_date_str = '01/12/2011';
$start_time = strtotime($start_date_str);
$iso_start = date('Y-m-d\T00:00:00\Z', $start_time);
$trans_search->setStartDate($iso_start, 'iso-8859-1');
$invoice_ID = '10942456'; // here we insert the invoice ID we know
$trans_search->setInvoiceID($invoice_ID);
$caller =& PayPal::getCallerServices($profile);
$response = $caller->TransactionSearch($trans_search); // execute search
$ptsr = $response->getPaymentTransactions();
$nrecs = sizeof($ptsr);
$ack = $response->getAck();
if( ($ack != ACK_SUCCESS)
&& ($ack != ACK_SUCCESS_WITH_WARNING) )
exit; // jump out on error
if($nrecs == 1){ // check whether we found only one transaction (as expected)
$paymentTransaction = $ptsr[0];
// we found our transaction ID
$transID = $paymentTransaction->getTransactionID();
}else{
// invoice ID not unique?! :-(
exit('Found multiple transactions: '. print_r($ptsr, true)); // jump out
}
// snip - work with transaction ID -
It's easy enough to use the TransactionSearch API to find a transaction by invoice number. All you need to do is send the INVNUM parameter along in the API call to PayPal.
For example (based on PayPal's TransactionSearch PHP sample code):
<?php
/** TransactionSearch NVP example; last modified 08MAY23.
*
* Search your account history for transactions that meet the criteria you specify.
*/
$environment = 'sandbox'; // or 'beta-sandbox' or 'live'
/**
* Send HTTP POST Request
*
* #param string The API method name
* #param string The POST Message fields in &name=value pair format
* #return array Parsed HTTP Response body
*/
function PPHttpPost($methodName_, $nvpStr_) {
global $environment;
// Set up your API credentials, PayPal end point, and API version.
$API_UserName = urlencode('xxxxxxxxxxxx');
$API_Password = urlencode('yyyyyyyyy');
$API_Signature = urlencode('zzzzzzzzzzzzzzzzzzzzzzz');
$API_Endpoint = "https://api-3t.paypal.com/nvp";
if("sandbox" === $environment || "beta-sandbox" === $environment) {
$API_Endpoint = "https://api-3t.$environment.paypal.com/nvp";
}
$version = urlencode('84.0');
// Set the curl parameters.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $API_Endpoint);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
// Turn off the server and peer verification (TrustManager Concept).
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
// Set the API operation, version, and API signature in the request.
$nvpreq = "METHOD=$methodName_&VERSION=$version&PWD=$API_Password&USER=$API_UserName&SIGNATURE=$API_Signature$nvpStr_";
// Set the request as a POST FIELD for curl.
curl_setopt($ch, CURLOPT_POSTFIELDS, $nvpreq);
// Get response from the server.
$httpResponse = curl_exec($ch);
if(!$httpResponse) {
exit("$methodName_ failed: ".curl_error($ch).'('.curl_errno($ch).')');
}
// Extract the response details.
$httpResponseAr = explode("&", $httpResponse);
$httpParsedResponseAr = array();
foreach ($httpResponseAr as $i => $value) {
$tmpAr = explode("=", $value);
if(sizeof($tmpAr) > 1) {
$httpParsedResponseAr[$tmpAr[0]] = $tmpAr[1];
}
}
if((0 == sizeof($httpParsedResponseAr)) || !array_key_exists('ACK', $httpParsedResponseAr)) {
exit("Invalid HTTP Response for POST request($nvpreq) to $API_Endpoint.");
}
return $httpParsedResponseAr;
}
Up to here it's all as usual. The only changes to the sample are here:
// Set request-specific fields.
//$transactionID = urlencode('example_transaction_id');
$invoice = urlencode('1234');
// Add request-specific fields to the request string.
//$nvpStr = "&TRANSACTIONID=$transactionID";
$nvpStr = "&INVNUM=$invoice";
Here, by setting a proper STARTDATE:
// Set additional request-specific fields and add them to the request string.
$startDateStr = "01/01/2010"; // in 'mm/dd/ccyy' format
$endDateStr; // in 'mm/dd/ccyy' format
if(isset($startDateStr)) {
$start_time = strtotime($startDateStr);
$iso_start = date('Y-m-d\T00:00:00\Z', $start_time);
$nvpStr .= "&STARTDATE=$iso_start";
}
if(isset($endDateStr)&&$endDateStr!='') {
$end_time = strtotime($endDateStr);
$iso_end = date('Y-m-d\T24:00:00\Z', $end_time);
$nvpStr .= "&ENDDATE=$iso_end";
}
// Execute the API operation; see the PPHttpPost function above.
$httpParsedResponseAr = PPHttpPost('TransactionSearch', $nvpStr);
And here, by adding a simple if statement to trigger whether or not to return the full TransactionSearch API result, or only return the PayPal transaction ID (bla.php?view=minimal):
if($_GET['view'] != "minimal") {
if("SUCCESS" == strtoupper($httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($httpParsedResponseAr["ACK"])) {
echo('TransactionSearch Completed Successfully: '.print_r($httpParsedResponseAr, true));
} else {
echo('TransactionSearch failed: ' . print_r($httpParsedResponseAr, true));
}
}
else {
// Output only the TransactionID
echo $httpParsedResponseAr['L_TRANSACTIONID0'];
}
?>
Related
I have successfully implement PayPal with laravel. I am able to make payment using PayPal APIs. Now I want to implement refund from PayPal using laravel. I don't want to make refund from PayPal dashboard but i want to make it done from our admin panel where admin user can see list of payments and link to refund that amount to customer. After successful payment I got Transaction id in response from PayPal. If i use that transaction id to refund then i am not able to do that successfully, and if i copy transaction id from paypal dashboard where all transactions are listed and get detail information of that transaction, then i am able to make refund success. Can anyone tell me how can i get that transaction id using which i can make refund using laravel.
I have to use below code to get actual sale id to refund amount using code not from paypal dashboard
$apiContext = new ApiContext(new OAuthTokenCredential(
"<CLIENT_ID>", "<CLIENT_SCRET_KEY>")
);
$payments = Payment::get($payment_id, $apiContext);
$payments->getTransactions();
$obj = $payments->toJSON();//I wanted to look into the object
$paypal_obj = json_decode($obj);//I wanted to look into the object
$transaction_id = $paypal_obj->transactions[0]->related_resources[0]->sale->id;
$this->getRefundPayment($transaction_id);
public function getRefundPayment($transaction_id){
$this->API_UserName = urlencode($this->API_Username);
$this->API_Password = urlencode($this->API_Password);
$this->API_Signature = urlencode($this->Signature);
$this->version = urlencode($this->version);
$transactionid = $transaction_id;
$DataInArray['currencyCode'] = 'INR';
$DataInArray['refundType'] = 'Full';
$DataInArray['transactionID'] = $transactionid;
$DataInArray['invoiceID'] = '';
$DataInArray['memo'] = 'This is refund of transaction id ='.$transactionid;
$DataInArray['amount'] = '';
if(trim(#$DataInArray['currencyCode'])=="")
return array("ERROR_MESSAGE"=>"Currency Code is Missing");
if(trim(#$DataInArray['refundType'])=="")
return array("ERROR_MESSAGE"=>"Refund Type is Missing");
if(trim(#$DataInArray['transactionID'])=="")
return array("ERROR_MESSAGE"=>"Transaction ID is Missing");
$Api_request = "&TRANSACTIONID={$DataInArray['transactionID']}&REFUNDTYPE={$DataInArray['refundType']}&CURRENCYCODE={$DataInArray['currencyCode']}";
if(trim(#$DataInArray['invoiceID'])!="")
$Api_request = "&INVOICEID={$DataInArray['invoiceID']}";
if(isset($DataInArray['memo']))
$Api_request .= "&NOTE={$DataInArray['memo']}";
if(strcasecmp($DataInArray['refundType'], 'Partial') == 0) {
if(!isset($DataInArray['amount'])) {
return array("ERROR_MESSAGE"=>"For Partial Refund - It is essential to mention Amount");
} else {
$Api_request = $Api_request."&AMT={$DataInArray['amount']}";
}
if(!isset($DataInArray['memo'])) {
return array("ERROR_MESSAGE"=>"For Partial Refund - It is essential to enter text for Memo");
}
}
$curl_var = curl_init();
curl_setopt($curl_var, CURLOPT_URL, $this->API_Endpoint);
curl_setopt($curl_var, CURLOPT_VERBOSE, 1);
curl_setopt($curl_var, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl_var, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($curl_var, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl_var, CURLOPT_POST, 1);
$Api_request_final = "METHOD=RefundTransaction&VERSION={$this->version}&PWD={$this->API_Password}&USER={$this->API_UserName}&SIGNATURE={$this->API_Signature}$Api_request";
curl_setopt($curl_var, CURLOPT_POSTFIELDS, $Api_request_final);
// Get response from the server.
$curlResponse = curl_exec($curl_var);
if(!$curlResponse)
return array("ERROR_MESSAGE"=>"RefundTransaction failed".curl_error($curl_var)."(".curl_errno($curl_var).")");
// Extract the response details.
$httpResponseAr = explode("&", $curlResponse);
$aryResponse = array();
foreach ($httpResponseAr as $i => $value) {
$tmpAr = explode("=", $value);
if(sizeof($tmpAr) > 1) {
$aryResponse[$tmpAr[0]] = urldecode($tmpAr[1]);
}
}
if((0 == sizeof($aryResponse)) || !array_key_exists('ACK', $aryResponse))
return array("ERROR_MESSAGE"=>"Invalid HTTP Response for POST request ($reqStr) to {$this->API_Endpoint}");
// var_dump($aryResponse);
return $aryResponse;
}
I am using Paypal's two IPN scripts from github here: https://github.com/paypal/ipn-code-samples/tree/master/php however they aren't working.
I send the test IPN using Paypal's tool here: https://developer.paypal.com/developer/ipnSimulator/ and it says it was succesful: "IPN was sent and the handshake was verified."
However, I can't do what I want after that. I've tried inserting into a database or even just sending a success email. Both of these work fine when done on their own but when I add it to the IPN script nothing happens.
PaypalIPN.php (copied from the github)
<?php
class PaypalIPN
{
/** #var bool Indicates if the sandbox endpoint is used. */
private $use_sandbox = false;
/** #var bool Indicates if the local certificates are used. */
private $use_local_certs = true;
/** Production Postback URL */
const VERIFY_URI = 'https://ipnpb.paypal.com/cgi-bin/webscr';
/** Sandbox Postback URL */
const SANDBOX_VERIFY_URI = 'https://ipnpb.sandbox.paypal.com/cgi- bin/webscr';
/** Response from PayPal indicating validation was successful */
const VALID = 'VERIFIED';
/** Response from PayPal indicating validation failed */
const INVALID = 'INVALID';
/**
* Sets the IPN verification to sandbox mode (for use when testing,
* should not be enabled in production).
* #return void
*/
public function useSandbox()
{
$this->use_sandbox = true;
}
/**
* Sets curl to use php curl's built in certs (may be required in some
* environments).
* #return void
*/
public function usePHPCerts()
{
$this->use_local_certs = false;
}
/**
* Determine endpoint to post the verification data to.
*
* #return string
*/
public function getPaypalUri()
{
if ($this->use_sandbox) {
return self::SANDBOX_VERIFY_URI;
} else {
return self::VERIFY_URI;
}
}
/**
* Verification Function
* Sends the incoming post data back to PayPal using the cURL library.
*
* #return bool
* #throws Exception
*/
public function verifyIPN()
{
if ( ! count($_POST)) {
throw new Exception("Missing POST Data");
}
$raw_post_data = file_get_contents('php://input');
$raw_post_array = explode('&', $raw_post_data);
$myPost = array();
foreach ($raw_post_array as $keyval) {
$keyval = explode('=', $keyval);
if (count($keyval) == 2) {
// Since we do not want the plus in the datetime string to be encoded to a space, we manually encode it.
if ($keyval[0] === 'payment_date') {
if (substr_count($keyval[1], '+') === 1) {
$keyval[1] = str_replace('+', '%2B', $keyval[1]);
}
}
$myPost[$keyval[0]] = urldecode($keyval[1]);
}
}
// Build the body of the verification post request, adding the _notify-validate command.
$req = 'cmd=_notify-validate';
$get_magic_quotes_exists = false;
if (function_exists('get_magic_quotes_gpc')) {
$get_magic_quotes_exists = true;
}
foreach ($myPost as $key => $value) {
if ($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1)
{
$value = urlencode(stripslashes($value));
} else {
$value = urlencode($value);
}
$req .= "&$key=$value";
}
// Post the data back to PayPal, using curl. Throw exceptions if errors occur.
$ch = curl_init($this->getPaypalUri());
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSLVERSION, 6);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
// This is often required if the server is missing a global cert bundle, or is using an outdated one.
if ($this->use_local_certs) {
curl_setopt($ch, CURLOPT_CAINFO, __DIR__ . "/cert/cacert.pem");
}
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'User-Agent: PHP-IPN-Verification-Script',
'Connection: Close',
));
$res = curl_exec($ch);
if ( ! ($res)) {
$errno = curl_errno($ch);
$errstr = curl_error($ch);
curl_close($ch);
throw new Exception("cURL error: [$errno] $errstr");
}
$info = curl_getinfo($ch);
$http_code = $info['http_code'];
if ($http_code != 200) {
throw new Exception("PayPal responded with http code $http_code");
}
curl_close($ch);
// Check if PayPal verifies the IPN data, and if so, return true.
if ($res == self::VALID) {
return true;
} else {
return false;
}
}
}
This is my IPN handler URL, example_usage.php (also copied from the github, I just added the one line to send an email, which does nothing when I send the test IPN):
<?php namespace Listener;
require('PaypalIPN.php');
use PaypalIPN;
$ipn = new PaypalIPN();
// Use the sandbox endpoint during testing.
$ipn->useSandbox();
$verified = $ipn->verifyIPN();
if ($verified) {
/*
* Process IPN
* A list of variables is available here:
*
https://developer.paypal.com/webapps/developer/docs/classic/ipn/integration-
guide/IPNandPDTVariables/
*/
//THIS IS THE ONLY PART I HAVE ADDED, BUT NOTHING IS HAPPENING
$name = '' //Get name from form input
$email = '' //Get email from form input
$amount = '' //Get amount from hidden form input
$subject = 'New order from' . $name
$message = 'New order. Amount: ' . $amount
//For some reason this isn't being sent, even if I change $subject and $message to my own string.
$sendemail= mail("***#***.com", $subject, $message);
}
// Reply with an empty 200 response to indicate to paypal the IPN was
received correctly.
header("HTTP/1.1 200 OK");
?>
Does anyone have an idea of what the problem is? Thanks if so
You need to make sure the IPNs are triggering as expected, and are being sent to the URL you expect.
Follow the steps outlined here and you'll be able to find the problem, which includes:
Local Testing
IPN Simulator
Sandbox Transaction Testing
Deployment
Additional tips for troubleshooting.
I am trying to integrate a payment gateway into a website that is being driven by AngularJS on the front-end and PHP Yii Framework on the backend. The backend is a REST API.
I have a page on my website with all my buying options. When a user clicks on the "Buy" button alongside any of these options I need the user to be sent to the payment page of the payment gateway service provider along with the required details sent as a POST request.
To do this, first I am sending a JSON to one of my APIs. This JSON contains some product related details and that's about it. It is as follows.
$scope.payment = {
key: '',
txnid: '',
amount: '1250',
productinfo: '3',
firstname: '',
email: '',
phone: '',
surl: '',
furl: '',
hash: '',
service_provider: ''
};
Except the amount and product info, all other values are empty.
Once this JSON is received by the API, the API decodes this JSON and fills it up with all the other values. The API code is as follows.
public function actionMakePayment () {
$returnInfo = array("requireLogin"=>false);
if (!$this->isLogedIn()) {
$returnInfo['requireLogin'] = true; // Checking if user is logged in
} else {
$userId = Yii::app()->user->id; // Getting user id
$currentUserModel = User::model()->findByPk($userId); // Extracting user model
$email = $currentUserModel->email; // Extracting email ID
$phone = $currentUserModel->contact_no; // Extracting contact number
$first_name = $currentUserModel->first_name; // Extracting first name
$action = '';
$json = file_get_contents('php://input'); // Taking in the posted JSON
$posted = json_decode($json, true); // Decoding JSON
$MERCHANT_KEY = "XXXXXX"; // Setting merchant key
$SALT = "XXXXXXXX"; // Setting merchant SALT
$PAYU_BASE_URL = "https://paymentgateway.com"; // Gateway domain name
$SERVICE_PROVIDER = "service_provider"; // Gateway provider ID
$RETURN_URL = "http://domain.com/rest/api/resolvePayment"; // Setting URL for redirection after payment is made or cancelled
$formError = 0; // POST data error check
// Assigning txnid
if (empty($posted['txnid'])) {
$txnid = substr(hash('sha256', mt_rand() . microtime()), 0, 20);
$posted['txnid'] = $txnid;
} else {
$txnid = $posted['txnid'];
}
$posted['key'] = $MERCHANT_KEY; // assigning the merchant key
$posted['surl'] = $RETURN_URL; // assigning success URL
$posted['furl'] = $RETURN_URL; // assigning failure URL
$posted['service_provider'] = $SERVICE_PROVIDER; // assigning
$posted['firstname'] = $first_name; // assigning name
$posted['phone'] = $phone; // assigning contact number
$posted['email'] = $email;
$hash = '';
$hashSequence = "key|txnid|amount|productinfo|firstname|email|udf1|udf2|udf3|udf4|udf5|udf6|udf7|udf8|udf9|udf10";
if (empty($posted['hash']) && sizeof($posted) > 0) {
if (
empty($posted['key']) ||
empty($posted['txnid']) ||
empty($posted['amount']) ||
empty($posted['firstname']) ||
empty($posted['email']) ||
empty($posted['phone']) ||
empty($posted['productinfo']) ||
empty($posted['surl']) ||
empty($posted['furl']) ||
empty($posted['service_provider'])
) {
$formError = 1;
} else {
$hashVarsSeq = explode('|', $hashSequence);
$hash_string = '';
foreach($hashVarsSeq as $hash_var) {
$hash_string .= isset($posted[$hash_var]) ? $posted[$hash_var] : '';
$hash_string .= '|';
}
$hash_string .= $SALT;
$hash = strtolower(hash('sha512', $hash_string));
$posted['hash'] = $hash;
$action = $PAYU_BASE_URL . '/_payment';
}
} else if (!empty($posted['hash'])) {
$hash = $posted['hash'];
$action = $PAYU_BASE_URL . '/_payment';
}
}
echo json_encode($posted);
**$this->send_post($action, $posted);**
}
When I echo $posted as a response to the API, it returns the exact JSON I am required to POST to the payment gateway URL. Now comes the part where I am struggling. I am using the last line of code to send the data as POST request to the URL $action. The code for the function "send_post" is as follows.
private function send_post($url, $data) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url); // set url to post to
// curl_setopt($ch, CURLOPT_FAILonerror, TRUE); //Fail on error
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); // return into a variable
curl_setopt($ch, CURLOPT_POST, TRUE); // set POST method
curl_setopt($ch, CURLOPT_POSTFIELDS, $data); // add POST fields
$result = curl_exec($ch); // run the whole process
curl_close($ch);
return $result;
}
I had to comment out the CURLOPT_FAILonerror option as it throws an error. Do not know why. Also, after putting up all this code, when I click on the "buy" button on the front-end, the API executes and return $posted, but I am not taken to the payment page, and I don't know if the data gets posted or not. There is no error in the response to the API call. It executes perfectly as far as I can see.
Can someone help me with this? I am posting the data correctly? Or am I supposed to post the $hash_string variable? The last few parts are confusing me.
This is not strictly an answer to the issue I faced with CURL. But I figured a work around. I sent the parameters as GET variables to an intermediate PHP page that I built. I then captured these GET variables in the PHP page and sent them as a POST request to the payment gateway.
I don't know why CURL did not work, and after I spoke to the payment gateway tech guys they were very much against using CURL. So I tried to send a POST request to the gateway using AngularJS itself. But this was another huge (and seemingly popular) problem with response headers in Angular. I went through a lot of forums to check for solutions but nothing worked for me. So I finally decided to build and intermediate PHP page and work it out as described above.
I know you may ask why I don't try to google the solution first, now I can say that I already googled for it, unfortunately it come out too many solutions and different ways to do that.
My situation is like this, I want to allow those clients to be able to subscribe my service annually.
From this link, they suggested too much solution, I don't know which 1 is fit to my situation. And of course, I want to use the free service (direct debit need monthly fee).
Which mean that, I want to store the transaction# into my db every year when the service subscribed by my client is expired, and it automatically send an acknowledgement email to clients and my company's email.
In summary,
Which way is suitable to my situation.
Is cron job need in this case? or just need to use recurring payment that provided by paypal?
Is there any link or example (i.e. coding implementation in sandbox)?
Thanks in advanced.
You could use PayPal Payments Pro with the Direct Payment API to process the initial credit card transactions. Then you can store the transaction in your system, and set your system to run a cron job and perform a reference transaction API call to charge the buyer again. This will give you the effects of setting up a recurring payment profile without actually having the service through PayPal.
However, if you prefer to do less coding and setting up your system to perform cron jobs and etc, then you could just sign up for PayPal's recurring payments/recurring billing services, which would allow you to just make an API call to PayPal to set up a profile. Then PayPal will take of billing your buyers when they should be billed.
HI I have made code for ZF
public function processPaymentAction()
{
$methodName = 'CreateRecurringPaymentsProfile';
// from nvpHeader function
$API_Endpoint = 'https://api-3t.sandbox.paypal.com/nvp';
$version = '65.2';
// But you can use here your own Sandbox API credentials of Business account
// and you can get through Payapl Sandbox API Credentials Link on Left.
$API_UserName = 'platfo_1255077030_biz_api1.gmail.com';
$API_Password = '1255077037';
$API_Signature = 'Abg0gYcQyxQvnf2HDJkKtA-p6pqhA1k-KTYE0Gcy1diujFio4io5Vqjf';
$subject = '';
global $nvp_Header, $AUTH_token, $AUTH_signature, $AUTH_timestamp;
$nvpHeaderStr = "";
//pr($this->data);die;
//$this->data['User']['paymentType']
$paymentType = urlencode('Sale');
$firstName = urlencode("Jaskaran");
$lastName = urlencode("Singh");
$creditCardType = urlencode("Visa");
$creditCardNumber = urlencode("4798720058660243");
$expDateMonth =urlencode(11);
// Month must be padded with leading zero
$padDateMonth = str_pad($expDateMonth, 2, '0', STR_PAD_LEFT);
$expDateYear = urlencode(2015);
$cvv2Number = urlencode(962);
$address1 = urlencode("1 Main St");
$address2 = urlencode("");
$city = urlencode("San Jose");
$state = urlencode("CA");
$zip = urlencode(95131);
$amount = urlencode(1.00);
// $init_amount = urlencode($this->data['User']['pack_price']);
$currencyCode="USD";
$profileDesc = urlencode("Welcome to the world of shopping where you get everything");
$billingPeriod = urlencode("Week");
$billingFrequency = urlencode(4);
$totalBillingCycles = urlencode(0);
################# Commented as we need to define through Admin ##############
$profileStartDateDay = 10;
// Day must be padded with leading zero
$padprofileStartDateDay = str_pad($profileStartDateDay, 2, '0', STR_PAD_LEFT);
$profileStartDateMonth = 02;
// Month must be padded with leading zero
$padprofileStartDateMonth = str_pad($profileStartDateMonth, 2, '0', STR_PAD_LEFT);
$profileStartDateYear = 2015;
$profileStartDate = urlencode($profileStartDateYear . '-' . $padprofileStartDateMonth . '-' . $padprofileStartDateDay . 'T00:00:00Z');
//string from nvpHeader
$nvpHeaderStr = "&PWD=".urlencode($API_Password)."&USER=".urlencode($API_UserName)."&SIGNATURE=".urlencode($API_Signature);
$nvpstr="&AMT=$amount&CREDITCARDTYPE=$creditCardType&ACCT=$creditCardNumber&EXPDATE=". $padDateMonth.$expDateYear."&CVV2=$cvv2Number&FIRSTNAME=$firstName&LASTNAME=$lastName&STREET=$address1&CITY=$city&STATE=$state".
"&ZIP=$zip&COUNTRYCODE=US&CURRENCYCODE=$currencyCode&PROFILESTARTDATE=$profileStartDate&DESC=$profileDesc&BILLINGPERIOD=$billingPeriod&BILLINGFREQUENCY=$billingFrequency&TOTALBILLINGCYCLES=$totalBillingCycles";
$nvpstr = $nvpHeaderStr.$nvpstr;
//check if version is included in $nvpStr else include the version.
if(strlen(str_replace('VERSION=','', strtoupper($nvpstr))) == strlen($nvpstr))
{
$nvpstr = "&VERSION=" . urlencode($version) . $nvpstr;
}
$nvpreq="METHOD=".urlencode($methodName).$nvpstr;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$API_Endpoint);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POST, 1);
//$nvpreq=”METHOD=”.urlencode($methodName).$nvpStr;
//setting the nvpreq as POST FIELD to curl
curl_setopt($ch,CURLOPT_POSTFIELDS,$nvpreq);
//getting response from server
$response = curl_exec($ch);
//convrting NVPResponse to an Associative Array
$nvpResArray=$this->deformatNVP($response);
$nvpReqArray=$this->deformatNVP($nvpreq);
if (curl_errno($ch))
{
echo "cURL Error";
die;
// moving to display page to display curl errors
$_SESSION['curl_error_no']=curl_errno($ch) ;
$_SESSION['curl_error_msg']=curl_error($ch);
//$location = "APIError.php";
//header("Location: $location");
}
else
{
//closing the curl
curl_close($ch);
}
#### Checking error ###
if(!empty($nvpResArray))
{
if($nvpResArray['ACK'] == 'Failure')
{
echo "ERROR : ". $errmsg = $nvpResArray["L_LONGMESSAGE0"];
echo "<pre>";
print_r($nvpResArray);
die;
}
}
// Print this array you will get some necessary info
################ Starting data insert##################
if($nvpResArray['ACK'] == 'Success')
{
echo 'Success';
print_r($nvpResArray);
die;
// save data into tables for Recurring Profile
}
}
############### Function deformatNVP #########
/** This function will take NVPString and convert it to an Associative Array and it will decode the response.
* It is usefull to search for a particular key and displaying arrays.
* #nvpstr is NVPString.
* #nvpArray is Associative Array.
*/
function deformatNVP ($nvpstr)
{
$intial = 0;
$nvpArray = array();
while (strlen($nvpstr)) {
//postion of Key
$keypos = strpos($nvpstr, '=');
//position of value
$valuepos = strpos($nvpstr, '&') ? strpos($nvpstr, '&') : strlen(
$nvpstr);
/*getting the Key and Value values and storing in a Associative Array*/
$keyval = substr($nvpstr, $intial, $keypos);
$valval = substr($nvpstr, $keypos + 1, $valuepos - $keypos - 1);
//decoding the respose
$nvpArray[urldecode($keyval)] = urldecode($valval);
$nvpstr = substr($nvpstr, $valuepos + 1, strlen($nvpstr));
}
return $nvpArray;
}
function formAutorization ($auth_token, $auth_signature, $auth_timestamp)
{
$authString = "token=" . $auth_token . ",signature=" . $auth_signature .
",timestamp=" . $auth_timestamp;
return $authString;
}
This is a question about Paypal Mass Pay IPN. My platform is PHP & mySQL.
All over the Paypal support website, I have found IPN for only payments made. I need an IPN on similar lines for Mass Pay but could not find it. Also tried experimenting with already existing Mass Pay NVP code, but that did not work either.
What I am trying to do is that for all the recipients to whom the payment has been successfully sent via Mass Pay, I want to record their email, amount and unique_id in my own database table. If possible, I want to capture the payment status as well, whether it has been a success of failure and based upon the same, I need to do some in house processing.
The existing code Mass pay code is below:
<?php
$environment = 'sandbox'; // or 'beta-sandbox' or 'live'
/**
* Send HTTP POST Request
*
* #param string The API method name
* #param string The POST Message fields in &name=value pair format
* #return array Parsed HTTP Response body
*/
function PPHttpPost($methodName_, $nvpStr_) {
global $environment;
// Set up your API credentials, PayPal end point, and API version.
$API_UserName = urlencode('my_api_username');
$API_Password = urlencode('my_api_password');
$API_Signature = urlencode('my_api_signature');
$API_Endpoint = "https://api-3t.paypal.com/nvp";
if("sandbox" === $environment || "beta-sandbox" === $environment) {
$API_Endpoint = "https://api-3t.$environment.paypal.com/nvp";
}
$version = urlencode('51.0');
// Set the curl parameters.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $API_Endpoint);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
// Turn off the server and peer verification (TrustManager Concept).
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
// Set the API operation, version, and API signature in the request.
$nvpreq = "METHOD=$methodName_&VERSION=$version&PWD=$API_Password&USER=$API_UserName&SIGNATURE=$API_Signature$nvpStr_";
// Set the request as a POST FIELD for curl.
curl_setopt($ch, CURLOPT_POSTFIELDS, $nvpreq);
// Get response from the server.
$httpResponse = curl_exec($ch);
if(!$httpResponse) {
exit("$methodName_ failed: ".curl_error($ch).'('.curl_errno($ch).')');
}
// Extract the response details.
$httpResponseAr = explode("&", $httpResponse);
$httpParsedResponseAr = array();
foreach ($httpResponseAr as $i => $value) {
$tmpAr = explode("=", $value);
if(sizeof($tmpAr) > 1) {
$httpParsedResponseAr[$tmpAr[0]] = $tmpAr[1];
}
}
if((0 == sizeof($httpParsedResponseAr)) || !array_key_exists('ACK', $httpParsedResponseAr)) {
exit("Invalid HTTP Response for POST request($nvpreq) to $API_Endpoint.");
}
return $httpParsedResponseAr;
}
// Set request-specific fields.
$emailSubject =urlencode('example_email_subject');
$receiverType = urlencode('EmailAddress');
$currency = urlencode('USD'); // or other currency ('GBP', 'EUR', 'JPY', 'CAD', 'AUD')
// Add request-specific fields to the request string.
$nvpStr="&EMAILSUBJECT=$emailSubject&RECEIVERTYPE=$receiverType&CURRENCYCODE=$currency";
$receiversArray = array();
for($i = 0; $i < 3; $i++) {
$receiverData = array( 'receiverEmail' => "user$i#paypal.com",
'amount' => "example_amount",
'uniqueID' => "example_unique_id",
'note' => "example_note");
$receiversArray[$i] = $receiverData;
}
foreach($receiversArray as $i => $receiverData) {
$receiverEmail = urlencode($receiverData['receiverEmail']);
$amount = urlencode($receiverData['amount']);
$uniqueID = urlencode($receiverData['uniqueID']);
$note = urlencode($receiverData['note']);
$nvpStr .= "&L_EMAIL$i=$receiverEmail&L_Amt$i=$amount&L_UNIQUEID$i=$uniqueID&L_NOTE$i=$note";
}
// Execute the API operation; see the PPHttpPost function above.
$httpParsedResponseAr = PPHttpPost('MassPay', $nvpStr);
if("SUCCESS" == strtoupper($httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($httpParsedResponseAr["ACK"])) {
exit('MassPay Completed Successfully: '.print_r($httpParsedResponseAr, true));
} else {
exit('MassPay failed: ' . print_r($httpParsedResponseAr, true));
}
?>
In the code above, how and where do I add code to capture the fields that I requested above? Any code indicating the solution is highly appreciated.
Thank you very much.
I am more familiar with Recurring Payments, but I think the IPN response will send back the values you are seeking. Just capture them out of the array sent back, place them in some variables, and save to the database.
$email = $httpParsedResponseAr["receiver_email"];
$amount = $httpParsedResponseAr["mc_currency_x"];
Here are the values for the Mass Pay Variables
https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_html_IPNandPDTVariables
There are generally two ways to get this data, one is to look at the responses from the call you make to masspay directly, and the other is setting up IPN for your account.
You have to setup the global IPN, I cannot find a way to send in the IPN listen url as a variable on this call.
HTH
-FT