Checkout-PHP-SDK and createOrder connection issue - php

Trying to implement the Checkout-PHP-SDK paypal API to createOrder JS call.As far as I understand I have to send the data from php file to js approval form. But I am getting an error when I press the "PayPal Pay" button.
The JS codes are like below :
<div id="paypal-button-container"></div>
<script>
function loadAsync(url, callback) {
var s = document.createElement('script');
s.setAttribute('src', url); s.onload = callback;
document.head.insertBefore(s, document.head.firstElementChild);
}
// Usage -- callback is inlined here, but could be a named function
loadAsync('https://www.paypal.com/sdk/js?client-id=AQgUM6x3URK1A-rcNIq56covuc0CYGv3pb5sYeL6-cqsO1HYV2CV6h4ur6BCly_1YYd3-UOMTNGtwQXd&currency=USD&disable-funding=card', function() {
paypal.Buttons({
// Call your server to set up the transaction
createOrder: function(data, actions) {
return fetch('https://example.com/TESTS.php', {
method: 'post'
}).then(function(res) {
return res.json();
}).then(function(orderData) {
return orderData.id;
});
},
// Call your server to finalize the transaction
onApprove: function(data, actions) {
return fetch('/demo/checkout/api/paypal/order/' + data.orderID + '/capture/', {
method: 'post'
}).then(function(res) {
return res.json();
}).then(function(orderData) {
// (1) Recoverable INSTRUMENT_DECLINED -> call actions.restart()
// (2) Other non-recoverable errors -> Show a failure message
// (3) Successful transaction -> Show confirmation or thank you
// This example reads a v2/checkout/orders capture response, propagated from the server
// You could use a different API or structure for your 'orderData'
var errorDetail = Array.isArray(orderData.details) && orderData.details[0];
if (errorDetail && errorDetail.issue === 'INSTRUMENT_DECLINED') {
return actions.restart(); // Recoverable state, per:
// https://developer.paypal.com/docs/checkout/integration-features/funding-failure/
}
if (errorDetail) {
var msg = 'Sorry, your transaction could not be processed.';
if (errorDetail.description) msg += '\n\n' + errorDetail.description;
if (orderData.debug_id) msg += ' (' + orderData.debug_id + ')';
return alert(msg); // Show a failure message (try to avoid alerts in production environments)
}
// Successful capture! For demo purposes:
console.log('Capture result', orderData, JSON.stringify(orderData, null, 2));
var transaction = orderData.purchase_units[0].payments.captures[0];
alert('Transaction '+ transaction.status + ': ' + transaction.id + '\n\nSee console for all available details');
// Replace the above to show a success message within this page, e.g.
// const element = document.getElementById('paypal-button-container');
// element.innerHTML = '';
// element.innerHTML = '<h3>Thank you for your payment!</h3>';
// Or go to another URL: actions.redirect('thank_you.html');
});
}
}).render('#paypal-button-container');
})
</script>
The php file is like this :
<?php
use PayPalCheckoutSdk\Orders\OrdersCreateRequest;
use PayPalCheckoutSdk\Core\PayPalHttpClient;
use PayPalCheckoutSdk\Core\SandboxEnvironment;
use PayPalCheckoutSdk\Orders\OrdersCaptureRequest;
require __DIR__ . '/Checkout-PHP-SDK-develop/vendor/autoload.php';
// Creating an environment
$clientId = "AQgUM7x3URK1A-rcNIq56covuc0CYGv3pb5sYeL6-cqsO1HYV2CV6h4ur6BCly_1YYd3-UOMTNGtwQXd";
$clientSecret = "EDm88hmcFd6arhd7vaJ6d9AWjIvCScR6E6s0eM3OKqwf1uZt0G0KlLNUXG057vesyXR4eYP3RKDLJBz8";
$environment = new SandboxEnvironment($clientId, $clientSecret);
$client = new PayPalHttpClient($environment);
$request = new OrdersCreateRequest();
$request->prefer('return=representation');
$request->body = [
"intent" => "CAPTURE",
"purchase_units" => [[
//"reference_id" => "test_ref_id1",
"amount" => [
"value" => "100.00",
"currency_code" => "USD"
]
]],
"application_context" => [
"cancel_url" => "https://example.com/cancelled",
"return_url" => "https://example.com/success"
]
];
try {
$response = $client->execute($request);
print_r($response);
}catch (HttpException $ex) {
// echo $ex->statusCode;
print_r($ex->getMessage());
}
if(isset($_POST['id'])) {
$od_id = $response->result->id;
//echo $od_id;
$request1 = new OrdersCaptureRequest($od_id);
$request1->prefer('return=representation');
try {
// Call API with your client and get a response for your call
$response1 = json_encode($client->execute($request1));
return $response1;
// If call returns body in response, you can get the deserialized version from the result attribute of the response
return $request1;
}catch (HttpException $ex) {
echo $ex->statusCode;
// print_r($ex->getMessage());
}
}
Should I create, and catch the order in php file and then send it to JS? Actually is it the proper way to send the data? Any help would be highly appreciated. Thanks.
I have added CAPTURE method to the php file. and now it looks like above.

