Magento 1.9 Rest API POST create new user - magento-1.9

I'm using custom Magento Rest API, to create a new user, my postman request data is:
URL: http://megashopping.am/api/rest/register/store/1
content-type: application/json
Key: firstname
but I am having this error
{
"messages": {
"error": [
{
"code": 400,
"message": "Decoding error."
}
]
}
}
My XML file is
<extendrestapiregister translate="title" module="api2">
<group>extendrestapi</group>
<model>extendrestapi/api2_register</model>
<title>Register</title>
<sort_order>10</sort_order>
<privileges>
<guest>
<retrieve>1</retrieve>
<create>1</create>
</guest>
</privileges>
<attributes >
<firstname>First Name</firstname>
</attributes>
<routes>
<route_entity>
<route>/register/:id/store/:store_id</route>
<action_type>entity</action_type>
</route_entity>
<route_collection>
<route>/register/store/:store_id</route>
<action_type>collection</action_type>
</route_collection>
</routes>
<versions>1</versions>
</extendrestapiregister>
My Class is
<?php
/**
* Override for Magento's Catalog REST API
*/
class ITology_RestApi_Model_Api2_Register_Rest_Guest_V1 extends Mage_Api2_Model_Resource {
/**
* Create a customer
* #return array
*/
public function _create(array $data) {
return $firstName = $data['firstname'];
}
}

Related

Do you now how i can update a json in a function ? (API,Angular)

So i have following JSON:
.json
"type": [ {
"id": 2,
"secondid": "1",
"name": "f",
"positionX": 0,
"positionY": 0
}]
and following Service:
public updateposition(Model: typemodel): Observable<any> {
return this.http.post(this.apiEndPoint + '/type' + '/' + typemodel.id , typemodel);
}
and following TS:
.ts
x: number;
y: number;
updateposition()
{
}
So the goal is to update the json object "type" by clicking a button with html. The html part is no problem. But i don't know how to update the json object with the two new positions x and y which are declared in ts. I want to have the process in the function updateposition(). Do you have any suggestions :) ?
You would have to use Dependency Injection to obtain a reference to the Service in your component and use it to retrieve and store the JSON object. Then update it like you would any other object in JS when the button is clicked, and make the API call. Be sure to subscribe to the result or the API call will not go through.
// ...
export class MyComponent {
public jsonObject: TypeModel = { ... };
public constructor(private service: Service) { }
// ...
public function updateposition() {
this.jsonObject[0].positionX = 52;
this.jsonObject[0].positionY = 42;
this.jsonObject = this.service.updateposition(this.jsonObject).subscribe(
result => {
console.log("The API call returned", result);
}
);
}
}

Rest API using Symfony4

I have been creating REST API using symfony4,
I have installed FosRestBundle and I configured it to return object directly from the controller.
I want to return an object from the controller but I get the error
Warning: ReflectionObject::__construct() expects parameter 1 to be object, null given
MoviesController:
/**
* #Rest\View()
* #Route("/movies", name="get_movies")
*
*/
public function getMovies()
{
$movies = $this->getDoctrine()
->getRepository(Movie::class)
->findAll();
return $movies;
}
fos_rest.yaml:
fos_rest:
param_fetcher_listener: force
body_converter:
enabled: true
view:
formats: { json: true, xml: false, rss: false }
view_response_listener: true
serializer:
serialize_null: true
format_listener:
rules:
- { path: '^/', priorities: ['json'], fallback_format: 'json' }
framework.yaml
sensio_framework_extra:
view: { annotations: false }
I use FOSRest, but my controller looks like:
use FOS\RestBundle\Controller\FOSRestController; //
use FOS\RestBundle\View\View; // <-- first import
use FOS\RestBundle\Controller\Annotations as Rest; //
class TagController extends FOSRestController // <-- extend
{
/**
* Retrieves a collection of Tag resource.
*
* #Rest\View(serializerGroups={"details"})
* #Rest\Get("/tag") // <-- rout
*/
public function index(TagRepository $tagRepository): View // <-- use View
{
$data = $tagRepository->findAll();
return View::create($data, Response::HTTP_OK); // <-- how to return
}
}

How to make the error = false appear in Fractal json response

