I'm sending a request to an API that sends back a response to a page/url (response.php). Details from this response are stored in a db table as well as the page's session id. Obtaining the data stored in the db with the session id as the reference value returns null because I noticed the session id sent to the db alongside the response body changes each time making it different to session ids from all other pages in the folder (processor.php, app.js, fromdb.php) which are similar each other. How do I handle the issue seeing as I need the device from which the button that initiated the process got clicked to be able to receive an alert with some details based on data saved to db, on whether their payment was successful or not.
The js page that initiates action when a button is clicked:
if (document.readyState == 'loading') {
document.addEventListener('DOMContentLoaded',ready);
}else{
ready()
}
function ready() {
var btn = document.getElementById('sub')
btn.addEventListener('click',btnClicked)
console.log("ready")
}
function btnClicked() {
let amount = document.getElementById('Amt').value;
let phone = document.getElementById('Number').value;
let name = document.getElementById('Name').value;
//using ajax post data
$.ajax({
url: "http://localhost/textEditor/processor.php",
method: "POST",
data: {
amount: amount,
phone: phone,
name: name
},
});
getResult();
}
async function getResult() {
//using ajx Get method to obtain data from db echoed on fromdb.php page
return await setTimeout($.ajax({
url: "http://localhost/textEditor/fromdb.php",
method: "GET",
success: function(data) {
console.log("The data is:", data)
}
}), 5000)
}
Below is page that makes request to the API and provides callbackurl on which response is sent:
<!-- processor.php -->
<?php
session_start();
$sess_id = session_id();
include_once "db.te.php";
// if (isset($_POST['submit'])) {
date_default_timezone_set('Africa/Nairobi');
$Passkey = 'bfb279f9aa9bdbcf158e97dd71a467cd2e0c893059b10f78e6b72ada1ed2c919';
$Amount= $_POST['amount'];
$BusinessShortCode = '174379';
$PartyA =$_POST['phone'];
$AccountReference =$_POST['name'];
$TransactionDesc = 'test';
$Timestamp =date('YmdHis');
$Password = base64_encode($BusinessShortCode.$Passkey.$Timestamp);
$headers=['Content-Type:application/json; charset=utf8'];
$initiate_url='https://sandbox.safaricom.co.ke/mpesa/stkpush/v1/processrequest';
$callBackURL ='https://c28d-197-231-178-65.ngrok.io/textEditor/response.php';
// ------------------------------
function newAccessToken() {
$ConsumerKey = 'uhsjjsjbVGatHuJKK';
$ConsumerSecret = 'Yh29KHAY17LKjahh';
$credentials = base64_encode($ConsumerKey.":".$ConsumerSecret);
$url = "https://sandbox.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HTTPHEADER, array("Authorization: Basic ".$credentials,"Content-Type:application/json"));
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$curl_response = curl_exec($curl);
$access_token=json_decode($curl_response);
curl_close($curl);
return $access_token->access_token;
}
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $initiate_url);
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type:application/json','Authorization:Bearer '.newAccessToken()));
$curl_post_data = array(
'BusinessShortCode' =>$BusinessShortCode,
'Password' => $Password,
'Timestamp' => $Timestamp,
'TransactionType' => 'CustomerPayBillOnline',
'Amount' => $Amount,
'PartyA' => $PartyA,
'PartyB' => $BusinessShortCode,
'PhoneNumber' => $PartyA,
'CallBackURL' => $callBackURL,
'AccountReference' => $AccountReference,
'TransactionDesc' => $TransactionDesc
);
$data_string = json_encode($curl_post_data);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
$curl_response = curl_exec($curl);
curl_close($curl);
// }
The callbackurl page where response is sent and inserted into db:
<!-- callbackurl: response.php, page where response body is sent to the db alongside its session id-->
<?php
include_once "db.te.php";
session_start();
$sess_id = session_id();
$homepage = file_get_contents('php://input');
$nowNow = json_decode($homepage);
if ($nowNow->Body->stkCallback->ResultCode==0) {
$Items = $nowNow->Body->stkCallback->CallbackMetadata->Item;
foreach($Items as $Item) {
if ($Item->Name =='MpesaReceiptNumber') {
$MpesaReceiptNumber = $Item->Value;
}
}
}else{
$ResultCode = $nowNow->Body->stkCallback->ResultCode;
$MerchantRequestID = $nowNow->Body->stkCallback->MerchantRequestID;
$CheckoutRequestID = $nowNow->Body->stkCallback->CheckoutRequestID;
$ResultDesc = $nowNow->Body->stkCallback->ResultDesc;
$sql = "SELECT * FROM duka;";
$stmt = mysqli_stmt_init($conn);
if (!mysqli_stmt_prepare($stmt, $sql)) {
echo "SQL statement failed 1!";
}else{
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
$rowCount = mysqli_num_rows($result);
$sql = "INSERT INTO duka(ResultCode, MerchantReqID, CheckoutReqID, ResultDesc, SessionId) VALUES (?,?,?,?,?);";
if (!mysqli_stmt_prepare($stmt, $sql)) {
echo "SQL statement failed 2!";
}else{
mysqli_stmt_bind_param($stmt,"sssss", $ResultCode, $MerchantRequestID,$CheckoutRequestID,$ResultDesc,$sess_id);
mysqli_stmt_execute($stmt);
}
}
}
Selecting data from db and sending it to the js page to be logged:
<!-- fromdb.php -->
<?php
include_once "db.te.php";
session_start();
$sess_id = session_id();
//retrieving data from db where Session ID is equal to this page's session ID
$sql="SELECT * FROM duka WHERE SessionId = $sess_id;";
$result = mysqli_query($conn, $sql);
$resultCheck=mysqli_num_rows($result);
if ($resultCheck > 0) {
while ($row = mysqli_fetch_assoc($result)) {
$data = $row["CheckoutReqID"];
}
}
//value to be printed using console.log following an ajax get method
echo json_encode($data);
If you set a cookie for the id, instead of the session, you'll be able to maintain the id in the callback url.
Related
if i call reload function before ajax call then can ajax execute or not?
function my_status_update(id,va){
$(".close-menu").trigger("click");
var status = va;
var id = id;
$.ajax({
type: "POST",
url : base_url+'home/update_status_job_naha?id='+id+'&&val='+status,
data: {status:status,id:id},
success: function(){
},
});
location.reload();
}
public function update_status_job_naha(){
$status = $_REQUEST['val'];
$id = $_REQUEST['id'];
$data = array(
'shipping-status' => $status,
'shipping_status' => $status,
'status_change_dt' => date('d-m-Y h:i:sa'),
);
$this->db->where('id', $id);
$this->db->update('one_table', $data);
$d_id=$this->session->userdata('user_id');
$status = $_REQUEST['val'];
$id = $_REQUEST['id'];
$data = array(
'tracking_reference' => $id,
'shipping_status' => $status,
'updated_by' => $d_id
);
$this->db->insert('second_table',$data);
if ($status=='Delivered' && isset($_REQUEST['amount'])) {
$ins_am=0;
$amount = $_REQUEST['amount'];
$d_id=$this->session->userdata('user_id');
$amount_d_b = $this->Common_Model->get_wallet_amount_ofdriver($d_id);
$ins_am =($amount_d_b[0]->delv_amount+$amount);
$dataam = array('delv_amount' => $ins_am );
$this->db->where('id', $d_id);
$this->db->update('third_table', $dataam);
}
$url = 'https://this_is_a_api/notify-order-status/';
$ch = curl_init($url);
$payload = array(
'tracking-reference'=>$id, 'shipping-status'=>$status
);
$data = json_encode($payload);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type:application/json',
'Media type:: application/json'
));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
curl_close($ch);
return true;
}
here $url = 'https://this_is_a_api/notify-order-status/'; this is very slow.
my issues are:
i update status with ajax call
in ajax call have a api link (that link was very slow.when i got the response i become a old man )
what i need:
api response no matter about me that will update in background
reload my page with new status
The code down below was implemented by me to retrieve specific details from LinkedIn accounts and save them to the database. Although they are retrieving correctly data is not saving to the database correctly. Not sure something wrong with my query. Please have a look at my coding and point out the issue. Any sort of help would be really appreciated.
<?php
session_start();
$client_id = "";
$client_secret = "";
$redirect_uri = "http://localhost:8888/Exercise/callback.php";
$csrf_token = random_int(1111111, 9999999);
$scopes = "r_basicprofile%20r_emailaddress";
function curl($url, $parameters)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $parameters);
curl_setopt($ch, CURLOPT_POST, 1);
$headers = [];
$headers[] = "Content-Type: application/x-www-form-urlencoded";
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($ch);
return $result;
}
function getCallback()
{
$client_id = "";
$client_secret = "";
$redirect_uri = "http://localhost:8888/Exercise/callback.php";
$csrf_token = random_int(1111111, 9999999);
$scopes = "r_basicprofile%20r_emailaddress";
if (isset($_REQUEST['code'])) {
$code = $_REQUEST['code'];
$url = "https://www.linkedin.com/oauth/v2/accessToken";
$params = [
'client_id' => $client_id,
'client_secret' => $client_secret,
'redirect_uri' => $redirect_uri,
'code' => $code,
'grant_type' => 'authorization_code',
];
$accessToken = curl($url,http_build_query($params));
$accessToken = json_decode($accessToken)->access_token;
$url = "https://api.linkedin.com/v1/people/~:(id,firstName,lastName,pictureUrls::(original),headline,publicProfileUrl,location,industry,positions,email-address )?format=json&oauth2_access_token=" . $accessToken;
$user = file_get_contents($url, false);
$User = json_decode(post_curl($url)); // Request user information on received token
$query = "INSERT INTO `linkedti_scheduler`.`users`
(`userid`,
`firstName`,
`lastName`,
`emailAddress`,
`position`,
`location`,
`profileURL`,
`headline`)
VALUES
('$id',
'$firstName',
'$lastName',
'$emailAddress',
'$position',
'$location',
'$profileURL',
'$headline')";
mysqli_query($connection,$query);
return (json_decode($user));
}
}
?>
You need to reference the fields using the $User object like this:
$User = json_decode(post_curl($url)); // Request user information on received token
$query = "INSERT INTO `linkedti_scheduler`.`users`
(`userid`,
`firstName`,
`lastName`,
`emailAddress`,
`position`,
`location`,
`profileURL`,
`headline`)
VALUES
('$id',
'$User->firstName',
'$User->lastName',
'$User->emailAddress',
'$User->position',
'$User->location',
'$User->profileURL',
'$User->headline')";
Also, be warned that you are not using an MySQL escaping here -- I suggest using a prepared query to prevent any issues with single quotes:
https://secure.php.net/manual/en/mysqli.quickstart.prepared-statements.php
I have the following JavaScript that sends parameters to a PHP file:
function getOutput()
{
$.ajax({
url:'myPHPFile.php',
data:{APIKey:$APIKey,Password:$APIPass,Alias:$Alias,DataCenter:$DataCenter},
type:'POST',
complete: function (response) {
$('#output').html(response.responseText);
},
error: function ()
{
$('#output').html('Bummer: there was an error!');
}
});
return response.responseText;
}`
Which changes the following HTML to the output of the PHP file:
test
Here is the PHP
<?php
// echo nl2br("\nIntializing api.php \n");
// DATA SECTION
$APIKey = $_POST["APIKey"];
$APIPass = $_POST["Password"];
$AccountAlias = $_POST["Alias"];
$dataCenter = $_POST["DataCenter"];
$data = array(
"APIKey" => $APIKey,
"Password" => $APIPass,
);
$url_send = 'https://api.ctl.io/REST/Auth/Logon/';
$json_data = json_encode($data);
function sendPostData($url, $post, $cook = null){
// echo "Beginning sendPostData($url, $post, $cook)";
$ch = curl_init($url);
$headers= array('Accept: application/json','Content-Type: application/json');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS,$post);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
if (!empty($cook))
{
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: application/json','Content-Type: application/json','Cookie:'.$cook));
}
$result = curl_exec($ch);
curl_close($ch); // Seems like good practice
return $result;
};
$myresult = sendPostData($url_send, $json_data);
// print_r ($myresult);
$decodedresult = json_decode($myresult);
// print_r ($decodedresult);
'/reply-(.*?)-private/';
preg_match_all('/Tier3(.*?)path=/', $myresult, $matches);
$cookies = array();
foreach($matches[0] as $item)
{
parse_str($item, $cookie);
$cookies = array_merge($cookies, $cookie);
}
$prefix = 'Tier3.API.Cookie=';
$cookie = implode(" ",$matches[0]);
// Call the customer server list
$data = array(
'AccountAlias' => $AccountAlias,
'Location' => $dataCenter
);
$data_url = 'https://api.ctl.io/REST/Server/GetAllServersForAccountHierarchy/';
$data_string = json_encode($data);
$dataResult = sendPostData($data_url,$data_string, $cookie);
print_r($dataResult);
return $dataResult;
`
How can I get the $dataResult PHP array into a javascript variable so I can parse it? It is a big JSON response from an API.
Thanks.
Ajax calls are (normally) asynchronous, this means that the return response.responseText; will be executed immediately and should even raise an error related to response being undefined.
You'll have the response in the complete event of the ajax call and is inside there where you should go on with the execution of the script. jQuery will parse the JSON automatically and response will be the resulting object.
At the other side, the PHP script should just print the result of json_encode() and nothing else in order for the response to be valid JSON.
how to create a post with request in php or javascript for steam web API
Example post:
https://api.steampowered.com/IEconService/CancelTradeOffer/v1/?key=STEAM_API_KEY&tradeofferid=TRADE_OFFER_ID
when i use it in a browser i get:
Method Not Allowed
This API must be called with a HTTP POST request
In C# this was written as:
private bool CancelTradeOffer(ulong tradeofferid)
{
string options = string.Format("?key={0}&tradeofferid={1}", ApiKey, tradeofferid);
string url = String.Format(BaseUrl, "CancelTradeOffer", "v1", options);
Debug.WriteLine(url);
string response = SteamWeb.Fetch(url, "POST", null, null, false);
dynamic json = JsonConvert.DeserializeObject(response);
if (json == null || json.success != "1")
{
return false;
}
return true;
}
If you are using jQuery then there is a very handy function to do this.
$.post( "http://api.example.com/get-some-value", { name: "John", time: "2pm" })
.done(function( data ) {
alert( "Data Loaded: " + data );
});
But be careful about cross domain ajax when calling it from JS.
EDIT
For the comment.
You have to include jQuery into your page and then you can call anything within the very useful and handy $( document ).ready() that jQuery supplies.
$(document).ready(function(){
$.post( "http://api.example.com/get-some-value", { name: "John", time: "2pm" })
.done(function( data ) {
alert( "Data Loaded: " + data );
});
})
UPDATE:
Try this:
$url = 'https://api.steampowered.com/IEconService/CancelTradeOffer/v1/';
$postData = array();
$postData['key'] = $STEAM_API_KEY;
$postData['tradeofferid'] = $TRADE_OFFER_ID;
$parameters=json_encode($postData);
$headers = array( "Accept-Encoding: gzip",
"Content-Type: application/json");
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $parameters);
$resultt = curl_exec($ch);
var_dump($resultt);
curl_close($ch);
Or use this as a function to POST values
function httpPost($url,$params)
{
$postData = '';
//create name value pairs seperated by &
foreach($params as $k => $v)
{
$postData .= $k . '='.$v.'&';
}
rtrim($postData, '&');
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_POST, count($postData));
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
$output=curl_exec($ch);
curl_close($ch);
return $output;
}
Final Answer:
PHP Curl Post, works OK :)
Please give credits to WD :)
$url = 'http://api.steampowered.com/IEconService/CancelTradeOffer/v1/';
$postData = array();
$postData['key'] = ""; // insert variable
$postData['tradeofferid'] = ""; // insert variable
$fields = '';
foreach($postData as $key => $value) {
$fields .= $key . '=' . $value . '&';
}
rtrim($fields, '&');
$post = curl_init();
curl_setopt($post, CURLOPT_URL, $url);
curl_setopt($post, CURLOPT_POST, count($postData));
curl_setopt($post, CURLOPT_POSTFIELDS, $fields);
curl_setopt($post, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($post);
var_dump($result);
curl_close($post);
jQuery Post, works OK :)
Please give credits to SRC :)
<script src="jquery-1.11.1.min.js"></script>
<script>
$(document).ready(function(){
$.post( "http://api.steampowered.com/IEconService/CancelTradeOffer/v1/", { key: "SteamApiKey", tradeofferid: "TradeOfferID" })
//This part does not work -- but is not needed to post data
//.done(function( data ) {
// alert( "Data Loaded: " + data );
//});
})
</script>
To Check Trade Offer status in PHP use:
//Check if trade offer was canceled
//Get File and avoid error if the server is down
$CheckTradeOfferID = ""; // add variable
$BotSteamApiKey = ""; // add variable
if (!$data = #file_get_contents("https://api.steampowered.com/IEconService/GetTradeOffer/v1/?key=".$BotSteamApiKey."&tradeofferid=".$CheckTradeOfferID."&format=json")) {
print 'Steam Api is Down';
} else {
$json=json_decode($data,true);
$TradeOffersResponse = $json['response'];
if (empty($TradeOffersResponse)) {
print "Trade Offer ID not found!!!";
}else{
$trade_offer_state = $json['response']['offer']['trade_offer_state'];
$TRANSLATE_Trade_Offer_State = "Unknown";
if($trade_offer_state == "1"){ $TRANSLATE_Trade_Offer_State = "Invalid"; }
if($trade_offer_state == "2"){ $TRANSLATE_Trade_Offer_State = "Trade Offer Sent"; }
if($trade_offer_state == "3"){ $TRANSLATE_Trade_Offer_State = "Trade Offer Accepted"; }
if($trade_offer_state == "4"){ $TRANSLATE_Trade_Offer_State = "The User Sent A Counter Offer"; }
if($trade_offer_state == "5"){ $TRANSLATE_Trade_Offer_State = "Trade Offer not accepted before the expiration date"; }
if($trade_offer_state == "6"){ $TRANSLATE_Trade_Offer_State = "The sender cancelled the offer"; }
if($trade_offer_state == "7"){ $TRANSLATE_Trade_Offer_State = "User Declined the Trade Offer"; }
if($trade_offer_state == "8"){ $TRANSLATE_Trade_Offer_State = "Some of the items in the offer are no longer available"; }
print $TRANSLATE_Trade_Offer_State;
}
}
I read this question and this one. They both said (a year ago) that recurring payments via the REST API was in the works. On my client's website, customers need to be able to pay either
in full (all at once — e.g., $1200 at check out)
in installments ($1200 over 6 months at $200 per month)
It is crucial that his website be notified when a customer pays. I have currently set this up for option #1:
app.get("/cart/checkout/paypal", isLoggedIn, isVerified, function (req, res) {
var user = req.user;
var paymentDetails = {
"intent": "sale",
"payer": { "payment_method": "paypal"},
"redirect_urls": {
"return_url": "http://localhost:5000/cart/checkout/success",
"cancel_url": "http://localhost:5000/cart"
},
"transactions": [
{ "amount": { "total": user.cart.finalPrice.toFixed(2), "currency": "USD"},
"description": "You are being billed for " + user.cart.finalPrice.toFixed(2)}
]
};
paypal.payment.create(paymentDetails, function (err, payment) {
if (err) console.log(err);
else {
if (payment.payer.payment_method === "paypal") {
req.session.paymentId = payment.id;
var redirectURL;
for (var i = 0; i < payment.links.length; i++) {
var link = payment.links[i];
if (link.method === "REDIRECT") redirectURL = link.href;
}
res.redirect(redirectURL);
}
}
})
})
Then, the "return_url" (/cart/checkout/success) grabs all the correct session info and my database processes it.
app.get("/cart/checkout/success", isLoggedIn, isVerified, function (req, res) {
var user = req.user,
paymentId = req.session.paymentId,
payerId = req.param("PayerID"),
details = { "payer_id": payerId };
...
Is there a similar setup for option #2 (recurring payments). If not, is there a way for PayPal to notify my server every time a user has paid an installment with the outstanding balance and amount paid/etc.?
Yes, there is now a way to do subscriptions within the new REST API. See the documentation.
OK, first you need to set the Client ID and secret you get from PayPal.
I have both a testing and live environment
All {xxx} are my private application variables
public function __construct()
{
$this->sandbox = {sandbox};
if($this->sandbox)
{
$this->host = 'https://api.sandbox.paypal.com';
$this->clientId = {clientIdSandbox};
$this->clientSecret = {clientSecretSandbox};
}
else
{
$this->host = 'https://api.paypal.com';
$this->clientId = {clientId};
$this->clientSecret = {clientSecret};
}
$this->get_access_token();
}
I then go and get the access token
private function get_access_token()
{
$curl = curl_init($this->host.'/v1/oauth2/token');
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_USERPWD, $this->clientId . ":" . $this->clientSecret);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, 'grant_type=client_credentials');
$response = curl_exec( $curl );
if (empty($response))
{
echo "NO RESPONSE for $url for function ".__FUNCTION__;
print_r(curl_getinfo($curl));
die(curl_error($curl));
curl_close($curl); // close cURL handler
}
else
{
$info = curl_getinfo($curl);
curl_close($curl); // close cURL handler
if($info['http_code'] != 200 && $info['http_code'] != 201 )
{
echo "Received error: " . $info['http_code']. "\n";
echo "Raw response:".$response."\n";
die();
}
}
$jsonResponse = json_decode( $response );
$this->token = $jsonResponse->access_token;
$this->expires = time()+$jsonResponse->expires_in;
}
This then stores the access data in the classes properties
You then need three more sections. Create the subscription template, then retrieve the agreement, then create the agreement for the client.
In this method I send over the data Name, Desc, Period, Interval and Price. However you can just fill in manually. This will create the subscription that you can now sell.
public function create_subscription($name, $desc, $period, $interval, $price)
{
$data = array(
'name' => $name,
'description' => $desc,
'type' => 'INFINITE',
'payment_definitions' => array(
0 => array (
'name' => 'Payment Definition-1',
'type' => 'REGULAR',
'frequency' => $period,
'frequency_interval' => $interval,
'amount' => array(
'value' => $price,
'currency' => 'EUR',
),
'cycles' => '0',
),
),
'merchant_preferences' => array(
'return_url'=>{return_url},
'cancel_url'=>{cancel_url},
'auto_bill_amount' => 'YES',
'initial_fail_amount_action' => 'CONTINUE',
'max_fail_attempts' => '0',
),
);
$data=json_encode($data);
$url = $this->host.'/v1/payments/billing-plans';
return $this->make_post_call($url, $data);
}
From the above method you will get in return an id, use that for the method below to collect the data of the subscription and store it
public function retrieve_agreement($id)
{
$url = $this->host.'/v1/payments/billing-agreements/'.$id;
return $this->make_get_call($url);
}
This method will allow you to allocate and agreement to a client.
You will need the id of the aggreement with some data for you to be able add to the description.
public function create_agreement($subId, $data, $product)
{
$paypalId = ($this->sandbox) ? $product->paypal_test_sub_id : $product->paypal_sub_id;
$startDate = date('c', strtotime('+10 MINUTE'));
$data = array (
'name'=>'Subscription for subscription::'.$subId,
'description'=>{company}.' Subscription - ' . $data . ' - '.$product->name.' - '.$product->price .'€',
'start_date'=>$startDate,
'plan'=>array(
'id'=>$paypalId,
),
'payer'=>array(
'payment_method'=>'paypal',
),
'override_merchant_preferences'=>array(
'return_url'=>{return_url}.$subId.'/',
'cancel_url'=>{cancel_url}.$subId.'/',
),
);
$data=json_encode($data);
$url = $this->host.'/v1/payments/billing-agreements';
$response = $this->make_post_call($url, $data);
header("location:".$response['links'][0]['href']);
//return $response;
}
The return_url is the url that the end user will be sent to to complete the aggreement. I than use that to pass to the method below
public function execute_agreement($token)
{
$data=json_encode('');
$url = $this->host.'/v1/payments/billing-agreements/'.$token.'/agreement-execute';
return $response = $this->make_post_call($url, $data);
}
You will then need to create a scheduled task to use the retrieve_agreement method and see if a subscription has been cancelled or not.
This is a brief explanation.
if you require more please let me know.
Get and Post
private function make_post_call($url, $postdata)
{
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
'Authorization: Bearer '.$this->token,
'Accept: application/json',
'Content-Type: application/json'
));
curl_setopt($curl, CURLOPT_POSTFIELDS, $postdata);
$response = curl_exec( $curl );
if (empty($response))
{
echo "NO RESPONSE for $url for function ".__FUNCTION__;
print_r(curl_getinfo($curl));
die(curl_error($curl));
curl_close($curl); // close cURL handler
}
else
{
$info = curl_getinfo($curl);
curl_close($curl); // close cURL handler
if($info['http_code'] != 200 && $info['http_code'] != 201 )
{
echo "Received error: " . $info['http_code']. "\n";
echo "Raw response:".$response."\n";
die();
}
}
$jsonResponse = json_decode($response, TRUE);
return $jsonResponse;
}
private function make_get_call($url)
{
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_POST, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
'Authorization: Bearer '.$this->token,
'Accept: application/json',
'Content-Type: application/json'
));
$response = curl_exec( $curl );
if (empty($response))
{
echo "NO RESPONSE for $url for function ".__FUNCTION__;
print_r(curl_getinfo($curl));
die(curl_error($curl));
curl_close($curl); // close cURL handler
}
else
{
$info = curl_getinfo($curl);
//echo "Time took: " . $info['total_time']*1000 . "ms\n";
curl_close($curl); // close cURL handler
if($info['http_code'] != 200 && $info['http_code'] != 201 )
{
echo "Received error: " . $info['http_code']. "\n";
echo "Raw response:".$response."\n";
die();
}
}
$jsonResponse = json_decode($response, TRUE);
return $jsonResponse;
}
I would recommend staying away from the REST API for now. It's just not complete yet, and the Classic API gives you so much more flexibility.
I'd go with Express Checkout with Recurring Payments, and then you'll want to use Instant Payment Notification (IPN) to handle processing payments, canceled profiles, etc.
IPN notifications will actually be triggered for any transaction that ever hits your account, so you can automate the processing of payments, refunds, disputes, subscriptions, etc. You can update your database, send email notifications, or anything else you need to automate based on these transaction types.
IPN is one of the most valuable tools PayPal provides, yet it's also one of the most underutilized.