Each of your routes (the create route, and the capture route) must return a response that is a JSON string, and no other text nor HTML. print_r is not suitable.

Related

set ajax response in php variable

I am trying to set json response in php variable.After success response my html data is printed in div.
Any Idea How to upload This in a Php variable. it's any idea where I can store this in a session or cookies.
$('#pincode').on('change', function() {
//const formData = $('#formid').serializeArray();
var address = $("input[name=address]").val();
var pincode= $("input[name=pincode]").val();
var price = $("input[name=price]").val();
var city = $("input[name=city]").val();
var country =$('#country').val();
var state = $('#state').val();
//var state =$(this).val();
//console.log(formData);
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
type:'POST',
data:{address:address, pincode:pincode, price:price,country:country,state:state,city:city},
url:'./ava',
dataType: "text",
success:function(data){
$('#gettax').html(data);
//alert(res);
},
error: function (err) {
console.log(err);
alert("Something Went Wrong, Please check again");
}
});
});
Here is mY controller and I m returning a plan text value.and try to restore this in a php variable
public function avatax(Request $request){
$input = $request->all();
$address=$input['address'];
$pincode=$input['pincode'];
$country=$input['country'];
$state=$input['state'];
$city=$input['city'];
$price=$input['price'];
// print_r(json_decode(json_encode($input)));
// die();
//return response()->json(['success'=>$input]);
$client = new Avalara\AvaTaxClient('phpTestApp', '1.0', 'localhost', 'sandbox');
$client->withSecurity('ABC', 'ABC');
// If I am debugging, I can call 'Ping' to see if I am connected to the server
$p = $client->ping();
echo('<h2>Ping</h2>');
echo('<pre>' . json_encode($p, JSON_PRETTY_PRINT) . '</pre>');
if ($p->authenticated == true) {
echo '<p>Authenticated!</p>';
}
// Create a simple transaction for $100 using the fluent transaction builder
$tb = new Avalara\TransactionBuilder($client, "ABC", Avalara\DocumentType::C_SALESINVOICE, 'ABC');
$t = $tb->withAddress('SingleLocation',$address,null,null, $city,$state,$pincode, $country)
->withLine($price, 1, null, "P0000000")
->create();
// echo('<h2>Transaction #1</h2>');
// echo('<pre>' . json_encode($t, JSON_PRETTY_PRINT) . '</pre>');
// echo '<pre>';print_r($t);
$ta=$t->totalTax;
// die();
return response($ta)
->header('Content-Type', 'text/plain');

How to fix the 3D secure confirm Payment on client side or on server side in Stripe Payment Intent?

I'm integrating Stripe Payment Intent API and it's working well where 3D secure is not required, 3D secure authorization is popping up but I think I'm missing return_url to confirm the payment.
Where do I need to mention return_url for 3D Secure in PaymentIntent?
I've tried multiple times but got stuck on 3D Secure Authorize. It returns an error in the object.
I've mentioned the code of view and controller below.
Thanks in Advance
Client Side Code:
form.addEventListener('submit', function(event) {
event.preventDefault();
$('#card-button').html('<i class="fa fa-circle-o-notch fa-spin" style="font-size:24px"></i>');
var fname = $('#firstname2').val();
var lname = $('#lastname2').val();
var cardholderName = fname + " " + lname;
var cardButton = document.getElementById('card-button');
var form_data = $("#payment-form").serialize();
cardButton.addEventListener('click', function(ev) {
stripe.createPaymentMethod('card', cardElement, {
billing_details: {name: cardholderName}
}).then(function(result) {
if (result.error) {
// Show error in payment form
} else {
console.log(result);
// Otherwise send paymentMethod.id to your server (see Step 2)
fetch('<?php echo base_url(); ?>payment/stripe_test/process_payment',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ payment_method_id: result.paymentMethod.id, customer_detail: form_data})
}).then(function(result) {
// Handle server response (see Step 3)
result.json().then(function(result) {
console.log("Response" + result);
handleServerResponse(result);
});
});
}
});
});
}
function handleServerResponse(response) {
if (response.error) {
// Show error from server on payment form
} else if (response.requires_action) {
var action = response.next_action;
if (action && action.type === 'redirect_to_url') {
window.location = action.redirect_to_url.url;
}
// Use Stripe.js to handle required card action
stripe.handleCardAction(
response.payment_intent_client_secret
).then(function(result) {
if (result.error) {
// Show error in payment form
} else {
// The card action has been handled
// The PaymentIntent can be confirmed again on the server
fetch('<?php echo base_url(); ?>payment/stripe_test/process_payment', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ payment_intent_id: result.paymentIntent.id })
}).then(function(confirmResult) {
return confirmResult.json();
}).then(handleServerResponse);
}
});
} else {
// Show success message
console.log("3D" + response);
}
}
CodeIgniter Controller:
//PaymentIntent Function
function process_payment() {
require_once (APPPATH."third_party/stripe/init.php");
$key = "STRIPE_KEY_HERE";
header('Content-Type: application/json');
# retrieve json from POST body
$json_str = file_get_contents('php://input');
$json_obj = json_decode($json_str);
$intent = null;
try {
if (isset($json_obj->payment_method_id)) {
# Create the PaymentIntent
//STRIPE PAYMENT INTENT
\Stripe\Stripe::setApiKey($key);
// Create a Customer:
$customer = \Stripe\Customer::create([
'email' => 'client#gmail.com',
]);
// Attach payment method to the customer:
$customer_detail = $json_obj->customer_detail;
$intent = \Stripe\PaymentIntent::create([
'payment_method' => $json_obj->payment_method_id,
'amount' => 1099,
'currency' => 'GBP',
'confirmation_method' => 'manual',
"customer" => $customer->id,
'confirm' => true,
]);
}
if (isset($json_obj->payment_intent_id)) {
$intent = \Stripe\PaymentIntent::retrieve(
$json_obj->payment_intent_id
);
$intent->confirm();
}
$this->generatePaymentResponse($intent);
} catch (\Stripe\Error\Base $e) {
# Display error on client
echo json_encode([
'error' => $e->getMessage()
]);
}
}
generatePaymentResponse Function:
function generatePaymentResponse($intent) {
if ($intent->status == 'requires_source_action' &&
$intent->next_action->type == 'use_stripe_sdk') {
# Tell the client to handle the action
echo json_encode([
'requires_action' => true,
'payment_intent_client_secret' => $intent->client_secret
]);
} else if ($intent->status == 'succeeded') {
# The payment didn’t need any additional actions and completed!
# Handle post-payment fulfillment
echo json_encode([
"success" => true
]);
} else {
# Invalid status
http_response_code(500);
echo json_encode(['error' => 'Invalid PaymentIntent status']);
}
}
As mentioned in comments, you don't need to specify return_url, because in your case Stripe will use Popup for 3DS confirmation, not redirecting.
You missed two things in your code:
1. In function generatePaymentResponse add condition for $intent->status === 'requires_action'.
2. On Payment Intent confirmation ($intent->confirm();) you missed to set api key (\Stripe\Stripe::setApiKey($key);)
I have tested your code and it works with mentioned modifications.
Stripe updated the API and few statuses were renamed so the major reason was that I was using requires_source_action as status so replaced it with requires_action.
Stripe Update - 2019-02-11
Some PaymentIntent statuses have been renamed
requires_source is now requires_payment_method
requires_source_action is now requires_action
All other statuses are unchanged
save_source_to_customer has been renamed to save_payment_method.
allowed_source_types has been renamed to payment_method_types.
The next_source_action property on PaymentIntent has been renamed to next_action, and the authorize_with_url within has been renamed to redirect_to_url.
You can find Stripe Api upgrades here: https://stripe.com/docs/upgrades#api-versions.

