I have two different website : my application and my backoffice (in Laravel)
I create an API route to store a document on my application. I made a request with Guzzle on my backoffice to store a document.
My guzzle http request on backoffice website :
public static function storeDocument($token, $request)
{
$client = new \GuzzleHttp\Client([
'Content-Type' => 'multipart/form-data'
]);
$headers = [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
];
$datas = [
'document' => $request->file('document'),
'doc_name' => $request->doc_name ?? '',
];
$request = $client->post(env('API_URL') . '/api/document/store/', ['headers' => $headers, 'form_params' => $datas]);
$result = json_decode($request->getBody()->getContents());
return $result;
}
And there is my API route method on application website :
public function store(Request $request) {
$validator = Validator::make($request->all(), [
'document' => 'bail|required|mimes:pdf,doc,docs,csv,txt|max:2048',
'doc_name' => 'bail|string|max:80|nullable',
]);
if($validator->fails()){
return response()->json($validator->errors());
};
$document = $request->document;
$fileName = '';
if(isset($request->doc_name)) {
$fileName = $request->doc_name . '.' . $document->extension();
} else {
$fileName = $document->getClientOriginalName();
}
$result = Storage::putFileAs(
'documentations',
$document,
$fileName,
'public'
);
if($result) {
return response()->json(['success' => 'Le fichier a bien été enregistré'], 201);
} else {
return response()->json(['error' => $errors], 400);
};
}
It seems that my datas aren't sent correctly because storeDocument() gives me an error : 'This field is required'. So it looks like it can't find $request->document which is required...
And with Insomnia I have no error, my file is correctly save.
I want to specify that I pass correct datas to storeDocument.
That is the result of $request->file('document') :
Illuminate\Http\UploadedFile {#1354 ▼
-test: false
-originalName: "test.pdf"
-mimeType: "application/pdf"
-error: 0
#hashName: null
path: "/tmp"
filename: "phpPOxtfN"
basename: "phpPOxtfN"
pathname: "/tmp/phpPOxtfN"
extension: ""
realPath: "/tmp/phpPOxtfN"
aTime: 2022-08-25 14:30:14
mTime: 2022-08-25 14:30:13
cTime: 2022-08-25 14:30:13
inode: 4856076
size: 48632
perms: 0100600
owner: 33
group: 33
type: "file"
writable: true
readable: true
executable: false
file: true
dir: false
link: false
}
I'm stuck since several hours on this, does anyone has any idea to help me?
Thanks ;)
EDIT: I finally found that I have to pass 'multipart' instead of 'form_params' on my http request.
Moreover I found that I have to use fopen or file_get_contents to send raw datas...
So my storeDocument function looks like this now :
public static function storeDocument($token, $request)
{
$client = new \GuzzleHttp\Client([
'Content-Type' => 'multipart/form-data'
]);
$headers = [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
];
$datas = [
[
'name' => 'document',
'contents' => file_get_contents($request->file('document')),
],
[
'name' => 'doc_name',
'contents' => $request->doc_name ?? '',
]
];
$request = $client->post(env('API_URL') . '/api/document/store/', ['headers' => $headers, 'multipart' => $datas]);
$result = json_decode($request->getBody()->getContents());
return $result;
}
But it still doesn't work...
Continue searching...
Related
I am using wp_remote_post() to post products to a third party site. First I get these products via API from a site called Mercado Libre. But when I carry out the mass publication, the products are published without a name, without a price, and without respecting the parameters provided. They only have the name "Product".
function publish_products_in_woocommerce()
{
$respuesta = wp_remote_get('https://api.mercadolibre.com/sites/MLA/search?q=Motorola%20G6', array(
'headers' => array(
'Authorization' => 'Bearer APP_USR-2778915669536100-052221-0f3a39361bdcea9bc3de0df8ab619f66-370993848'
)
));
$respuesta = json_decode($respuesta['body'], true);
print_r($respuesta);
foreach ($respuesta['results'] as $value) {
$product_data = array(
'name' => $value['title'],
'status' => 'draft',
'type' => 'simple',
'regular_price' => $value['price'],
'description' => $value['title'],
'short_description' => $value['title'],
'categories' => [
[
'id' => $value['category_id'],
]
],
'images' => [
[
'src' => $value['thumbnail']
]
]
);
$woocommerce_api_ck = 'ck_b2a0f58d07590e8283302eca04fbc1b66a9ff653';
$woocommerce_api_cs = 'cs_b4d91662590be47416f663fc9f0d1c49f600e394';
$url = 'http://nuevo.labisbal.com.ar/wp-json/wc/v3/products';
wp_remote_post('http://nuevo.labisbal.com.ar/wp-json/wc/v3/products', array(
'headers' => array(
'Authorization ' => 'Basic ' . base64_encode($woocommerce_api_ck . ':' . $woocommerce_api_cs),
),
'body' => $ProductToWooCommerce = json_encode($product_data),
'method' => 'POST',
'timeout' => 145,
'blocking' => false,
'sslverify' => false,
'stream' => true,
'data_format' => 'json'
));
print_r($ProductToWooCommerce);
if (wp_remote_retrieve_response_message($respuesta) === 'Created') {
echo 'The product has been created';
}
}
}
publish_products_in_woocommerce();
?>
It's strange because when I display the json already converted (using json_encode) the data is displayed correctly... (using print_r)
I take a look at this and the issue is on how you sent the data to the API, when you use wp_remote_post you need to send the body as an array, and the method handles that information for you, so you don't need to convert it to JSON.
Below is a small test plugin that saves products using the WC REST API, the plugin adds a new endpoint to your site to trigger the scrapper https://yoursite.com/wp-json/wpapi/v1/fetch, I hope that helps.
Note: Please double check the code, is not fully tested.
<?php
/**
* Plugin Name: A WC API test
* Plugin URI: https://enriquechavez.co
* Description: Just a test.
* Version: 1.0.0
* Requires at least: 5.2
* Requires PHP: 7.4
* Author: Enrique Chavez
* Author URI: https://enriquechavez.co/
* License: GPL v2 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Update URI: https://example.com/my-plugin/
* Text Domain: my-basics-plugin
* Domain Path: /languages
*/
add_action('rest_api_init', function () {
register_rest_route('wpapi/v1', 'fetch', [
'methods' => WP_REST_Server::READABLE,
'callback' => 'fetch_ml_products',
'permissions_callback' => '__return_true',
]);
});
function fetch_ml_products(WP_REST_Request $request)
{
$ml_api = 'https://api.mercadolibre.com/sites/MLM/search?q=Motorola%20G6&limit=5';
$wc_ck = 'ck_1f2e32852403a1701c1adxxxxxxxxxxxxxxxxxxx';
$wc_cs = 'cs_6fd5feedd2a25b73eebc9xxxxxxxxxxxxxxxxxxx';
$request = wp_safe_remote_get($ml_api);
if (is_wp_error($request)) {
return $request;
}
$response = json_decode(wp_remote_retrieve_body($request));
$new_products = [];
foreach ($response->results as $product) {
$wc_api_url = 'https://wp.test/wp-json/wc/v3/products/';
$request_data = [
'headers' => [
'Authorization' => 'Basic ' . base64_encode($wc_ck . ':' . $wc_cs),
],
'body' => [
'name' => $product->title,
'status' => 'draft',
'regular_price' => $product->price,
],
'sslverify' => false,
];
$request = wp_remote_post($wc_api_url, $request_data);
if (is_wp_error($request)) {
// TODO: validate the error.
print_r($request);
die('Something is wrong');
}
$new_products[] = json_decode(wp_remote_retrieve_body($request));
}
return $new_products;
}
My code is as follows:
require __DIR__.'/vendor/autoload.php';
use Psr\Http\Message\ResponseInterface;
$loop = React\EventLoop\Factory::create();
$client = new React\Http\Browser($loop);
$data = [
'name' => [
'first' => 'Alice',
'name' => 'Smith',
],
'email' => 'alice#example.com',
'userid' => 'alice',
];
$client->post(
'https://httpbin.org/post',
[
'Content-Type' => 'application/json',
],
json_encode($data)
)->then(function (ResponseInterface $response) {
$response = (string) $response->getBody();
return $response;
});
**echo $response;**
$loop->run();
I am able to get the response inside then function(). but I cannot retrieve the response value outside.
I like to send multiple asynchronous POST requests and collect each responses and echo all of them at once.
How can I access the response variable from outside of post()->then()?
I could get the response when I need a response with deferred and promise method.
First, I assigned the request and response method to $promise.
And I was able to simply get the response with $deferred->resolve();
require __DIR__.'/vendor/autoload.php';
use Psr\Http\Message\ResponseInterface;
$loop = React\EventLoop\Factory::create();
$client = new React\Http\Browser($loop);
$deferred = new React\Promise\Deferred();
$promise = $deferred->promise();
$data = [
'name' => [
'first' => 'Alice',
'name' => 'Smith',
],
'email' => 'alice#example.com',
'userid' => 'alice',
];
$promise = $client->post(
'https://httpbin.org/post',
[
'Content-Type' => 'application/json',
],
json_encode($data)
)->then(function (ResponseInterface $response) {
$response = (string) $response->getBody();
return $response;
});
echo $deferred->resolve();
$loop->run();
I am developing three area for my website.. using WordPress (Front Page), XenForo (Forum), and Laravel (Member Area) ... i already succeed integrating my laravel and XenForo, so when XenForo user login to Member Area my function will check if the user already exist (If XenForo user exist then laravel will create the user in database using XenForo user data, if not exist then login failed)
Now i want to do the same for WordPress .. when user login to member area the function will check if WordPress user is exist or not .. if exist then new user will be created using wordpress user data (name, email, password, and token if possible) if not exist then login failed, but how do i do this? unlike XenForo .. i can't find WordPress API documentation for getting user data
Edit 1 :
This is my login function
public function login_post(Request $request){
// XENFORO API AUTH START
$http = Http::withHeaders([
'XF-Api-Key' => 'SECRET'
])->asForm()->post('http://forum.mywebsite.com/api/auth', [
'login' => $request->email,
'password' => $request->password
]);
if(isset($http['errors'])){
return redirect('login')->with('error', 'Username and Password Error');
}
$name = $http['user']['username'];
$email = $http['user']['email'];
$password = $request->password;
$is_admin = $http['user']['is_admin'];
$user_id = $http['user']['user_id'];
// XENFORO API AUTH END
// WordPress API AUTH START
$client = new \GuzzleHttp\Client([
// Base URI is used with relative requests
'base_uri' => 'http://mywebsite.com/',
'headers' => ['Content-Type' => 'application/json', "Accept" => "application/json", 'Authorization' => 'Basic ' . base64_encode( 'ADMIN' . ':' . 'PASSWORD' ),],
]);
$response = $client->get('users/', [
'query' => [
'email' => $request->email,
]
]);
return json_decode($response->getBody());
// WordPress API AUTH END
if (Auth::attempt(['email' => $email, 'password' => $password])) {
# code...
if(Auth::user()->role == 0){
return redirect('dashboard');
}
return redirect('login');
} else {
$newUser = new User;
$newUser->name = $name ;
$newUser->email = $email;
$newUser->password = bcrypt($password);
$newUser->role = $is_admin;
$newUser->save();
auth()->login($newUser, true);
return redirect('dashboard');
}
}
Edit 2 :
$client = new \GuzzleHttp\Client([
// Base URI is used with relative requests
'base_uri' => 'http://mywebsite.com/wp-json/wp/v2/',
'headers' => ['Content-Type' => 'application/json', "Accept" => "application/json", 'Authorization' => 'Basic ' . base64_encode( 'ADMIN' . ':' . 'PASSWORD' ),],
]);
$response = $client->get('users/', [
'query' => [
'email' => $request->email,
]
]);
$response = json_decode($response->getBody());
$name = $response['username'];
$email = $response['email'];
$password = $request->password;
$is_admin = $response['role'];
$user_id = $response['id'];
The Response :
array:3 [▼
0 => {#287 ▼
+"id": 1
+"name": "Admin"
+"url": "http://www.mywebsite.com"
+"description": ""
+"link": "http://mywebsite.com/author/admin/"
+"slug": "admin"
+"avatar_urls": {#285 ▶}
+"meta": []
+"_links": {#281 ▶}
}
1 => {#274 ▼
+"id": 2
+"name": "Prima"
+"url": ""
+"description": ""
+"link": "http://mywebsite.com/author/prima/"
+"slug": "prima"
+"avatar_urls": {#272 ▶}
+"meta": []
+"_links": {#279 ▶}
}
2 => {#288 ▼
+"id": 3
+"name": "TEST ER"
+"url": ""
+"description": ""
+"link": "http://mywebsite.com/author/testing/"
+"slug": "testing"
+"avatar_urls": {#289 ▶}
+"meta": []
+"_links": {#291 ▶}
}
]
WordPress doesn't provide API to check user exists or not, however you can check this by using List Users API.
Here is what I have done in Laravel:
$client = new \GuzzleHttp\Client([
// Base URI is used with relative requests
'base_uri' => 'http://www.example.com',
'headers' => ['Content-Type' => 'application/json', "Accept" => "application/json"],
]);
$response = $client->get('users/', [
'query' => [
'search' => 'example#email.com',
]
]);
return json_decode($response->getBody());
With Authorization:
Install this https://github.com/WP-API/Basic-Auth plugin and update headers, $username & $password refers to WP admin credentials.
$client = new \GuzzleHttp\Client([
// Base URI is used with relative requests
'base_uri' => 'http://www.example.com',
'headers' => ['Content-Type' => 'application/json', "Accept" => "application/json", 'Authorization' => 'Basic ' . base64_encode( $username . ':' . $password ),],
]);
I want to integrate an Advanced statistics in my project symfony 4
so i decide to use PowerBI ( if you have an alternative please let me know),
my question is how to integrate it in my local project symfony4 and in relation with my database MySQL
Untill now , there no Symfony bundle for power bi , but instead you can use :
the adevait/power-bi
In case you don't find options you are looking for , you can using the native power bi rest api
You need to create an account and manage it by creating your dataset etc ...
Requirement :
GuzzleHttp
The point here is to create for example a service that manage calling the api :
example for authentication :
try {
/** #var GuzzleHttp\Client $client **/
$response = $client->post(
'https://login.windows.net/<tenant-id>/oauth2/token',
[
"headers" => [
"Accept" => "application/json"
],
'form_params' => [
'resource' => 'https://analysis.windows.net/powerbi/api',
'client_id' => $this->clientId,
'client_secret' => $this->secret,
'grant_type' => 'password',
'username' => $this->username,
'password' => $this->password,
'scope' => 'openid',
]
]
);
$body = json_decode($response->getBody()->getContents(), true);
return $body['access_token'];
} catch (ClientException $e) {
return ['error' => $e->getMessage()];
}
At this point , you need the token to call other endpoint , so you need to inject the returned token in the header of any request you send like :
try {
/** #var GuzzleHttp\Client $client **/
$client->post(
https://api.powerbi.com/v1.0/myorg/groups/<group-id>/datasets/<dataset-id>/tables/<table-name>/rows,
[
'headers' => [
"Accept" => "application/json",
"Authorization" => sprintf("Bearer %s", $token),
],
'json' => $data
]
);
return true;
} catch (ClientException $e) {
return false;
}
Hope that help you .
I followed the tutorial on https://github.com/KnpLabs/KnpSnappyBundle and https://ourcodeworld.com/articles/read/250/how-to-create-a-pdf-from-html-using-knpsnappybundle-wkhtmltopdf-in-symfony-3.
app/config/config.yml
knp_snappy:`enter code here`
pdf:
enabled: true
binary: /usr/local/bin/wkhtmltopdf
options: []
image:
enabled: true
binary: /usr/local/bin/wkhtmltoimage
options: []
app/AppKernel
new Knp\Bundle\SnappyBundle\KnpSnappyBundle(),
MyController
use Knp\Bundle\SnappyBundle\Snappy\Response\PdfResponse;
public function pdfAction(string $offerId)
{
$html = $this->renderView('#App/Offer/offer_pdf.html.twig', array(
'offerId' => $offerId
));
return new PdfResponse(
$this->get('knp_snappy.pdf')->getOutputFromHtml($html),
'file.pdf'
);
}
I try and this:
public function offerToPDFAction(string $offerId)
{
$snappy = $this->container->get('knp_snappy.pdf');
$html = '<h1>Hello</h1>';
$filename = 'myFirstSnappyPDF';
return new Response(
$snappy->getOutputFromHtml($html),
200,
array(
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'attachment; filename="'.$filename.'.pdf"'
)
);
The same problem:
You have requested a non-existent service "knp_snappy.pdf".
/**
* #Route("/{id}/pdf", name="sandbox_pdf", methods={"GET"})
*/
public function pdfAction(\Knp\Snappy\Pdf $snappy, Product $product): Response
{
$html = $this->renderView('pdf/index.html.twig', [
'product' => $product,
]);
$filename = 'product';
return new Response(
$snappy->getOutputFromHtml($html),
200,
array(
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'inline; filename="'.$filename.'.pdf"'
)
);
}
use Knp\Snappy\Pdf;
use Knp\Bundle\SnappyBundle\Snappy\Response\PdfResponse;
/**
* #Route("/show/pdf/{token}", name="admin_invoice_show_pdf", methods={"GET"})
*/
public function showPdf(Command $command, Pdf $pdf)
{
$html = $this->renderView('admin/invoice/showPdf.html.twig',array('command' $command));
return new PdfResponse($pdf->getOutputFromHtml($html), 'invoice.pdf');
}