I need to dinamically generate PayPal links with customized payment amounts and recipients. I don't know much about PayPal's way of handling this kind of stuff, and I actually wonder whether it is possible. I have a table with user's email address and payment value and, on the last column, I need to put that link that, clicked, takes to the PayPal's page where, after security checks and everything, the amount of money by me given can be directly transferred to the email address of the user.
Is it possible to do something like this? I'm working in PHP.
Thanks.
please, read documentation - it's all very well described. you will need to register at https://developer.paypal.com/; refer to https://www.paypal.com/documentation for more information.
I believe paypal standard payments would suffice your needs. read this https://cms.paypal.com/cms_content/US/en_US/files/developer/PP_WebsitePaymentsStandard_IntegrationGuide.pdf -- it has all sorts of samples.
when we integrate paypal, we usually do like this: user picks goods to purchase, then proceeds to checkout. at this point, form is created as per documentation, and that form includes merchant account to use for processing the payment. in the form you also specify: notify_url and cancel_url, so you would get notification from the paypal as to what happened and to which account. that should address your needs.
sample form:
<form action="https://www.'.$this->isSandbox().'paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="business" value="'.$this->api->getConfig('billing/paypal/merchant').'">
<input type="hidden" name="cmd" value="_xclick">
<input type="hidden" name="rm" value="2">
<input type="hidden" name="item_name" value="'.addslashes($_GET['descr']).'">
<input type="hidden" name="item_number" value="'.addslashes($_GET['id']).'">
<input type="hidden" name="amount" value="'.addslashes($_GET['amount']).'">
<input type="hidden" name="no_shipping" value="1">
<input type="hidden" name="notify_url" value="http://' . $_SERVER['HTTP_HOST'].$this->api->getDestinationURL('/ppproxy',array('ipn'=>$_GET['id'])).'">
<input type="hidden" name="cancel_return" value="http://' . $_SERVER['HTTP_HOST'].$this->api->getDestinationURL('/ppproxy',array('cancel'=>$_GET['id'])).'">
<input type="hidden" name="return" value="http://' . $_SERVER['HTTP_HOST'].$this->api->getDestinationURL('/ppproxy',array('success'=>$_GET['id'])).'">
<input type="hidden" name="currency_code" value="'.addslashes($_GET['currency']).'">
</form>
sample callback handler:
....
if($_POST){
// might be getting adta from paypal! better log!
foreach ($_POST as $key=>$value) $postdata.=$key."=".urlencode($value)."&";
$postdata.="cmd=_notify-validate";
$curl = curl_init("https://www.".$this->isSandbox()."paypal.com/cgi-bin/webscr");
curl_setopt ($curl, CURLOPT_HEADER, 0);
curl_setopt ($curl, CURLOPT_POST, 1);
curl_setopt ($curl, CURLOPT_POSTFIELDS, $postdata);
curl_setopt ($curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt ($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($curl, CURLOPT_SSL_VERIFYHOST, 1);
$response = curl_exec ($curl);
curl_close ($curl);
$this->api->logger->logLine($response);
if ($response != "VERIFIED"){
$this->api->logger->logLine('FAILED: post='.print_r($_POST,true));
exit;
}else{
$this->api->logger->logLine('VERIFIED: post='.print_r($_POST,true));
}
if($_POST['payment_status']=='Completed' and $_POST['txn_type']!='reversal')return true; // or perform your desired actions
exit;
}
excerpt from agiletoolkit.org paypal billing addon
Related
I am using a third party payment service.
<form name="form1" method="post" action="https://exampledomain.com/postpayment.php">
<input type="hidden" name="CRESecureID" value="1"/>
<input type="hidden" name="trans_type" value=" 2"/>
<input type="hidden" name="content_template_url" value="https://example.com/enterpaymentdetails.html"/>
<input type="hidden" name="allowed_types" value=" 3"/>
<input type="hidden" name="total_amt" value="$payment->amount"/>
<input type="hidden" name="collect_total_amt" value="$payment->total"/>
<input type="hidden" name="sess_id" value="e91dd8af53j35k072s0bubjtn7"/>
<input type="hidden" name="sess_name" value="session"/>
<input type="hidden" name="return_url" value="https://example.com/return.html"/>
<p><label> <input type="submit" name="submit" value="submit"/> </label></p>
How can I correctly send these variables to an external URL? Should I do it in the controller? An example would be helpful.
Thanks
Best method to implement this is:
Post form data to one of your own URL, then post this data to the required external URL using Guzzle client or curl request.
This approach will help you to track the response from the external URL and manipulate or use it if required.
Hope this helps.
You can do it on controller, a good approach will be to get these variables on controller, pass them to repository/service layer, perform all the validation checks and once everything is good, send them via CURL POST.
You can use Request to validate the form fields. Validate, process and send.
Here is the code to send data via CURL post
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "URL_OF_API");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 100);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postFieldsArray);
$data = curl_exec($ch);
curl_close($ch);
Try adding double forward-slash in your form action
E.g. <form action="{{'//newsite.com/whatever'}}" >
That is all.
I have a question regarding php button. I want to make a dynamic buy now button with paypal. A button that i can pass my custom variables into. The only way i know how to that is through a paypal form.
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_xclick">
<input type="hidden" name="business" value="paid#yourdomain.com">
<input type="hidden" name="item_name" value="my product">
<input type="hidden" name="item_number" value="12345">
<input type="hidden" name="amount" value="9.99">
<input type="hidden" name="no_note" value="1">
<input type="hidden" name="currency_code" value="USD">
<input type="hidden" name="bn" value="PP-BuyNowBF">
<input type="image" src="https://www.paypal.com/en_US/i/btn/x-click-but23.gif" border="0" name="submit" alt="Make payments with PayPal - it's fast, free and secure!">
<img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">
</form>
But the above form's amount value can easily be tampered with. So instead of this i want to have just a button in html, and have everything process through a php file. When a user clicked the button, the process of price calculation will happen in the php file, and then redirect the user to paypal, where they can pay for the item. This way the price can't be tampered with. Can someone tell me if it's possible to do it that way? or i have to dynamically encrypt the button using openssl? or there's another way?
Instead of posting directly to PayPal, you can collect all the data server side, and use cURL to post the data to PayPal. The form would look more like:
<form action="confirm.php" method="post">
<input type="hidden" name="business" value="paid#yourdomain.com">
<input type="hidden" name="item_number" value="12345">
<input type="image" src="https://www.paypal.com/en_US/i/btn/x-click-but23.gif" border="0" name="submit" alt="Make payments with PayPal - it's fast, free and secure!">
<img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">
</form>
Then confirm.php would do a handful of things. Lookup the price, calculate the total, etc.
<?php
$bizName = isset($_POST['business']):$_POST['business']:"";
$itemNumber = isset($_POST['item_number'])?intval($_POST['item_number']):"";
// Lookup details for the Item, purchase, and collect them into an array maybe
$itemDetails = array(
"cmd" => "_xclick",
"amount" => $itemPrice, // Get from DB
"no_note" => 1,
"currency_code" => "USD",
"bn" => "PP-BuyNowBF",
"business" => $bizName,
"item_name" => $itemName, // Get from DB
"item_number" => $itemNumber
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://www.paypal.com/cgi-bin/webscr");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($itemDetails));
// receive server response ...
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$svr_out = curl_exec ($ch);
curl_close ($ch);
// Do something with $svr_out, maybe display it, or if it's a redirect, redirect the user in turn.
?>
This is untested and is more of a template to get you started. I am sure your site is more complex and you could then build off of this. It is just an example of something you could do.
So I'm doing a site selling membership plan (monthly billing)
User will need to input a registration form (name, ICNumber, etc which may be different to the paypal used by this user)
Upon clicking 'next/submit', system will save the posted data inside a session, and will display it again in another page so it's like a confirmation page.
Inside the confirmation page,
<form method='post' action="https://www.sandbox.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_ext-enter">
<input type="hidden" name="redirect_cmd" value="_xclick-subscriptions">
<input type="hidden" name="item_number" value="<?php echo $plan[0]['id'];?>">
<input type="hidden" name="no_note" value="1">
<input type="hidden" name="item_name" value="<?php echo $plan[0]['plan_name'];?>">
<input type="hidden" name="currency_code" value="USD">
<input type="hidden" name="a3" value="<?php echo $plan[0]['plan_price'];?>">
<!--change p3 value 1M=1month, 1D(t3) = 1 day-->
<input type="hidden" name="p3" value="1">
<!--change value=M as month-->
<input type="hidden" name="t3" value="M">
<input type="hidden" name="src" value="1">
<input type="hidden" name="sra" value="1">
<!--here change to your seller sandbox account-->
<input type="hidden" name="business" value="seller-facilitator#test.com">
<input type="hidden" name="return" value="<?php echo base_url(); ?>signup/success">
<input type="hidden" name="notify_url" value="<?php echo base_url(); ?>payment/subscribe" />
<input type="hidden" name="rm" value="2">
<!--and echoing out bunch of data (name, ICNumber, phone number etc) posted from previous page,, which has been stored into a session array-->
So, user can do the payment, the money has come into the seller account, and buyer's balance has been deducted.
So my questions:
1. where should I put my ipn link? Is it inside 'notify_url' AND 'return' url?
2. If my understanding is correct, we 'should' put a link under our profile>selling preference>IPN so I have updated my profile, and put mydomain.com/controller/ipncode (I'm using codeigniter)
3. I turned on auto-return, but even on live, the site won't autoreturn. This is minor issue; my return page contains a simple 'thank you' page. Now, since the txn_type when the payment is made is "subscr_signup" therefore, NO txn_id, NO payment_status UNTIL the txn_type changes to 'subcr_payment', and this may occur long AFTER or BEFORE the user returns to our main site and surfing. So I need to save the registration data (as the user submitted) for his login. After payment, user can directly login, no matter what the payment outcome will be as the end, the seller and buyer will have to meet up for transaction (this is a rental dvd site, so buyer must go down to the retail shop and collect the dvds he books through the site).
But to make the life of the seller easier, it'd better if I can update the membership_status to 'active' IF the payment_status is verified and completed.
So far, my IPN code is this
$req = 'cmd=_notify-validate';
$fullipnA = array();
$url ='https://www.sandbox.paypal.com/cgi-bin/webscr';
foreach ($_POST as $key => $value)
{
$fullipnA[$key] = $value;
$encodedvalue = urlencode(stripslashes($value));
$req .= "&$key=$encodedvalue";
}
//$fullipn = Array2Str(" : ", "\n", $fullipnA);
$curl_result=$curl_err='';
$fp = curl_init();
curl_setopt($fp, CURLOPT_URL,$url);
curl_setopt($fp, CURLOPT_RETURNTRANSFER,1);
curl_setopt($fp, CURLOPT_POST, 1);
curl_setopt($fp, CURLOPT_POSTFIELDS, $req);
curl_setopt($fp, CURLOPT_HTTPHEADER, array("Content-Type: application/x-www-form-urlencoded", "Content-Length: " . strlen($req)));
curl_setopt($fp, CURLOPT_HEADER , 0);
curl_setopt($fp, CURLOPT_VERBOSE, 1);
curl_setopt($fp, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($fp, CURLOPT_TIMEOUT, 30);
$response = curl_exec($fp);
$curl_err = curl_error($fp);
curl_close($fp);
$custom=$this->session->userdata('registration'); //this contains the submitted registration data in a session array
$this->load->model('signup_model');
//'VERIFIED' only qualifies if the txn_type=subscr_payment(seller has received the money)
//if payment status is verified, then update DB/activate the account
if (strcmp ($response, "VERIFIED") == 0) {
if($_POST['payment_status']=='Completed') {
//this is to get customer_id based on the ICNumber posted upon registration (which is stored inside a session)
$cid=$this->signup_model->getCustomerID($custom['nric']);
//this is to update membership_status to active if payment is verified and completed
$this->signup_model->updatePlanStatus($cid[0]['id'],1);
$this->signup_model->test('payment status complete and verified', $cid);
} else {
$cid=$this->signup_model->getCustomerID($custom['nric']);
$this->signup_model->updatePlanStatus($cid[0]['id'],0);
$this->signup_model->test('payment status NOT complete but verified', $cid);
}
}
//'Invalid' if paypal can't process the payment
//update account status as pending
if (strcmp ($response, "INVALID") == 0) {
$cid=$this->signup_model->getCustomerID($custom['nric']);
$this->signup_model->updatePlanStatus($cid[0]['id'],0);
$this->signup_model->test('payment status NOT verified', $cid);
}
I'm also confused WHERE to put the sql syntax to insert the registration data into the DB.
Currently because I don't know how to use IPN properly, the return url (which is a thank you page), I put mysql db insert there. So, when user click 'return to main site', system will insert the registration details first, with membership_status = 0 (pending), this is to allow user to login directly to use the site.
Please guide me how should I put this all together.
Thanks!
I have built an application, that sends a notification url with the GUID of the logged in user to PayPal, and upon completion of purchase, the url is called, and after verification, the user database entry updates the column purchased from 0 to 1.
The user then clicks the return to app button, and the premium functionality displays based on the purchased column.
I have been testing this over the last few months in the sandbox. 100% of the times tested (including after this issue), the premium tab displays after purchase completion.
Client is thrilled, and gives the go ahead to move to production. I have set up IPN with the exact same URL, I have changed literally nothing except switching from www.sandbox.paypal.com to www.paypal.com and changing the account listed from the sandbox business to the personal business.
Ths issue is, the button now doesn't show up, until, you refresh the screen. Clicking the "return to app" button, which previously was working as expected, now doesn't display the premium tab. Once I click refresh - it then shows up. If I switch everything back to the sandbox settings, boom - it works just fine again.
Here is the BuyNow button code with production account:
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" id="buynowForm" target="_top">
<input type="hidden" name="cmd" value="_xclick">
<input type="hidden" name="business" value="ACCOUNT EMAIL">
<input type="hidden" name="lc" value="US">
<input type="hidden" name="item_name" value="Product">
<input type="hidden" name="amount" value="10.00">
<input type="hidden" name="currency_code" value="USD">
<input type="hidden" name="button_subtype" value="services">
<input type="hidden" name="no_note" value="1">
<input type="hidden" name="no_shipping" value="1">
<input type='hidden' name='notify_url' value='http://app.com/purchase/<?php echo $data[0]['uid'] ?>'>
<input type='hidden' name='return' value='http://app.com/'>
<input type="hidden" name="rm" value="1">
<input type="hidden" name="cbt" value="Return to Product Plus">
<input type="hidden" name="bn" value="PP-BuyNowBF:btn_buynowCC_LG.gif:NonHosted">
<input type="submit" class="hidden-print visible-print" border="0" name="buysubmit" value="Click For Product Plus" alt="Click for Product Plus">
<img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">
And here is the processing route called above:
$app->post('/purchase/:uid', function ($uid) use ($app) {
$request = Slim::getInstance()->request();
$inputs = json_decode($request->getBody());
$db_conn = conn();
$req = 'cmd=_notify-validate';
foreach ($_POST as $key => $value)
{
if (get_magic_quotes_gpc())
{
$_POST[$key] = stripslashes($value);
$value = stripslashes($value);
}
$value = urlencode($value);
$req .= "&$key=$value";
}
$url = "https://www.paypal.com/cgi-bin/webscr";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_TIMEOUT, 3);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
$result = curl_exec($ch);
curl_close($ch);
if (strcmp ($result, "VERIFIED") == 0)
{
$sql_st = 'UPDATE `user_data` SET `purchased` = 1 WHERE uid=:uid';
$sql = $db_conn->prepare($sql_st);
if ($sql->execute(array('uid'=>$uid))) {
$data = array('status' => "Ok");
} else {
$data = array('status' => print_r(mysql_error()));
}
}
else
{
// Did Not Process IPN Properly
}
});
REALLY hoping this is just something incredibly dumb on my part. Any help/guidance is appreciated.
Essentially the solution here is one of two options -
Build a secondary method of completion - in other words, the IPN is not the first line of defense for a purchased upgrade to software. Everything on my end is working, however the timing of the IPN (notify_url) call is too slow to make instant upgrades not exactly instant. Return them to a page that performs the upgrade then redirects.
Store the upgraded features behind a different route - this was PayPal's suggestion. Essentially, have app.com/basic and app.com/upgraded. This isn't really ideal, nor would I suggest it as a permanent solution.
Summed up - this is a known issue with PayPal. The sandbox and production workflows are basically different - not by function or API, but in usage - the production level account is getting hit more, and the time it takes to process the notifications are much slower.
Hope this helps someone.
I've been looking at several examples of utilizing paypal's API to develop a simple script to be able to use it to checkout, and in each one I keep running across cURL, and I really don't understand it at all. Is it just different PHP functions from a library, or something all together different? More importantly, can I copy and paste cURL commands into my document and it will work, or do I need to download something to get it work on my local server and shared hosting server where my live site will go? Lastly, where can I go to learn this? I've done some searching but haven't found any solid material on it. I really appreciate any help.
A basic understanding of cURL example from PHP Manual
<?php
$ch = curl_init("http://www.example.com/");
$fp = fopen("example_homepage.txt", "w");
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);
fclose($fp);
?>
PHP Manual
cURL with PayPal API . [Found it on the internet]
<?php
$ch = curl_init();
$clientId = "myId";
$secret = "mySecret";
curl_setopt($ch, CURLOPT_URL, "https://api.sandbox.paypal.com/v1/oauth2/token");
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERPWD, $clientId.":".$secret);
curl_setopt($ch, CURLOPT_POSTFIELDS, "grant_type=client_credentials");
$result = curl_exec($ch);
if(empty($result))die("Error: No response.");
else
{
$json = json_decode($result);
print_r($json->access_token);
}
curl_close($ch);
?>
You can use a simple form to the checkout. To use via cURL you need to enable cURL and use it in your PHP code.
The following is the simple way.
<form action="https://paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="business" value="sandy_1314264698_biz#gmail.com ">
<input type="hidden" name="cmd" value="_xclick-subscriptions">
<input type="hidden" name="item_name" value="sand bag">
<input type="hidden" name="item_number" value="1234">
<input type="hidden" name="currency_code" value="USD">
<input type="hidden" name="notify_url" value="http://abc.com/xyz.php">
<input type="hidden" name="return" value="http://google.com">
<!-- Display the payment button. -->
<input type="image" name="submit" border="0" src="btn_subscribe_LG.gif" alt="PayPal - The safer, easier way to pay online">
<img alt="" border="0" width="1" height="1" src="https://www.paypal.com/en_US/i/scr/pixel.gif" >