Assign Related Product In Magento 2 API - php

I am using magento 2 api for assigning product link like related or crosssell
using api /V1/products/{sku}/links
Here is My Sample Code
<?php
error_reporting(E_ALL);
define('mag_apiurl',"http://www.mywebsite.com/rest/V1/");
define('tn_webshopKey',"myshowpkey");
$sku1 = "sku1";
$sku2 = "sku2";
$productData = array(
"items" => array(
"sku" => $sku1,
"linkType" => 'related',
"linkedProductSku" => $sku2,
"linkedProductType" => "simple",
"position" => 0
)
);
$headers = array("Content-Type:application/json","Authorization: Bearer ".tn_webshopKey);
$requestUrl= mag_apiurl.'products/'.$sku1.'/links';
$ch = curl_init($requestUrl);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($productData));
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
echo $returnProductDetails = curl_exec($ch);
?>
But Every time i run the script its
response
{"message":"%fieldName is required filed.","parameters":{"fieldName":"linkType"}}
But the link type 'related' is already defined in my data (productData)
Does anyone knows the solution or related link which helps :)

Could you try setting "linkType" to 1 instead of "related"
$linkTypes = ['related' => 1, 'upsell' => 4, 'crosssell' => 5, 'associated' => 3];

Sorry Its my fault i'am reading the swagger api documentation for enterprise version of magento-2.2.* but i am working on magento-2.1.*
Actual Code Should be
$productData = array(
"items" => array(
array(
"sku" => $sku1,
"link_type" => 'related',
"linked_product_sku" => $sku2,
"linked_product_type" => "simple",
"position" => 0
)
)
);
/*
THE JOSN FORMAT START
{
"items": [
{
"sku": "string",
"link_type": "string",
"linked_product_sku": "string",
"linked_product_type": "string",
"position": 0,
"extension_attributes": {
"qty": 0
}
}
]
}
***************END************/
There are some differences ive noticed between those documentation that each document have different model schema declaration like some has snake_case and on other hand some has camelCase so do not begin confused between the documentation of swagger and select appropriate version of document for each store

Related

Import Document via CustomTranslator API in PHP