PHP Webhost Operation Checking

I wanted perform checking if the PHP Webhost is complete whenever perform a update function, if everything doing fine then send an notification and let the Application know the Operation is Doing fine.
Basically I wanted to know if the query in PHP work and use my application to notify the user.
is there any way or method to do so?
I using this method to fetch data from PHP in my React Native App
RecipeUpdation = () =>{
const { ID } = this.state ;
const { Name } = this.state ;
const { Type } = this.state ;
const { Ingredient } = this.state ;
const { Step } = this.state ;
return fetch('https://www.update.php', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
RecipeID : ID,
RecipeName : Name,
RecipeType : Type,
RecipeIngredient: Ingredient,
RecipeStep: Step
})
}).then((response) => response.json())
.then((responseJson) => {
}).catch((error) => {
console.error(error);
});
}
Basically we can verify if the Operation in PHP is successful or not by Checking the Query Execution Status. A very Basic way to do the checking is using If Else to see if the Query Function return True(Success) or False(Fail). You can also always return some Message through JsonResponds.
Here some example Code for PHP checking and Return Some Message:
// Using If Else to Check if operation Success or Not
if(mysqli_query($connection,$Your_Query)){
$MSG = 'Success' ;
// Convert message into Json format first
$json = json_encode($MSG);
// This is where it return the message to Application.
echo $json ;
}
else{
$MSG = 'Failed' ;
$json = json_encode($MSG);
echo $json ;
}
In your Application Code you already have the implementation to retrieve the JsonResponds(the Message) which have been echo in the PHP Code, I would suggest use a simple method which is Alert to pop out the message in your React Native Application to notify the User the Operation Status.
}).then((response) => response.json())
.then((responseJson) => {
// this responseJson Already have the echo Message from PHP
// just Display the Status with Alert Function
Alert.alert(responseJson);
}).catch((error) => {
console.error(error);
});
Hope this would help.

