I am trying to integrate Plaid via Stripe. Bear with me as I am not very familiar with javascript.
I want to know how I can place in to a PHP variable the public_token and account_ID so that I may include in the curl call.
JS
<button id='linkButton'>Open Plaid Link</button>
<script src="https://cdn.plaid.com/link/stable/link-initialize.js"></script>
<script>
var linkHandler = Plaid.create({
env: 'tartan',
clientName: 'Stripe / Plaid Test',
key: '[Plaid key]',
product: 'auth',
selectAccount: true,
onSuccess: function(public_token, metadata) {
// Send the public_token and account ID to your app server.
console.log('public_token: ' + public_token); // HOW DO I PLACE THIS IN PHP/curl?**
console.log('account ID: ' + metadata.account_id); // HOW DO I PLACE THIS IN PHP/curl?**
},
});
PHP/CURL
$ch = curl_init();
curl_setopt_array($ch, array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_URL => 'https://tartan.plaid.com/exchange_token',
CURLOPT_POST => true,
CURLOPT_HTTPHEADER, array(
'Content-Type: application/x-www-form-urlencoded',
),
CURLOPT_POSTFIELDS => http_build_query(array(
'client_id' => '[Plaid client ID]',
'secret' => '[Plaid secret]',
'public_token' => '[Plaid Link public_token]', // HOW DO I CREATE A VARIABLE FROM THE ABOVE JS ( console.log('public_token: ' + public_token);) to place here**
'account_id' => '[Plaid Link account_id]', // HOW DO I CREATE A VARIABLE FROM THE ABOVE JS ( console.log('public_token: ' + public_token);) to place here
)),
));
You will want to take a look at using XMLHTTP, also known as AJAX. This allows Javascript to make HTTP requests with post or get. If this looks too difficult, you can use the jQuery.ajax method (but you need to include jQuery in your HTML). You will then be able to point the request to your PHP page in which you make your cURL request and retrieve the values via _POST or _GET.
Examples as per below:
XMLHTTP REQUEST
var url = 'curl.php?token='+public_token+'&acctid='+metadata.account_id;
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
console.log(xmlhttp.responseText);
}
};
xhttp.open("GET", url, true);
xhttp.send();
JQUERY.AJAX
Assuming jQuery is included and jQuery.noConflict() has not been called.
$.ajax({
method: "GET",
url: "curl.php",
data: {
token: public_token,
acctid: metadata.account_id
}
}).done(function( msg ) {
console.log( msg );
});
Both examples above are only theoretical and untested, although I believe they should work. From here, you should be able to get the variables in your PHP like so:
'public_token' => $_GET['token'],
'account_id' => $_GET['acctid']
Related
Stripe are soon to roll out their use of Strong Customer Authentication for payments with their platform. There's a fairly substantial section in their documentation about it.
https://stripe.com/docs/payments/payment-intents/quickstart#manual-confirmation-flow
The process has the following flow:
The vanilla PHP implementation is like so:
<?php
# vendor using composer
require_once('vendor/autoload.php');
\Stripe\Stripe::setApiKey(getenv('STRIPE_SECRET_KEY'));
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
$intent = \Stripe\PaymentIntent::create([
'payment_method' => $json_obj->payment_method_id,
'amount' => 1099,
'currency' => 'gbp',
'confirmation_method' => 'manual',
'confirm' => true,
]);
}
if (isset($json_obj->payment_intent_id)) {
$intent = \Stripe\PaymentIntent::retrieve(
$json_obj->payment_intent_id
);
$intent->confirm();
}
generatePaymentResponse($intent);
} catch (\Stripe\Error\Base $e) {
# Display error on client
echo json_encode([
'error' => $e->getMessage()
]);
}
function generatePaymentResponse($intent) {
# Note that if your API version is before 2019-02-11, 'requires_action'
# appears as 'requires_source_action'.
if ($intent->status == 'requires_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']);
}
}
?>
The necessary JavaScript for its use with Stripe Elements looks like this:
var cardholderName = document.getElementById('cardholder-name');
var cardButton = document.getElementById('card-button');
cardButton.addEventListener('click', function(ev) {
stripe.createPaymentMethod('card', cardElement, {
billing_details: {name: cardholderName.value}
}).then(function(result) {
if (result.error) {
// Show error in payment form
} else {
// Otherwise send paymentMethod.id to your server (see Step 2)
fetch('/ajax/confirm_payment', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ payment_method_id: result.paymentMethod.id })
}).then(function(result) {
// Handle server response (see Step 3)
result.json().then(function(json) {
handleServerResponse(json);
})
});
}
});
});
function handleServerResponse(response) {
if (response.error) {
// Show error from server on payment form
} else if (response.requires_action) {
// 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('/ajax/confirm_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
}
}
In my own project I'm using Laravel which is entirely based on the MVC architecture and it fairly nice to you when it comes to most things.
I have tried to refactor a little but I have a question.
Why would you use this line $json_str = file_get_contents('php://input'); over just trying to grab the posted variables from the Request object used in Laravel?
I also read the following article from the PHP Manual:
https://www.php.net/manual/en/wrappers.php.php
To be perfectly honest I've been away from procedural PHP so this has confused me to no end.
Why use 'php://input' over the POST superglobal - Stripe SCA example
The body is encoded as JSON. You can tell because the next line explicitly decodes it.
PHP doesn't understand application/json requests. It will only populate $_POST if the data is encoding using the application/x-www-form-urlencoded or multipart/form-data formats.
Why would you use this line $json_str = file_get_contents('php://input'); over just trying to grab the posted variables from the Request object used in Laravel?
If you were using Laravel, there's no reason to do that.
Since there is no sign of anything Laravel in the example you gave, it is presumably not written with the intention of introducing a dependency on Laravel.
Given this GraphQL example, how can I in Javascript do a similar request with JSON?
Using GraphQL the query in the example is:
{
trip(
from: {place: "NSR:StopPlace:5533" },
to: {place:"NSR:StopPlace:5532"}
)
{
tripPatterns{duration}
}
}
According to the documentation the URL to query is https://api.entur.io/journey-planner/v2/graphql .
Here is what I tried in Javascript:
var url = "https://api.entur.io/journey-planner/v2/graphql";
var tripquery =
{
trip:
{
__args: {
from : {place :"NSR:StopPlace:5533" },
to : {place :"NSR:StopPlace:5532" }
},
tripPatterns: {
duration : true
}
}
};
function jsonQuery(){
var qry = JSON.stringify(tripquery);
var url_qry = url + "?query=" + qry;
var xhttp = new XMLHttpRequest();
xhttp.open("POST", url_qry, true);
xhttp.setRequestHeader("Content-Type", "application/json");
xhttp.onreadystatechange = function(){
console.log("onreadystatechange");
if(xhttp.readyState === 4 && xhttp.status === 200){
console.log("json-query-OK");
console.log(xhttp.responseText);
}
else{
console.log("xhttp.status : " + xhttp.status);
console.log("xhttp.statusText : " + xhttp.statusText);
console.log("xhttp.readyState : " + xhttp.readyState);
console.log("xhttp.responseType: " + xhttp.responseType);
console.log("xhttp.responseText: " + xhttp.responseText);
console.log("xhttp.responseURL : " + xhttp.responseURL);
console.log("json-not-ok");
}
};
xhttp.send();
console.log("query sent");
}
The code above will result in this output in the console:
query sent
api.entur.io/journey-planner/v2/graphql?query={%22trip%22:{%22__args%22:{%22from%22:{%22place%22:%22NSR:StopPlace:5533%22},%22to%22:{%22place%22:%22NSR:StopPlace:5532%22}},%22tripPatterns%22:{%22duration%22:true}}}:1 POST https://api.entur.io/journey-planner/v2/graphql?query={%22trip%22:{%22__args%22:{%22from%22:{%22place%22:%22NSR:StopPlace:5533%22},%22to%22:{%22place%22:%22NSR:StopPlace:5532%22}},%22tripPatterns%22:{%22duration%22:true}}} 400 (Bad Request)
query.js:29 onreadystatechange
query.js:35 xhttp.status : 400
query.js:36 xhttp.statusText : Bad Request
query.js:37 xhttp.readyState : 2
query.js:38 xhttp.responseType:
query.js:39 xhttp.responseText:
query.js:40 xhttp.responseURL : https://api.entur.io/journey-planner/v2/graphql?query={%22trip%22:{%22__args%22:{%22from%22:{%22place%22:%22NSR:StopPlace:5533%22},%22to%22:{%22place%22:%22NSR:StopPlace:5532%22}},%22tripPatterns%22:{%22duration%22:true}}}
query.js:41 json-not-ok
query.js:29 onreadystatechange
query.js:35 xhttp.status : 400
query.js:36 xhttp.statusText : Bad Request
query.js:37 xhttp.readyState : 3
query.js:38 xhttp.responseType:
query.js:39 xhttp.responseText: No query found in body
query.js:40 xhttp.responseURL : https://api.entur.io/journey-planner/v2/graphql?query={%22trip%22:{%22__args%22:{%22from%22:{%22place%22:%22NSR:StopPlace:5533%22},%22to%22:{%22place%22:%22NSR:StopPlace:5532%22}},%22tripPatterns%22:{%22duration%22:true}}}
query.js:41 json-not-ok
query.js:29 onreadystatechange
query.js:35 xhttp.status : 400
query.js:36 xhttp.statusText : Bad Request
query.js:37 xhttp.readyState : 4
query.js:38 xhttp.responseType:
query.js:39 xhttp.responseText: No query found in body
query.js:40 xhttp.responseURL : https://api.entur.io/journey-planner/v2/graphql?query={%22trip%22:{%22__args%22:{%22from%22:{%22place%22:%22NSR:StopPlace:5533%22},%22to%22:{%22place%22:%22NSR:StopPlace:5532%22}},%22tripPatterns%22:{%22duration%22:true}}}
query.js:41 json-not-ok
The __args in the Json object is something I got from an example online, but I haven't really understood it.
Maybe I'm not sure what exactly to search for, but I can't find some good explanation of how to translate this GraphQL query to a JSON object.
I had the same problem and I did it like this:
{
c_con_tic_PTF(dz: CR, docmanId: 123) {
docmanId
dz
data
}
}
I tried sending this request as curl command in OS X How to use CURL in OS X:
curl \
-X POST \
-H "Content-Type: application/json" \
--data '{ "query": "{ c_con_tic_PTF(docmanId: 123, dz: CR) { docmanId, dz, data }}" }' \
*my-graphicQL endpoint url*
And I got the response I wanted.
So you want to make something like this from your graphQL query:
{ "query": "{ cz_atlascon_etic_PTF(docmanId: 123, dz: CR) { docmanId, dz, data }}" }
And now just send request with JS.
If it helps you in any way, this is how my request looked in Java:
HttpRequest mainRequest =
HttpRequest.newBuilder()
.uri(URI.create("my graphQL endpoint"))
.POST(HttpRequest.BodyPublishers.ofString("{ \"query\": \"{ c_con_tic_PTF(docmanId: 123, dz: CR) { docmanId, dz, data }}\" }"))
.build();
One way to do it in Javascript is using the fetch api. Something like this is how I've done it in the past. You can test it out by copying the code below and then pasting it into Chrome Dev Tools and running it.
async function makeGraphQlQuery(urlToResource) {
const queryObject = {
query:
'{ trip( from: {place: "NSR:StopPlace:5533" }, to: {place:"NSR:StopPlace:5532"}) {tripPatterns{duration}} }',
};
const response = await fetch(urlToResource, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(queryObject),
});
const json = response.json();
return json;
}
async function sendAsync() {
const res = await makeGraphQlQuery('https://api.entur.io/journey-planner/v2/graphql');
console.log(res);
}
sendAsync().catch(err => console.log('Error in query', err));
I am trying to use mailgun.com for sending emails. But it happened that I need to send it with js (cause sometimes I built websites with rubyonrails, sometimes with python. And now I need to built a simple landing page with mail sending.
And hosting (which is free ad suits me only supports php which I don't know)
So I decided to use js and obfuscate this code and paste it somewhere in somelibrary.So no one will ever find my secret key)
Can someone help with translating some of this examples into js code?
This is python example:
def send_simple_message():
return requests.post(
"https://api.mailgun.net/v3/YOUR_DOMAIN_NAME/messages",
auth=("api", "YOUR_API_KEY"),
data={"from": "Excited User <mailgun#YOUR_DOMAIN_NAME>",
"to": ["bar#example.com", "YOU#YOUR_DOMAIN_NAME"],
"subject": "Hello",
"text": "Testing some Mailgun awesomness!"})
This is c# example
public static IRestResponse SendSimpleMessage() {
RestClient client = new RestClient();
client.BaseUrl = new Uri("https://api.mailgun.net/v3");
client.Authenticator =
new HttpBasicAuthenticator("api",
"YOUR_API_KEY");
RestRequest request = new RestRequest();
request.AddParameter("domain",
"YOUR_DOMAIN_NAME", ParameterType.UrlSegment);
request.Resource = "{domain}/messages";
request.AddParameter("from", "Excited User <mailgun#YOUR_DOMAIN_NAME>");
request.AddParameter("to", "bar#example.com");
request.AddParameter("to", "YOU#YOUR_DOMAIN_NAME");
request.AddParameter("subject", "Hello");
request.AddParameter("text", "Testing some Mailgun awesomness!");
request.Method = Method.POST;
return client.Execute(request);
}
This is php example
# Include the Autoloader (see "Libraries" for install instructions)
require 'vendor/autoload.php';
use Mailgun\Mailgun;
# Instantiate the client.
$mgClient = new Mailgun('YOUR_API_KEY');
$domain = "YOUR_DOMAIN_NAME";
# Make the call to the client.
$result = $mgClient->sendMessage($domain, array(
'from' => 'Excited User <mailgun#YOUR_DOMAIN_NAME>',
'to' => 'Baz <YOU#YOUR_DOMAIN_NAME>',
'subject' => 'Hello',
'text' => 'Testing some Mailgun awesomness!'
));
This is rails example:
def send_simple_message
RestClient.post "https://api:YOUR_API_KEY"\
"#api.mailgun.net/v3/YOUR_DOMAIN_NAME/messages",
:from => "Excited User <mailgun#YOUR_DOMAIN_NAME>",
:to => "bar#example.com, YOU#YOUR_DOMAIN_NAME",
:subject => "Hello",
:text => "Testing some Mailgun awesomness!"
end
Obfuscated code just slows down the naughty coder who is trying to mess up, its not a perfect layer of security. Since you say your host supports php use the php code. all you have to do is send a post request to the php script
example code considering you are sending using jQuery library for javascript
<?php
require 'vendor/autoload.php';
use Mailgun\Mailgun;
if(isset($_POST['variable1']) && isset($_POST['variable2']))
{
$msg = $_POST['variable1']." ".$_POST['variable1'];
$mgClient = new Mailgun('key');
$domain = "your domain";
$result = $mgClient->sendMessage($domain, array(
'from' => 'from adress',
'to' => 'to adress',
'subject' => 'some subject',
'html' => $msg
));
$result = objectToArray($result);
echo json_encode($result);
}
?>
jquery code to send post request
$("button").click(function(){
$.post("mailer.php",
{
variable1: "Donald Duck",
variable2: "Duckburg"
},
function(data, status){
console.log(data);
});
});
The above code sends a post request to your php file, where the php file validates if it contains the variables 1 and 2 and continues with the execution
In my Wordpress website Users can upload video files directly to a Amazon S3 bucket (So the files don't go through my webserver.) How i should keep track of the added objects (i.e: where and how i should add a data entry in my Wordpress Database )
With the limited information provided you could post the image data using ajax. The below is simple ajax with placeholder data for the image.
var imgData = {author: 'the-author-id', img_url: 'the-url', img_type: 'the-img-type'}
$.ajax({
data : JSON.stringify(imgData),
contentType : 'application/json',
type : 'POST',
url: 'your-wordpress-post-url',
success: function () {
// do something with the success result from backend
}
});
And within WordPress you would use wp_insert_attachment()
<?php
// Prepare an array of post data for the attachment.
$attachment = array(
'post_author' => $_POST['author'],
'post_date' => current_time('mysql'),
'guid' => $_POST['img_url'],
'post_mime_type' => $_POST['img_type'],
'post_title' => preg_replace( '/\.[^.]+$/', '', $_POST['img_url'] ),
'post_content' => '',
'post_status' => 'inherit',
'comment_status' => 'closed',
'ping_status' => 'closed',
);
// Insert the attachment.
$attach_id = wp_insert_attachment( $attachment );
// if fail $attach_id is 0
echo json_encode(array('attach_id' => $attach_id));
?>
I'm building an application where users can click a button to show all of their Instagram images on a page, but in order to do that I need userId and accessToken. How do I get these?
NOTE: If it makes any difference: I'm not trying to get just my own images, but anyone who uses my app to log into their account.
I have this code:
<script>
var feed = new Instafeed ({
get: "user",
userId: ,
accessToken: ""
});
feed.run();
</script>
<div id="instafeed"></div>
And I get a verification code by clicking on a link (note I removed cliend_id and redirect_uri):
Get Instagram images
Then this returns a code like '1251251...' which I grab with GET, but after that what do I do? How do I get userId and accesToken from this?
I'm not sure if I'm on the right track, but any help would be appreciated!
Answering my own question, as I figured it out:
$url = 'https://api.instagram.com/oauth/access_token';
$data = array(
'client_id' => $clientId,
'client_secret' => $clientSecret,
'grant_type' => 'authorization_code',
'redirect_uri' => $redirectUri,
'code' => $code
);
// use key 'http' even if you send the request to https://...
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($data),
),
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
$clientId, $clientSecret and $redirectUri are taken from: https://instagram.com/developer/clients/manage/
$code is the code from your url and $result contains the userId and accessToken if successful.
Thanks to: How do I send a POST request with PHP?