I'm using Fractal transformer to prettify my User model json return (using Laravel 5.3 + dingo api).
Previously I was returning my user model like this:
return response()->success(compact('user'));
and the json was returned like this
{
"errors": false,
"data": {
"user": {
"id": 2,
"first_name": "
Now I use a transformer, and return it like this:
return $this->response->item($user, new UserTransformer);
and the json looks like this:
{
"data": {
"id": 2,
"first_name": "Client",
"last_name": "Testing",
How do I wire things up with fractal to return the same structure as it was previously? All my unit tests expect the original format, and so they're failing like this:
1) LoginEmailTest::testLoginEmailSuccess
Unable to find JSON fragment
["errors":false]
within
[{"data":[{"user":{"a
Update
I think the obvious place to customize the response is in the Fractal default dataArraySerializer. But I'm not sure how to deal with the error parameter, in other words, how do I pass it an actual error if it exists rather than just hardcoded it to null?
so this is how i fixed it (but for some reason I'm not happy with this whole situation, being a laravel nuub yet having familiarity with rails/django etc.. something doesn't feel right about all of this:)
<?php
/*
* This is to address the problem asked here:
* https://stackoverflow.com/questions/48669423/how-to-make-the-error-false-appear-in-fractal-json-response
* basically we must add an error key to the top level of the json response
*
*
*/
namespace App\Http\Serializer;
use League\Fractal\Serializer\ArraySerializer;
class DataErrorArraySerializer extends ArraySerializer
{
/**
* Serialize a collection.
*
* #param string $resourceKey
* #param array $data
*
* #return array
*/
public function collection($resourceKey, array $data)
{
return ['data' => $data, 'errors' => false];
}
/**
* Serialize an item.
*
* #param string $resourceKey
* #param array $data
*
* #return array
*/
public function item($resourceKey, array $data)
{
return ['data' => $data, 'errors' => false];
}
/**
* Serialize null resource.
*
* #return array
*/
public function null()
{
return ['data' => [], 'errors' => false];
}
}
and in the controller:
$manager = new Manager();
$manager->setSerializer(new DataErrorArraySerializer());
$resource = new Item($user, new UserTransformer);
return $manager->createData($resource)->toArray();
so this is what it looks like in a successful http request:
{
"data": {
"id": 2,
"first_name": "Client",
"last_name": "Testing",
..
},
"errors": false
}
when an http error happens, it doesn't even execute that code anyways, it will return an error response (for example see this part of the code:
} catch (\JWTException $e) {
\Log::debug('Could not create token for login email: '. $email);
return response()->error(trans('errors.no_token'), 500);
}
and response is defined in public/index.php like so:
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
$response = $kernel->handle(
$request = Illuminate\Http\Request::capture()
);
$response->send();
anyways again this is what an error looks like:
{
"message": "422 Unprocessable Entity",
"errors": {
"message": [
"The email must be a valid email address."
]
},
"status_code": 422
}

Laravel Echo / Pusher authentication fails (403)

Learning Laravel event broadcasting / Echo / Vue and playing around with this tutorial.
I keep getting 403 responses to authentication, and I suspect my lack of understanding on the channels.php routes is the issue. I am using Player model instead of User for Auth which works ok.
Event ChatMessageSend
class ChatMessageSent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $channel;
public $player;
public $chatMessage;
/**
* Create a new event instance.
* GameChat constructor.
* #param $chatMessage
* #param $player
*/
public function __construct(ChatMessage $chatMessage, Player $player)
{
$this->channel = session()->get('chat.channel');
$this->chatMessage = $chatMessage;
$this->player = $player;
}
/**
* Get the channels the event should broadcast on.
*
* #return Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel($this->channel);
}
}
Listener ChatMessageNotification (default / empty)
class ChatMessageNotification
{
/**
* ChatMessageNotification constructor.
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* #param ChatMessageSent $event
* #return void
*/
public function handle(ChatMessageSent $event)
{
//
}
}
Controller ChatController
class ChatController extends Controller
{
/**
* Send chat message
*
* #param Request $request
* #return \Illuminate\Database\Eloquent\Collection|static[]
*/
public function getMessages(Request $request)
{
return ChatMessage::with('player')
->where('progress_id', '=', session('game.progress.id'))
->orderBy('created_at', 'DESC')
->get();
}
/**
* Send chat message
*
* #param Request $request
* #return array|string
*/
public function sendMessage(Request $request)
{
$player = Auth::user();
$message = $request->input('message');
if ($message) {
$message = ChatMessage::create([
'player_id' => $player->id,
'progress_id' => session()->get('game.progress.id'),
'message' => $request->input('message')
]);
}
broadcast(new ChatMessageSent($player, $message))->toOthers();
return ['type' => 'success'];
}
}
Routes channels.php
Broadcast::channel(session()->get('chat.channel'), function ($player, $message) {
return $player->inRoom();
});
And in my Player class
/**
* A user can be in one chat channel
*/
public function inRoom()
{
if ((Auth::check()) and ($this->games()->where('progress_id', '=', session('game.progress.id'))->get())) {
return true;
}
return false;
}
When a player logs in, I store in session a chat room id which I would like to use as channel.
My vue chat instance is
Vue.component('chat-messages', require('./../generic/chat-messages.vue'));
Vue.component('chat-form', require('./../generic/chat-form.vue'));
const app = new Vue({
el: '#toolbar-chat',
data: {
messages: []
},
created() {
this.fetchMessages();
Echo.private(chat_channel)
.listen('chatmessagesent', (e) => {
this.messages.unshift({
message: e.data.message,
player: e.data.player.nickname
});
});
},
methods: {
fetchMessages() {
axios.get(chat_get_route)
.then(response => {
this.messages = response.data;
});
},
addMessage(message) {
this.messages.unshift(message);
this.$nextTick(() => {
this.$refs.toolbarChat.scrollTop = 0;
});
axios.post(chat_send_route, message)
.then(response => {
console.log(response.data);
});
}
}
});
But I keep getting
POST http://my-games.app/broadcasting/auth 403 (Forbidden)
Pusher : Couldn't get auth info from your webapp : 403
Error 403 /broadcasting/auth with Laravel version > 5.3 & Pusher, you need change your code in resources/assets/js/bootstrap.js with
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'your key',
cluster: 'your cluster',
encrypted: true,
auth: {
headers: {
Authorization: 'Bearer ' + YourTokenLogin
},
},
});
And in app/Providers/BroadcastServiceProvider.php change by
Broadcast::routes()
with
Broadcast::routes(['middleware' => ['auth:api']]);
or
Broadcast::routes(['middleware' => ['jwt.auth']]); //if you use JWT
it worked for me, and hope it help you.
It may be an idea to figure out whether your routes/channels.php file is doing as you expect. Maybe add some logging to see if that route gets called at all, and that your inRoom function is returning what you expect.
In case anyone still needs an answer, this worked for me.
Add to your broadcastServiceProvider.php
Broadcast::routes([
'middleware' => 'auth:api']);
add to your channels.php
Broadcast::channel('chat', function () {
return Auth::check();
});

laravel validate Content-Type: application/json request

in laravel 5 i made a new request named ApiRequest.
class ApiRequest extends Request
{
public function authorize() {
return $this->isJson();
}
public function rules()
{
return [
//
];
}
}
As you can see i am accepting only json data. And i am receiving the json in controller like this
public function postDoitApi(ApiRequest $payload) {
$inputJson = json_decode($payload->getContent());
$name = $inputJson->name;
}
Which is working fine. I am getting data in $name. But now i need to validate the input json.
I need to set validation rule in ApiRequest for the name key like this
public function rules()
{
return [
'name' => 'required|min:6'
];
}
Help me to do this. Thanks.
Laravel validates AJAX requests the same way. Just make sure you're setting one of these request headers on your request:
'Accept': 'application/json'
'X-Requested-With': 'XMLHttpRequest'
Validating any headers can be done in clean way two steps:
Step 1: Prepare header data to request data in prepareForValidation method.
public function prepareForValidation()
{
$this->merge([
"content_type" => $this->headers->get("Content-type"),
]);
}
Step 2: Apply any validation rules that you want, (Here, you want your data exact to be application/json. so
public function rules(): array
{
return [
"content_type" => "required|in:application/json",
];
}
Complete Example looks like:
/**
* Class LoginRequest
*
* #package App\Requests
*/
class LoginRequest extends FormRequest
{
public function prepareForValidation()
{
$this->merge([
"content_type" => $this->headers->get("Content-type"),
]);
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules(): array
{
return [
"content_type" => "required|in:application/json",
];
}
}
You could use a validator method instead of rules method:
class ApiRequest extends Request
{
public function authorize() {
return $this->isJson();
}
public function validator(){
//$data = \Request::instance()->getContent();
$data = json_decode($this->instance()->getContent());
return \Validator::make($data, [
'name' => 'required|min:6'
], $this->messages(), $this->attributes());
}
//what happens if validation fails
public function validate(){
$instance = $this->getValidatorInstance();
if($this->passesAuthorization()){
$this->failedAuthorization();
}elseif(!$instance->passes()){
$this->failedValidation($instance);
}elseif( $instance->passes()){
if($this->ajax())
throw new HttpResponseException(response()->json(['success' => true]));
}
}
}
return $inputJson->toArray();
and then pass to validator
$name = ['name'=>'er'];
$rules = array('name' => 'required|min:4');
$validation = Validator::make($name,$rules);
you can put following function in your ApiRequest form request.
public function validator(){
return \Validator::make(json_decode($this->getContent(),true), $this->rules(), $this->messages(), $this->attributes());
}