I'm trying to import a TMX file via the Microsoft Custom Translator API in PHP. Unfortunately, I keep running into the following error:
"DocumentDetails must follow type IEnumerable[ImportDocumentRequestDetails]."
I've managed to make other (though only GET) requests to the API successfully, so it's specifically this request I'm having trouble figuring out.
So far, I've tried various permutations of the request, mostly by trial and error. I've tried replicating the request by uploading the same file in the portal, which succeeds without problems, but I've not been able to replicate this in PHP (7.3).
I've also tried to reverse-engineer the C# API samples on GitHub. Unfortunately, my C# knowledge isn't that sharp and I'm sure there are nuances I'm missing. I have noticed the sample uses a 'Language' string, whereas the portal seems to use a 'LanguageCode', as well as other inconsistencies which haven't made solving this much easier.
A stripped-down version of my code, with only the relevant parts (one can assume a valid access token and local filepath to a valid .tmx) is the following:
Class CustomTranslator {
private $curl;
private $aAccessToken; // valid, working token
// Set up connection and login with initial user
public function __construct() {
$this->curl = curl_init();
$aOptions = array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_TIMEOUT => 60
);
curl_setopt_array($this->curl, $aOptions);
}
function ImportParallelDocument($strFilePath) {
$aRequestContent = [
'Files' => new CURLFile($strFilePath, mime_content_type($strFilePath), basename($strFilePath)),
'DocumentDetails' => [
'DocumentName' => basename($strFilePath),
'DocumentType' => 'training',
'IsParallel' => true,
'FileDetails' => [
'Name' => $strFilePath,
'Language' => 'Dutch',
'Type' => pathinfo($strFilePath, PATHINFO_EXTENSION),
'OverwriteIfExists' => true
]
]
];
return $this->Request("v1.0/documents/import?workspaceId=".CUSTOMTRANSLATOR_WORKSPACEID, $aRequestContent, 'POST');
}
// Prototype request function
private function Request($strRequest, $aData = array(), $strMethod = 'GET') {
$strRequest = CUSTOMTRANSLATOR_API_URL.$strRequest;
// Reset between requests
curl_setopt($this->curl, CURLOPT_POST, false);
curl_setopt($this->curl, CURLOPT_HTTPHEADER, ['Authorization: Bearer '.$this->aAccessToken['access_token']]);
if(isset($aData['authorization'])) $aData['authorization'] = $this->aAccessToken['access_token'];
if ($strMethod == 'GET') {
$strRequest .= "?".http_build_query($aData);
}
else {
curl_setopt($this->curl, CURLOPT_POST, true);
curl_setopt($this->curl, CURLOPT_HTTPHEADER, ['Authorization: Bearer '.$this->aAccessToken['access_token'],
'X-HTTP-Method-Override: '.$strMethod]);
curl_setopt($this->curl, CURLOPT_POSTFIELDS, $aData);
}
curl_setopt($this->curl, CURLOPT_URL, $strRequest);
$strResponse = curl_exec($this->curl);
// Return the JSON array if it can be decoded, otherwise the actual curl response
return json_decode($strResponse, true)?:$strResponse;
}
}
As stated, when I try to upload a file using the above code, the exact error I'm receiving is {"message":"DocumentDetails must follow type IEnumerable[ImportDocumentRequestDetails].","display":false}, unfortunately without further specification of what's missing or incorrect. I'm hoping to achieve a successful file import of a TMX file which does successfully import via the portal itself, which I understand implements the same API.
I expect I'm simply missing something, or doing something not quite right, so any help would be appreciated!
With help from a colleague, figured out a will-do-for-now workaround, by simply providing the equivalent JSON of the call as it's used in the portal:
$aRequestContent = [
'Files' => new CURLFile($strFilePath, mime_content_type($strFilePath), basename($strFilePath)),
'DocumentDetails' =>
'[{ "DocumentName": "",
"DocumentType": "training",
"FileDetails": [{
"Name": "'.basename($strFilePath).'",
"LanguageCode": "en",
"OverwriteIfExists": true }]
}]'
];
It's not the best solution, but for the purposes of a preview API, it'll work for now (until it inevitably ends up in production, sigh).
Examining the JSON a little closer led me to discover the nested array structure (presumably for multi-file uploads), which wasn't inherently obvious to me at first. However, the following array structure is sufficient for requests to be processed:
$aDocumentDetails = [[ // Note the nested array here, for index numbering
'DocumentName' => '',
'DocumentType' => ucfirst($strType),
'FileDetails' => [[ // As well as here
'Name' => basename($strFilePath),
'LanguageCode' => $strLanguageCode,
'OverwriteIfExists' => $bOverwrite
]]
]];
$aRequestContent = [
'Files' => new CURLFile($strFilePath, mime_content_type($strFilePath), basename($strFilePath)),
'DocumentDetails' => json_encode($aDocumentDetails)
];
In short, the API expects DocumentDetails (and FileDetails) in indexed sub-arrays:
[0 => [ 'DocumentName' => ...,
'FileDetails' => [0 => ['Name' => ...]
];
Understanding this tidbit helped me tremendously.

How to send a Embedded Webhook using PHP [Discord]

I am trying to send a Webhook to a Discord channel when a User fills out a form on my website, I would really like it to be embedded, however I am having trouble doing that. I have managed to post the Webhhook fine using "content", however I just cannot get it embed it.
$Embed = {
"username": "Kick Report",
"embeds": [{
"fields": [
{
"name": "Victim",
"value": "Change Victim Later",
"inline": true
},
{
"name": "Reason",
"value": "Change Reason Later!",
"inline": true
},
{
"name": "Caller",
"value": "Change Caller Later"
},
{
"name": "Date",
"value": "Change Date Later"
}
]
}]
};
$data = array("content" => $Embed, "Kick Report" => "Webhooks");
$curl = curl_init("https://discordapp.com/api/webhooks/xxxxxxxxxxxxxxxxxxxxxxxx");
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
return curl_exec($curl);
Try this code:
<?php
// Replace the URL with your own webhook url
$url = "https://discordapp.com/api/webhooks/0000000/ABCDEFGH....";
$hookObject = json_encode([
/*
* The general "message" shown above your embeds
*/
"content" => "A message will go here",
/*
* The username shown in the message
*/
"username" => "MyUsername",
/*
* The image location for the senders image
*/
"avatar_url" => "https://pbs.twimg.com/profile_images/972154872261853184/RnOg6UyU_400x400.jpg",
/*
* Whether or not to read the message in Text-to-speech
*/
"tts" => false,
/*
* File contents to send to upload a file
*/
// "file" => "",
/*
* An array of Embeds
*/
"embeds" => [
/*
* Our first embed
*/
[
// Set the title for your embed
"title" => "Google.com",
// The type of your embed, will ALWAYS be "rich"
"type" => "rich",
// A description for your embed
"description" => "",
// The URL of where your title will be a link to
"url" => "https://www.google.com/",
/* A timestamp to be displayed below the embed, IE for when an an article was posted
* This must be formatted as ISO8601
*/
"timestamp" => "2018-03-10T19:15:45-05:00",
// The integer color to be used on the left side of the embed
"color" => hexdec( "FFFFFF" ),
// Footer object
"footer" => [
"text" => "Google TM",
"icon_url" => "https://pbs.twimg.com/profile_images/972154872261853184/RnOg6UyU_400x400.jpg"
],
// Image object
"image" => [
"url" => "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"
],
// Thumbnail object
"thumbnail" => [
"url" => "https://pbs.twimg.com/profile_images/972154872261853184/RnOg6UyU_400x400.jpg"
],
// Author object
"author" => [
"name" => "Alphabet",
"url" => "https://www.abc.xyz"
],
// Field array of objects
"fields" => [
// Field 1
[
"name" => "Data A",
"value" => "Value A",
"inline" => false
],
// Field 2
[
"name" => "Data B",
"value" => "Value B",
"inline" => true
],
// Field 3
[
"name" => "Data C",
"value" => "Value C",
"inline" => true
]
]
]
]
], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );
$ch = curl_init();
curl_setopt_array( $ch, [
CURLOPT_URL => $url,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $hookObject,
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
]
]);
$response = curl_exec( $ch );
curl_close( $ch );
?>
Source: https://www.reddit.com/r/discordapp/comments/83itgm/does_anyone_know_how_to_send_embeds_from_php_to_a/

how to setup this simple Elasticsearch Mapping in Elasticsearch-PHP?

Given in the end of the question is an terminal command showing a simple Elasticsearch mapping. I need to set up this kind of mapping for an index using Elasticsearch-PHP. And I need to do this at the time when I am indexing the data.
I know how to index in Elasticsearch-PHP. It will be something like
for($i = 0; $i < 100; $i++) {
$params['body'][] = [
'index' => [
'_index' => 'my_index',
'_type' => 'my_type',
]
];
$params['body'][] = [
'my_field' => 'my_value',
'second_field' => 'some more values'
];
}
$responses = $client->bulk($params);
My question is that how will I set up a Mapping, corresponding to the particular Mapping given below in the elasticsearch-PHP format (I believe it will become an associative array, but I am not sure of further details)?
This is the example ES Mapping, that I want to convert to the format used in PHP:
PUT _template/packets
{
"template": "packets-*",
"mappings": {
"pcap_file": {
"dynamic": "false",
"properties": {
"timestamp": {
"type": "date"
},
"layers": {
"properties": {
"ip": {
"properties": {
"ip_ip_src": {
"type": "ip"
},
"ip_ip_dst": {
"type": "ip"
}
}
}
}
}
}
}
}
}
If you don't update your mapping - you don't have to put mapping each time you re-index data into elasticsearch. But if you do, of you create index with new name you can do this:
$put = [
'mappings' => [
// your mapping here
],
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://yourHost:9200/yourIndex');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($put));
curl_exec($ch);
or you can use elasticsearch package:
$params = [
'index' => 'yourIndex',
'body' => [
'mappings' => [
// your mapping here
]
]
];
$response = $client->indices()->create($params);

Forbidden error 403 in Unification Engine API while sending message

I am using #unificationengine API to send message on facebook.
Details I have given while registering my APP on facebook:
site url : http://localhost:3000
Email adress and other required details
In unificationengine API I have used all the curls mentioned in their documentation step by step as follows:
1. Created user using API key and Secret
2. Added connection
3. test connection
4. Refresh connection
5. Send message
All 4 gave 200 success code but send message gives 403 fobidden error.
The curl I am using for this is as below:
$post_msg = json_encode(
array(
'message' =>
array(
'receivers' =>
array(
array(
'name' => 'Me',
'address' => 'https://graph.facebook.com/v2.5/me/feed',
'Connector' => 'facebook'
),
),
'sender' =>
array('address' => ''),
'subject' => 'Hello',
'parts' =>
array(
array(
'id' => '1',
'contentType' => 'text/plain',
'data' => 'Hi welcome to UE',
'size' => 100,
'type' => 'body',
'sort' => 0
),
),
),
)
);
$ch = curl_init('https://apiv2.unificationengine.com/v2/message/send');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_USERPWD,'3f43c37b-a066-4cc4-a3be-33faf72d6a21:2722fc72d-5d347-4a3a-a82b-0c1ss51aafb4');
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_msg);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// execute!
$response = curl_exec($ch);
// close the connection, release resources used
curl_close($ch);
// do anything you want with your response
var_dump($response);
return ['label' =>$response];
I am trying to figure this. But no success.
Again I like to mention that I am using this on localhost, could that be the reason for forbidden error? If so then facebook graph api from which we get access token should also give such error.
Earlier I have posted this question, here also I didn't find right solution. I added Curl options that is mentioned in comment of my question there but it didn't changed the things.
Any help would be highly appreciated.
Error Message:
{\"Status\":{\"facebook\":{\"status\":403,\"info\":\"Forbidden:
\"}},\"URIs\":[]}
UPDATE
Below is the json I get when I run me/permissions in facebook graph API explorer:
{
"data": [
{
"permission": "user_birthday",
"status": "granted"
},
{
"permission": "user_about_me",
"status": "granted"
},
{
"permission": "user_status",
"status": "granted"
},
{
"permission": "user_posts",
"status": "granted"
},
{
"permission": "email",
"status": "granted"
},
{
"permission": "manage_pages",
"status": "granted"
},
{
"permission": "publish_actions",
"status": "granted"
},
{
"permission": "public_profile",
"status": "granted"
}
]
}
I have resolved this problem:
public function facebookSharing($access_token) {
$app = new UEApp(env('UNIFICATION_APP_KEY'), env('UNIFICATION_APP_SECRATE'));
$user = new UEUser('unification_userkey', 'unification_usersecret');
$connection = $user->add_connection('FACEBOOK', "facebook", $access_token);
$options = array(
"receivers" => array(
array(
"name"=> "Me"
)
),
"message"=>array(
"subject"=>'testing',
"body"=> 'description',
"image"=> 'use any image url',
"link"=>array(
"uri"=> 'any web site url',
"description"=> "",
"title"=>"Title"
)
)
);
$uris = $connection->send_message($options);
}
Please use your keys like
facebook accesstoken
UNIFICATION_APP_KEY (its your unification keys)
UNIFICATION_APP_SECRATE (its your unification keys)
If this will not work then please let me know.
Can you please confirm if the "Connector" name that you have given is correct?
While I tried your sample code that you provided, I could sent the message to facebook via UE.
Can you please provide the exact error message that is returned while you execute the command?

Perl - LWP API Post

I'm trying to post a new item to a listing website using LWP. The listing website provides an example of how to post the data but using PHP, I’ve therefore tried to reproduce the solution but in Perl.
This is the PHP example.
$postData = array('type' => 'fixedPrice',
'item' => array(
'id_country' => 0,
'id_category' => 80,
'fixed_price' => '1.00',
'currency' => 'EUR',
'title' => 'My title',
'personal_reference' => 'My personal ref',
));
//RESOURCE CALL WITH POST METHOD
$url = 'http://correct.server.address/item?token=MyPersonalToken';
$ch = curl_init();
curl_setopt ($ch, CURLOPT_URL, $url);
curl_setopt ($ch, CURLOPT_POST, true);
curl_setopt ($ch, CURLOPT_POSTFIELDS, http_build_query($postData) );
curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true);
$xml_response = curl_exec($ch);
My Perl solution:
#!/usr/bin/perl
### Module requests ###
use strict;
use warnings;
use LWP::UserAgent;
use HTTP::Request::Common;
use XML::LibXML;
use Data::Dumper;
### Make Request to get the session Token ###
my $url = "http://correct.server.address/seller";
my $api = "APIKEY";
my $userAgent = LWP::UserAgent->new();
my $request = HTTP::Request->new(POST => $url . "?apikey=" . $api);
my $response = $userAgent->request($request);
### Display error if request to server fails ###
unless ($response->is_success) {
print "Content-type: text/html\n\n";
print "Error: " . $response->status_line;
exit;
}
### Assign response xml to $xml_token ###
my $xml_token = $response->content;
### Parse XML through XML::LibXML module ###
my $parser = XML::LibXML->new();
my $tree = $parser->parse_string($xml_token);
my $root = $tree->getDocumentElement;
my $token = $root->getElementsByTagName('token');
### Make Request to add Item - PROBLEM STARTS HERE ###
my $postURL = "http://correct.server.address/item" . "?token=" . $token;
my %item_data = (type => "fixedPrice",
item => {
id_country => "0",
id_category => "728",
fixed_price => "1.00",
currency => "GBP",
title => "Test item",
personal_reference => "12345"
}
);
my $userAgentReq2 = LWP::UserAgent->new();
my $requestReq2 = HTTP::Request->new(POST => $postURL);
$requestReq2->header(content_type => 'multipart/form-data');
$requestReq2->content(\%item_data);
my $responseReq2 = $userAgentReq2->request($requestReq2);
### Display error if request to server fails ###
unless ($responseReq2->is_success) {
print "Content-type: text/html\n\n";
print "<p>Error Message: " . $responseReq2->status_line;
print "</p><p>Output of test data sent: \n";
print Dumper(\%item_data);
print "</p><p>Dumped Response: \n";
print Dumper($responseReq2);
print "</p><p>\n";
print "Token: $token\n";
print "</p><p>\n";
print "Response: " . $responseReq2->as_string;
print "</p>\n";
exit;
}
### Assign response xml to $xml_responseReq2 ###
my $xml_responseReq2 = $responseReq2->content;
### Display Token ###
print "Content-type: text/html\n\n";
print "<p>Response: $xml_responseReq2</p>\n";
print Dumper($responseReq2);
exit;
My first post request to retrieve the session token works correctly and I receive the token. However my second post request trying to add the item fails.
This is the dumped response:
$VAR1 = bless( {
'_content' => 'Not a SCALAR reference at /usr/lib/perl5/site_perl/5.8.8/LWP/Protocol/http.pm line 203.
',
'_rc' => 500,
'_headers' => bless( {
'client-warning' => 'Internal response',
'client-date' => 'Fri, 21 Mar 2014 12:13:34 GMT',
'content-type' => 'text/plain',
'::std_case' => {
'client-warning' => 'Client-Warning',
'client-date' => 'Client-Date'
}
}, 'HTTP::Headers' ),
'_msg' => 'Not a SCALAR reference',
'_request' => bless( {
'_content' => {
'item' => {
'currency' => 'GBP',
'id_category' => '728',
'id_country' => '0',
'personal_reference' => '12345',
'title' => 'Test item',
'fixed_price' => '1.00'
},
'type' => 'fixedPrice'
},
'_uri' => bless( do{\(my $o = 'http://correct.server.address/item?token=986aee823d54a7c2d50651c1b272c455')}, 'URI::http' ),
'_headers' => bless( {
'user-agent' => 'libwww-perl/6.05',
'content-type' => 'multipart/form-data'
}, 'HTTP::Headers' ),
'_method' => 'POST'
}, 'HTTP::Request' )
}, 'HTTP::Response' );
Please can someone help me as to where I’m going wrong, many thanks in advance!
The following appears to achieve what you want.
my %item_data = (type => "fixedPrice",
'item[id_country]' => "0",
'item[id_category]' => "728",
'item[fixed_price]' => "1.00",
'item[currency]' => "GBP",
'item[title]' => "Test item",
'item[personal_reference]' => "12345"
);
my $userAgentReq2 = LWP::UserAgent->new();
my $responseReq2 = $userAgentReq2->post($postURL,[%item_data]);
PHP allows you to create POST variables that get automatically deserialized into nested structures; for example, you can have form fields called item[0] and item[1] and so forth and those will appear in your server-side PHP script as an array of values. But HTTP does not have any concept of arrays; post data are simple key and value pairs.
The sample client-side PHP code is trying to build a nested array structure which PHP's curl interface will automatically translate into HTTP field names. It's been a million years since I've done any PHP, but I think the field names would end up being item[0][id_country], item[0][id_category], and so on. This is how PHP "cheats" HTTP to put complex structure into POSTs.
Perl's LWP library does not support building field names out of nested structures this way. That's why you're getting this error:
Not a SCALAR reference at /usr/lib/perl5/site_perl/5.8.8/LWP/Protocol/http.pm line 203.
'
In your POST arguments, the item key is pointing to a hash reference, but LWP expects to only see a plain scalar or scalar reference there.
So you'll need to change your LWP POST parameters to something like the following. (If this is not exactly right, you can use a HTTP sniffer on the PHP code to figure out what the actual field names are that it generates.)
my %item_data = (type => "fixedPrice",
'item[0][id_country]' => "0",
'item[0][id_category]' => "728",
'item[0][fixed_price]' => "1.00",
'item[0][currency]' => "GBP",
'item[0][title]' => "Test item",
'item[0][personal_reference]' => "12345"
);

Categories