PayPal REST API with PHP results ERROR - php

Im using PayPal REST API with PHP, I have created a rest app in sandbox and everything as in documentation.
but it returns error
Got Http response code 401 when accessing https://api.sandbox.paypal.com/v1/oauth2/token.
not sure where Im going wrong on this, tried many other sample codes using rest api but same error everywhere.
can some one help me on this?
code is here
define('CLIENT_ID', 'MY CLIENT ID'); //your PayPal client ID
define('CLIENT_SECRET', 'MY SECRET'); //PayPal Secret
define('RETURN_URL', 'http://domain.com/order_process.php'); //return URL where PayPal redirects user
define('CANCEL_URL', 'http://domain.com/payment_cancel.html'); //cancel URL
define('PP_CURRENCY', 'USD'); //Currency code
define('PP_CONFIG_PATH', ''); //PayPal config path (sdk_config.ini)
include_once "vendor/autoload.php"; //include PayPal SDK
include_once "functions.inc.php"; //our PayPal functions
$item_name = 'Test Product'; //get item code
$item_code = 'sku123'; //get item code
$item_price = '10'; //get item price
$item_qty = '1'; //get quantity
/*
Note: DO NOT rely on item_price you get from products page, in production mode get only "item code"
from the products page and then fetch its actual price from Database.
Example :
$results = $mysqli->query("SELECT item_name, item_price FROM products WHERE item_code= '$item_code'");
while($row = $results->fetch_object()) {
$item_name = $row->item_name;
$item_price = item_price ;
}
*/
//set array of items you are selling, single or multiple
$items = array(
array('name'=> $item_name, 'quantity'=> $item_qty, 'price'=> $item_price, 'sku'=> $item_code, 'currency'=>PP_CURRENCY)
);
//calculate total amount of all quantity.
$total_amount = ($item_qty * $item_price);
try{ // try a payment request
//if payment method is paypal
$result = create_paypal_payment($total_amount, PP_CURRENCY, '', $items, RETURN_URL, CANCEL_URL);
//if payment method was PayPal, we need to redirect user to PayPal approval URL
if($result->state == "created" && $result->payer->payment_method == "paypal"){
$_SESSION["payment_id"] = $result->id; //set payment id for later use, we need this to execute payment
header("location: ". $result->links[1]->href); //after success redirect user to approval URL
exit();
}
}catch(PPConnectionException $ex) {
echo parseApiError($ex->getData());
} catch (Exception $ex) {
echo $ex->getMessage();
}

Related

PHP: Stripe API does not display any error when entering a bad card number

