Sending a payment gateway POST request through a RESTful API - php

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.

Related

Submit POST data in loop without cURL and get response data - CodeIgniter

I have a code that sends SMS to customers that is set up as cron job. My problem is, when I use cURL, it's sending 2-part messages and our wallet is being charged twice. We have an average of 500 messages to send per day. My goal is to make the message 1-part only.
So I'm trying to find the best way to send messages in loop without using cURL.
I have thought of saving the post data from the loop in an array and send it to my view. Then when the view is called, I will automatically send the form withouth hitting the submit button and using javascript to auto submit. After the view is called, I will use file_get_contents() to get the response from the URL. But I cant make it work:
The view is not working inside the loop. It just works outside the loop.
If I pass the loop inside the view and not in the controller, how can I get the response data each loop?
My current code in CURL:
public function send_sms_globe(){
error_reporting(-1);
ini_set('display_errors', 1);
set_time_limit(0);
//get all data from the database pull with status = queue
$globe_data = $this->New_Sms_Api_model->get_queued_data('globe_api');
$passphrase = '[our_pass_phrase]';
$app_id = '[our_app_id]';
$app_secret = '[our_app_secret]';
$url = 'https://devapi.globelabs.com.ph/smsmessaging/v1/outbound/<our_shortcode>/requests/';
$ch = curl_init($url);
$limit = 0;
foreach($globe_data AS $records_data){
if($limit == 49){
break;
}
switch($limit) {
case 49:
$limit = 0;
break;
default:
if($records_data['Remarks'] == 'LOADED'){
if($records_data['sent_to'] == 'sender'){
$address = $records_data['sender_phone_number'];
}else if($records_data['sent_to'] == 'consignee'){
$address = $records_data['consignee_phone_number'];
}
} else {
$address = $records_data['sender_phone_number'];
}
//$address = '+63917*******';//address : *subscriber number $records_data['phone_number'];
$message = (isset($records_data['Message']) && $records_data['Message'] != '') ? $records_data['Message']:''; //message : *sms content
$str = iconv('UTF-8', 'ASCII//IGNORE//TRANSLIT', $message);
$post_data = [
'app_id' => $app_id,
'app_secret' => $app_secret,
'passphrase' => $passphrase,
'message' => rawurlencode($str),
'address' => $address
];
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
// execute!
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$queue_id = $records_data['ID'];
$invoice_number = $records_data['InvoicecNumber'];
$status_remark = $records_data['Remarks'];
$record_id = $records_data['record_id'];
if($http_code == 201 || $http_code == 200){
$no_of_tries = $records_data['no_of_tries'];
if($no_of_tries == 0){
$no_of_tries = 1;
} else {
$no_of_tries = $records_data['no_of_tries'];
}
$status = 'sent';
$retry = 0;
} else {
$no_of_tries = $records_data['no_of_tries'] + 1;
if($no_of_tries == 3){
$status = 'failed';
$retry = 0;
} else {
$status = 'retry';
$retry = 1;
}
}
$update_queued_data = $this->New_Sms_Api_model->update_queued_data($queue_id, $invoice_number, $status, $retry, $no_of_tries);
if($update_queued_data){
if($status == 'sent'){
if($status_remark == 'LOADED'){
$sent_to = $records_data['sent_to'];
} else {
$sent_to = NULL;
}
$this->New_Sms_Api_model->save_to_cq_sms($invoice_number, $status_remark, $record_id,$sent_to);
echo $records_data['record_id'].' ---- '.$status;
}
$limit++;
}
}
}
// close the connection, release resources used
curl_close($ch);
}
We have a message with 157 characters (160 max). I already talked to the API support we're using. First they suggested to format my message as URL encoding, and so I did. So from 3-part message it became 2-part. And then they said it will send as 2-part even if it's formatted that way because we use cURL. They suggested that we use PostMan but it's not for free so it's not an option.
Any ideas that can replace my current code? Thanks!
Sorry for the confusion. I was able to fix the issue without changing all of my code. I just removed rawurlencode in my string message and it's sending a 1-part message now.
Maybe using $str = iconv('UTF-8', 'ASCII//IGNORE//TRANSLIT', $message); already did the trick and using rawurlencode after just added additional characters ex: %20.
Thanks everyone!

How to integrate paypal in Zend Framework 1.12?

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;
}

Submit form via cURL and redirect browser to PayPal