call rest api service from jquery

I am trying to understand restful services.i can create a class and define a function into this but when i call it through jquery it return null and when i call directly by typing url in address bar it return a json response
this is the code
class Api extends REST
{
public function processApi()
{
$func = strtolower(trim(str_replace("api/","",$_REQUEST['request'])));
if((int)method_exists($this,$func) > 0)
{
$this->$func();
}
else
{
$this->response('',404); // If the method not exist with in this class, response would be "Page not found".
}
}
private function json($data)
{
if(is_array($data))
{
return json_encode($data);
}
}
public function demo()
{
$error = array('status' => '200', "msg" => "OK");
$this->response($this->json($error), 200);
}
}
$api = new Api;
$api->processApi();
i just want to call demo method from jquery.this is what i am trying
$.post("db/api/demo",
function(data,status){
data = jQuery.parseJSON(data);
alert("Data: " + data + "\nStatus: " + status);
});
i am getting response through jquery when demo method is this
public function demo()
{
$error = array('status' => '200', "msg" => "OK");
echo json_encode($error);
//$this->response(json_encode($error), 200);
}
You should send datatype to server.
Try this code:
$.post( "db/api/demo")
.done(function( data ) {
$.each(data, function(index, element) {
alert('Data: ' + element.data + ' Status: ' + element.status);
});
}, "json");

sending a file to slimframework from nodejs server

i want to sent a file from my server to my rest api on another server, but for some reason it is not getting the data i sent..
rest api php using slim framework:
$app->post
(
'/api/upload',
function () use ($app)
{
$logs = '/home/logs';
//error_log(print_r($_FILES, 1), 3, $logs . '/export16.log');
try
{
$data = file_get_contents('php://input'); // EMPTY!!!!
error_log(print_r(count($data), 1), 3, $logs . '/export16.log');
}
catch(Exception $e)
{
error_log(print_r($data, 1), 3, $logs . '/export16err.log');
}
}
);
nodejs using request module:
fs.createReadStream('myfile.zip')
.pipe
(
request.post
(
UPLOAD_URL,
function (error, response, body)
{
//console.log(response);
if (!error && response.statusCode == 200)
{
//console.log(repons);
}
}
)
);
also tried with this code: using form-data module as explained in the docs
var r = request.post(UPLOAD_URL, function optionalCallback (err, httpResponse, body) {
if (err) {
return console.error('upload failed:', err);
}
console.log(httpResponse);
console.log('Upload successful! Server responded with:', body);
})
var form = r.form();
form.append('my_file', fs.createReadStream('file.zip') );
they both don't work and i get not data in my php:input,
i see the header content type: application/zip is set, but nothing else, somethign is missing maybe?
_header: 'POST /api/upload HTTP/1.1\r\nhost: xyz.com\r\ncontent-type: a
pplication/zip\r\nConnection: keep-alive\r\nTransfer-Encoding: chunked\r\n\r\n',
any ideas what i'm doing wrong?
Turns out i had to set the content length :)

Categories