It seems I am missing something when trying to handle some errors with Stripe in test mode with PHP.
Payment are successful when I enter a test card number like 4242424242424242 (for VISA) but I have no error and nothing is recorded when I enter a bad card number.
It is like if the button "Pay" was not working although it displays an error message if I use a real correct card number in test mode.
Does someone know what am I doing wrong here ? Thanks.
Here is the PHP code :
// Check whether stripe token is not empty
if(!empty($_POST['stripeToken'])){
// Retrieve stripe token, card and user info from the submitted form data
$token = $_POST['stripeToken'];
$name = $_POST['name'];
$email = $_POST['email'];
$card_number = $_POST['card_number'];
$card_exp_month = $_POST['card_exp_month'];
$card_exp_year = $_POST['card_exp_year'];
$card_cvc = $_POST['card_cvc'];
$itemPrice = $_POST['itemPrice'];
$itemNumber = $_POST['itemNumber'];
$Ticket_number = $_POST['Ticket_number'];
// Include Stripe PHP library
require_once 'stripe-php/init.php';
// Set API key
\Stripe\Stripe::setApiKey(STRIPE_API_KEY);
// Add customer to stripe
$customer = \Stripe\Customer::create(array(
'email' => $email,
'source' => $token
));
// Unique order ID
$orderID = strtoupper(str_replace('.','',uniqid('', true)));
// Convert price to cents
$itemPrice = ($itemPrice*100);
// Charge a credit or a debit card
$charge = \Stripe\Charge::create(array(
'customer' => $customer->id,
'amount' => $itemPrice,
'currency' => $currency,
'description' => $itemName,
'metadata' => array(
'order_id' => $orderID
)
));
// Retrieve charge details
$chargeJson = $charge->jsonSerialize();
// Check whether the charge is successful
if($chargeJson['amount_refunded'] == 0 && empty($chargeJson['failure_code']) && $chargeJson['paid'] == 1 && $chargeJson['captured'] == 1){
// Order details
$transactionID = $chargeJson['balance_transaction'];
$paidAmount = $chargeJson['amount'];
$paidCurrency = $chargeJson['currency'];
$payment_status = $chargeJson['status'];
// Include database connection file
include_once 'dbConnect.php';
$itemPrice = ($itemPrice/100);
$paidAmount = ($paidAmount/100);
// Insert tansaction data into the database
$sql = "INSERT INTO orders(name,email,card_number,card_exp_month,card_exp_year,item_name,item_number,item_price,item_price_currency,paid_amount,paid_amount_currency,txn_id,payment_status,created,modified) VALUES('".$name."','".$email."','".$card_number."','".$card_exp_month."','".$card_exp_year."','".$itemName."','".$itemNumber."','".$itemPrice."','".$currency."','".$paidAmount."','".$paidCurrency."','".$transactionID."','".$payment_status."',NOW(),NOW())";
$insert = $db->query($sql);
$payment_id = $db->insert_id;
// If the order is successful
if($payment_status == 'succeeded'){
$ordStatus = 'success';
$statusMsg = '';
}else{
$statusMsg = "Your Payment has Failed!";
}
}else{
print '<pre>';print_r($chargeJson);
$statusMsg = "Transaction has been failed!";
}
}else{
$statusMsg = "Error on form submission.";
}
?>
Thank you for your answers but in fact it was a dummy mistake : I did not declare an id to display my error. I had to add the following code in my form :
<p id="payment-status" role="alert"></p>

paypal payment gateway integration

I am integrating paypal payment gateway in one of site.After successful payment i am redirecting it to success.php file. In success.php file i have included all the insert parameters and a success message. It is redirecting to success.php file properly after making payment but showing payment failed message and no data is inserting to the database. following is my success.php page code
<?php
include 'dbConfig.php';
//Get payment information from PayPal
$item_number = $_GET['item_number'];
$txn_id = $_GET['tx'];
$payment_gross = $_GET['amt'];
$currency_code = $_GET['cc'];
$payment_status = $_GET['st'];
//Get product price from database
$productResult = $db->query("SELECT price FROM products WHERE id = = '".$item_number."'");
$productRow = $productResult->fetch_assoc();
$productPrice = $productRow['price'];
if(!empty($txn_id) && $payment_gross == $productPrice){
//Check if payment data exists with the same TXN ID.
$prevPaymentResult = $db->query("SELECT payment_id FROM payments WHERE txn_id = '".$txn_id."'");
if($prevPaymentResult->num_rows > 0){
$paymentRow = $prevPaymentResult->fetch_assoc();
$last_insert_id = $paymentRow['payment_id'];
}else{
//Insert tansaction data into the database
$insert = $db->query("INSERT INTO payments(item_number,txn_id,payment_gross,currency_code,payment_status) VALUES('".$item_number."','".$txn_id."','".$payment_gross."','".$currency_code."','".$payment_status."')");
$last_insert_id = $db->insert_id;
}
?>
<h1>Your payment has been successful.</h1>
<h1>Your Payment ID - <?php echo $last_insert_id; ?></h1>
<?php }else{ ?>
<h1>Your payment has failed.</h1>
<?php } ?>
what i am doing wrong?
As suggested by Van Hoa, paypal does not send payment information as parameters when you redirect a user to your success page. PayPal will only send back a token and a payer ID.
When redirecting the buyer back to your website from paypal.com,
PayPal appends the Express Checkout transaction token and the unique
PayPal buyer ID as GET parameters to your RETURN URL;
these GET parameters are named token and PayerID.
PayPal docs (emphasis added)
You can use the returned token to get the payment details using GetExpressCheckoutDetails and passing it the token you get back from PayPal.

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

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

This payment request must be authorized by the sender - Paypal