I'm developing a site where customers have several payment options, including PayPal Payments Standard. Since I'm collecting a fair amount of data about the customer, I'd like to process the form on my server before sending the user to PayPal's server. One option is to concatenate the data into a single string, assign the string to the custom field, and then process it in the IPN response, but I find this to be a very inelegant solution. Instead, after collecting the user data, I'm attempting to use cURL to submit a standard HTML PayPal form. How can I redirect the user to PayPal to complete the checkout process?
// Process PayPal payment
if ($method == 'PayPal') {
// Prepare POST data
$query = array();
$query['notify_url'] = 'http://example.com/ipn';
$query['cmd'] = '_cart';
$query['upload'] = '1';
$query['business'] = 'email#example.com';
$query['address_override'] = '1';
$query['first_name'] = $first_name;
$query['last_name'] = $last_name;
$query['email'] = $email;
$query['address1'] = $ship_to_address;
$query['city'] = $ship_to_city;
$query['state'] = $ship_to_state;
$query['zip'] = $ship_to_zip;
$query['item_name_'.$i] = $item['description'];
$query['quantity_'.$i] = $item['quantity'];
$query['amount_'.$i] = $item['info']['price'];
// Prepare query string
$query_string = '';
foreach ($query as $key=>$value) {
$query_string .= $key.'='.urlencode($value).'&';
}
$query_string = rtrim($query_string, '&');
// Open connection
$ch = curl_init();
//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL, 'https://www.paypal.com/cgi-bin/webscr');
curl_setopt($ch,CURLOPT_POST, count($query));
curl_setopt($ch,CURLOPT_POSTFIELDS, $query_string);
// Execute post
$result = curl_exec($ch);
// Close connection
curl_close($ch);
}
WARNING: this answer has a security deficit. Passing sensitive data (such as item and price) through the client allows the client to modify the transaction. ie. change the item, or change the price. See the PayPal documentation on how to implement IPN.
You should redirect the user with the php header function and send the vars as GET not POST.
// Process PayPal payment
if ($method == 'PayPal') {
// Prepare GET data
$query = array();
$query['notify_url'] = 'http://jackeyes.com/ipn';
$query['cmd'] = '_cart';
$query['upload'] = '1';
$query['business'] = 'social#jackeyes.com';
$query['address_override'] = '1';
$query['first_name'] = $first_name;
$query['last_name'] = $last_name;
$query['email'] = $email;
$query['address1'] = $ship_to_address;
$query['city'] = $ship_to_city;
$query['state'] = $ship_to_state;
$query['zip'] = $ship_to_zip;
$query['item_name_'.$i] = $item['description'];
$query['quantity_'.$i] = $item['quantity'];
$query['amount_'.$i] = $item['info']['price'];
// Prepare query string
$query_string = http_build_query($query);
header('Location: https://www.paypal.com/cgi-bin/webscr?' . $query_string);
}
Rather than trying to post all the data to PayPal and back, you should keep the data on your server and send only an identifying token. Any data you send to PayPal (via the user's browser) can be intercepted and modified. This is a serious security hazard.
If you send only the token there is no opportunity for tampering.
Read the PayPal spec, it has guidelines on how to implement these things.
You must use IPN or some similar post processing because PayPal is the only one who knows whether a payment was actually made. Do not trust any data you get from the user.
doing curl it will make end to end calls in backend side , it will not reflect on frontend behavior .
you have to make a form with hidden field and javascript to auto submit the form once page loaded .

Importing quotes into vtiger crm with web services

I need to import quotes into vtiger.
I find out it can be be done using vtiger web services API
I find out the reference manual:
https://wiki.vtiger.com/archives/index.php/vtiger510:Webservice_reference_manual
But i can't find any example PHP script, neither what data fields I need to pass to webservice.php.
Please help, I need some guidance.
I have done something like this, I have a quick and (rather) dirty but working solution:
<?php
function createOffer($account_id,$subject,$offerlanguage, $totalamount,$date_submission,$date_decision,$date_start,$assigned_user_id,$quotestage,$winningchance,$description,$productarray){
global $adb;
$endpointUrl = "[your URL]/webservice.php";
$userName="admin";
$userAccessKey = '[your accesskey]';
$httpc = new HTTP_CLIENT();
//getchallenge request must be a GET request.
$httpc->GET($endpointUrl."?operation=getchallenge&username=".$userName);
$response = $httpc->currentResponse();
//decode the json encode response from the server.
$jsonResponse = Zend_JSON::decode($response['body']);
//check for whether the requested operation was successful or not.
if($jsonResponse['success']==false)
//handle the failure case.
die('getchallenge failed:'.$jsonResponse['error']['errorMsg']);
//operation was successful get the token from the reponse.
$challengeToken = $jsonResponse['result']['token'];
//create md5 string concatenating user accesskey from my preference page
//and the challenge token obtained from get challenge result.
$generatedKey = md5($challengeToken.$userAccessKey);
//getchallenge request must be a GET request.
$httpc->post("$endpointUrl",
array('operation'=>'login', 'username'=>$userName, 'accessKey'=>$generatedKey), true);
$response = $httpc->currentResponse();
//decode the json encode response from the server.
$jsonResponse = Zend_JSON::decode($response['body']);
//operation was successful get the token from the reponse.
if($jsonResponse['success']==false)
//handle the failure case.
die('login failed:'.$jsonResponse['error']['errorMsg']);
//login successful extract sessionId and userId from LoginResult to it can used for further calls.
$sessionId = $jsonResponse['result']['sessionName'];
$userId = $jsonResponse['result']['userId'];
$currency_id=1;
$params = array('description'=>$description,'subject'=>$subject,'quotestage'=>$quotestage,'assigned_user_id'=>'2x'.$assigned_user_id,'account_id'=>'3x'.$account_id,'cf_682'=>$offerlanguage,'currency_id'=>'21x'.$currency_id,'taxtype'=>'group','cf_683'=>$date_submission,'cf_684'=>$date_decision,'cf_685'=>$date_start,'cf_766'=>$winningchance);
$urlArgs = "?&total=".$totalamount;
//encode the object in JSON format to communicate with the server.
$objectJson = Zend_JSON::encode($params);
//name of the module for which the entry has to be created.
$moduleName = 'Quotes';
//sessionId is obtained from loginResult.
$params = array("sessionName"=>$sessionId, "operation"=>'create', "element"=>$objectJson, "elementType"=>$moduleName);
//Create must be POST Request.
$httpc->post($endpointUrl.$urlArgs, $params, true);
$response = $httpc->currentResponse();
//decode the json encode response from the server.
$jsonResponse = Zend_JSON::decode($response['body']);
$savedObject = $jsonResponse['result'];
$id = $savedObject['id'];
$id=str_replace("13x", "", $id);
echo $id." offer: ".$subject." created for amount ".$totalamount." for customer: ".$account_id." assigned to: ".$assigned_user_id;
return $id;
}
As you see there are a few custom fields too so you can see how I've handled those.
You can call this function like this:
createOffer($account_id, $subject, $offerlanguage, $totalamount, $date_submission, $date_decision, $date_start, $assigned_user_id, $quotestage, $winningchance, $description, $productarray)
Then you need to add the products too, which I've found the easiest via a separate function as there can be more products per quote...
<?php
function createProducts($productarray,$id) {
$counter = 1;
foreach ($productarray as $prod) {
$query ="insert into vtiger_inventoryproductrel(id, productid, sequence_no, quantity, listprice) values(?,?,?,?,?)";
$qparams = array($id,$prod['prod'],$counter,$prod['pcs'],$prod['price']);
$productadded=$adb->pquery($query,$qparams);
$counter=$counter+1;
}
}
use it like this:
$prodlist = array();
array_push($prodlist,array('prod'=>"prod1",'pcs'=>2,'price'=>1000));
array_push($prodlist,array('prod'=>"prod2",'pcs'=>2,'price'=>100));
createProducts($prodlist,10);
so my logic is like this:
you create the quote with the createOffer function. It returns with the newly created quote's ID
then you build the array of products (I have just the very basic data here) and add that by referencing the quote's ID
Maybe not the most beautiful solution but works.
Maybe you can start like this (according to your reference link).
Manual: https://wiki.vtiger.com/archives/index.php/vtiger510:Webservice_reference_manual
Login: https://wiki.vtiger.com/archives/index.php/vtiger510:Webservice_reference_manual#Login
Pseudo;
<?php
class VTiger_Login
{
private $serviceURL = 'http://vtiger_url/webservice.php?operation=login&username=%s&accessKey=%s';
// A Vtiger username.
private $userName = 'my_username';
// An md5 of the concatenation of the challenge token and the user's webservice access key.
private accessKey = 'my_accesskey';
public function login() {
// Open CURL
$ch = curl_init();
// Set URL as same as on manual
curl_setopt($ch, CURLOPT_URL, sprintf($this->serviceURL, $this->userName, $this->accessKey));
// Need POST according to manual
curl_setopt($ch, CURLOPT_POST, 1);
// Receive server response = TRUE
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// Exec CURL
$result = curl_exec($ch);
// Close CURL
curl_close($ch);
/*
$result should be like this according to manual;
LoginResult {
sessionId: String // Unique Identifier for the session
userId: String // The vtiger id for the logged in user
version: String // The version of the webservices api
vtigerVersion: String // The version of the vtiger crm.
}
*/
// From manual: All structural data including response from the api is represented as JSON strings.
$result =# json_decode($result);
// See "Response" on manual
if (null === $result) {
throw new Exception('No response returned from Vtiger server!');
}
// See "ErrorObject" on manual
if (null !== $result->success && false === $result->success) {
throw new Exception('Something went wrong with login operation! errorCode: '.
$result->errorCode .', errorMessage: '. $result->errorMessage);
}
// I think, there is no problem anymore, go with $result after this line...
}
}

How to get PayPal transaction ID from invoice ID

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'];
}
?>

Categories