Ok, here is what I did:
Created a PayRequest
SetPaymentOptions - https://developer.paypal.com/webapps/developer/docs/classic/api/adaptive-payments/SetPaymentOptions_API_Operation/
ExecutePayment - "This payment request must be authorized by the sender". I have ran out of idea on why am I not able to execute the payment. From what I understand, once I execute the payment successfully, I will be given a payKey which I shall use this to redirect user to paypal. https://developer.paypal.com/webapps/developer/docs/classic/api/adaptive-payments/ExecutePayment_API_Operation/
Attached are the source codes that I used. The values are all hardcoded. I have tried my best to look through at similar questions, and it makes no sense to me as it contradicts what I understand. Some answers were pointing out that the buyer needs to approve the payment first before you executePayment.
I just want to see the details of all items when I reach the paypal login page.
//1. Obtain endpoint. For live, no need sandbox?
$endPoint = "https://svcs.sandbox.paypal.com/AdaptivePayments/Pay";
//2. Format the HTTP headers needed to make the call.
$appID = "xxx"; //Sandbox test AppID:
$username = "xxx;
$password = "xxx";
$signature = "xxx";
$paypalHeaders = array(
"X-PAYPAL-SECURITY-USERID :" . $username,
"X-PAYPAL-SECURITY-PASSWORD :" . $password,
"X-PAYPAL-SECURITY-SIGNATURE :" . $signature,
"X-PAYPAL-APPLICATION-ID :" . $appID,
"X-PAYPAL-REQUEST-DATA-FORMAT : JSON",
"X-PAYPAL-RESPONSE-DATA-FORMAT : JSON"
);
$data = array();
$data['actionType'] = "CREATE"; //PAY
$data['currencyCode'] = "SGD";
$receiver['amount'] = $orderTotal;
$receiver['email'] = $receiverEmail;
$data['receiverList'] = array();
$data['receiverList']['receiver'][] = $receiver;
$data['returnUrl'] = $returnURL;
$data['cancelUrl'] = $cancleURL;
$requestEnvelope = array();
$requestEnvelope['errorLanguage'] = "en_US";
$data['requestEnvelope'] = $requestEnvelope;
//I omitted the POST call
//print_r($returnedData);
$payKey = $returnedData->payKey;
$paymentStatus = $returnedData->paymentExecStatus;
/*
* Set payment options
*/
$endPoint = "https://svcs.sandbox.paypal.com/AdaptivePayments/SetPaymentOptions";
//paymentDetailsData
$paymentDetailsData = array();
//set payKey
echo "payKey: " . $payKey;
$paymentDetailsData['payKey'] = $payKey;
//displayOptions
$displayOptions['businessName'] = "My Business";
$paymentDetailsData['displayOptions'] = $displayOptions;
//senderOptions
$senderOptions = array();
$senderOptions['requireShippingAddressSelection'] = true; //set to true if courier is chosen
$senderOptions['shippingAddress']['addresseeName'] = "Ny Name";
$senderOptions['shippingAddress']['street1'] = "Address 1Avenue 3";
$senderOptions['shippingAddress']['street2'] = "#xx-112";
$senderOptions['shippingAddress']['city'] = "Singapore";
$senderOptions['shippingAddress']['state'] = "Singapore";
$senderOptions['shippingAddress']['zip'] = "123456";
$senderOptions['shippingAddress']['country'] = "Singapore";
$paymentDetailsData['senderOptions'] = $senderOptions;
//item
$item = array();
$item['name'] = "Korea";
$item['itemPrice'] = 11;
//there is still price, and itemcount
//invoiceData
$invoiceData = array();
$invoiceData['item'] = $item;
//receiverOptions
$receiverOptions = array();
$receiverOptions['description'] = "Product description.";
$receiverOptions['invoiceData'] = $invoiceData;
$paypalEmail = "test#test.com"; //I may need to change this
$receiver['email'] = $paypalEmail;
$receiverOptions['receiver'] = $receiver;
$paymentDetailsData['receiverOptions'] = $receiverOptions;
//requestEnvelope. I have set the request envelope above. It is the same. Can still be used.
$paymentDetailsData['requestEnvelope'] = $requestEnvelope;
makePaypalCall($endPoint, $paypalHeaders, $paymentDetailsData);
/*
* Get payment options. I can see the result of get payment options correctly,
*/
echo "GETTING PAYMENT OPTIONS";
$endPoint = "https://svcs.sandbox.paypal.com/AdaptivePayments/GetPaymentOptions";
$getPaymentData['payKey'] = $payKey;
$getPaymentData['requestEnvelope'] = $requestEnvelope;
makePaypalCall($endPoint, $paypalHeaders, $getPaymentData);
$endPoint = "https://svcs.sandbox.paypal.com/AdaptivePayments/ExecutePayment";
/*
* ExecutePayment. Ok, I get the error here. This payment request must be authorized by the sender
*/
$executePaymentData = array();
echo "paykey: " . $payKey;
$executePaymentData['payKey'] = $payKey;
//$executePaymentData['actionType'] = "PAY";
$executePaymentData['requestEnvelope'] = $requestEnvelope;
I hope I understand you correctly.
To me it seems like you are skipping the step where the user needs to authorize the payment. When you do a Pay (Create) operation you should see get a RedirectURL in the response from PayPal. You need to redirect the user to this URL for them to authorize the payment on PayPal.
Once they have approved the payment, then you'll be able to execute the payment.
Your steps need to change to:
Create PayRequest
Set PaymentOptions
Redirect to PayPal (RedirectURL from the PayRequest response) for user authorization
If authorized, ExecutePayment
PayPal hints at this on the Pay API operation page
URL to redirect the sender's browser to after the sender has logged into PayPal and approved a payment; it is always required but only used if a payment requires explicit approval
After the step 3, the user will be returned to the URL your provided in $data['returnUrl'] = $returnURL;
I am using Delayed Chained Payment and often i end up with this error "This payment request must be authorized by the sender". Actually it was due to a small mistake in the logic.
wrong procedure (# step 3)
generate a payKey successfully
save it to database
refresh the page for some reason which results in generating new payKey (this new payKey doesn't update to database)
payRequest = pay();
.....
if(empty(db_record)) {
.....
db_record->payKey = payRequest->payKey;
db_record->save();
}
paid with new payKey ( ie. payment approved by sender)
trying to execute payment with payKey from database (which is indeed old one. That payKey was not used to make payment)
Solution
update database with last payKey which used for making payment by getting approval of sender
step 3 should be like
if(empty(db_record) || is_expired(db_record->payKey)) {
payRequest = pay();
.....
.....
db_record->payKey = payRequest->payKey;
db_record->save();
}

Trouble getting output from API

I'm currently building a site that will offer services that customers can pay for in Dogecoin. I am using DogeAPI and these example checkout scripts to try and build my checkout pages.
The problem is I can't get the address ($new_address) to echo to the page. When I run the script all that shows up is "Please pay 1000 DOGE to to receive your item. It may take up to 10 minutes to confirm your payment." When I log into my dashboard on DogeAPI, it doesn't show that any addresses were created.
I have a feeling that I need some sort of code that will wait until file_get_ contents() is finished and then start the JSON decoding. My code is below.
NOTE: I do have the API key in my code, I just obviously removed it before posting the code here.
//set to your API_KEY
$api_key = 'MY API HERE';
//set this to your users id
//must be alphanumeric only
$user_id = 'test123';
//set this to the amount the item costs
$amount_doge = '1000';
//send a request to the API to make a new payment address
//put info about the request in
$response = file_get_contents("https://www.dogeapi.com/wow/?api_key=$api_key&a=get_new_address&address_label=$user_id");
if($response !== 'Bad Query' && $response !== '') {
$new_address = json_decode($response);
//insert the new pending payment
mysql_query("INSERT INTO `api_payments`
(`payment_label`,`payment_address`,`paid`,`amount`)
VALUES ('$user_id', '$new_address', '0', '$amount_doge')");
//give them the address or echo a widget here
//for this example we will just echo an address
echo "Please pay $amount_doge DOGE to $response to receive your item. It may take up to 10 minutes to confirm your payment.";
} else {
echo 'There was a problem processing your order.';
}

Categories