Could not connect to host - php

I am trying to use the SOAP webservice described by the below WSDL:
http://qaws.ssichilexpress.cl/TarificarCourier?wsdl
I tried:
public function __construct($config) {
$this->config = $config;
$this->client = new SoapClient($this->wsdl, [
'trace' => true,
'exceptions' => true
]);
}
public function tarifar($data) {
try {
$this->client->TarificarCourier([
'reqValorizarCourier' => $data
]);
} catch(SoapFault $fault) {
die($fault->getCode() . ': ' . $fault->getMessage());
}
}
But i get a SoapFault with message "Could not connect to host".
Any ideas ?
EDIT 1:
Also i tried:
public function __construct($config) {
$this->config = $config;
$this->wsdl = null;
$this->client = new SoapClient($this->wsdl, [
'trace' => true,
'exceptions' => true,
'location' => 'http://qaws.ssichilexpress.cl/',
'uri' => 'TarificarCourier'
]);
}
public function tarifar($data) {
try {
$this->client->__soapCall('TarificarCourier', [
'reqValorizarCourier' => $data
]);
} catch(SoapFault $fault) {
die('SFinReq: ' . $fault->getCode() . ': ' . $fault->getMessage());
}
}
But, i get a SoapFault with "Not Found" message.

Related

"INVALID_ARGUMENT" when updating or adding a label using the gmail api

I am trying to manage the mail labels using the gmail api the delete does but when I try to add or modify some it tells me that the arguments are invalid.
My code to modify is the following:
public function editLabelGmail(Request $request)
{
try {
$url = 'https://www.googleapis.com/gmail/v1/users/me/labels';
$token = LaravelGmail::getToken()['access_token'];
$params = [
'id' => $request->id,
'labelListVisibility' => 'labelShow',
'messageListVisibility' => 'show',
'name' => $request->name,
];
$response = Http::asForm()
->put(
$url . '/' . $request->id . '?access_token=' . $token,
$params
)
->json();
return Response($response, 200);
} catch (\Exception $e) {
return Response()->json(
[
'message' => $e->getMessage(),
'line' => $e->getLine(),
'file' => $e->getFile(),
],
500
);
}
}
And to add:
public function addLabelGmail(Request $request)
{
try {
$url = 'https://gmail.googleapis.com/gmail/v1/users/me/labels';
$token = LaravelGmail::getToken()['access_token'];
$params = [
'labelListVisibility' => 'labelShow',
'messageListVisibility' => 'show',
'name' => $request->name,
'type' => 'user',
];
$response = Http::asForm()
->post($url . '?access_token=' . $token, $params)
->json();
return Response([$response, 'ok'], 200);
} catch (\Exception $e) {
return Response()->json(
[
'message' => $e->getMessage(),
'line' => $e->getLine(),
'file' => $e->getFile(),
],
500
);
}
}
The parameters I am passing from the front end are coming in as follows:
{
"id": "Label_3",
"name": "Test3"
}
Solution:
I was able to solve it by replacing the $response with the following:
Method Add:
$response = Http::post($url . '?access_token=' . $token, $params)->json();
Method Update:
$response = Http::put($url . '?access_token=' . $token, $params)->json();

How to send form fields with Guzzle 6?

I am developing my unit tests for an API created in Symfony4
Reading the Guzzle documentation I generated the following code:
File SecurityControllerTest.php
$client = new Client([
'base_uri' => 'http://localhost/sacrepad/sacrepad-api/public/index.php/',
'timeout' => 2.0,
]);
$data = array();
$data['email'] = 'admin#admin.com';
$data['password'] = '12345678';
$data2 = array();
$data2['json'] = $data;
$formData = json_encode($data);
$response = $client->request('POST', 'login', [
'headers' => ['Content-Type' => 'application/x-www-form-urlencoded'],
'form_params' => [
'json' => $formData,
]
]);
$body = json_decode($response->getBody(), true);
File SecurityController.php
/**
* #Route("/login", name="login", methods={"POST"})
*/
public function login(Request $request,Helpers $helpers,ValidatorInterface $validator, JwtAuth $jwtauth) {
$data = array(
'status' => 'error',
'code' => 400,
'msg' => 'data not received'
);
$json = $request->request->get('json');
$params = json_decode($json);
}
When I run the tests with the phpunit command, I get the following error:
1) App\Tests\SecurityControllerTest::testAuth GuzzleHttp\Exception\ServerException: Server error: `POST http://localhost/sacrepad/sacrepad-api/public/index.php/login` resulted in a `500 Internal Server Error` response:
If I change the name of the request:
$json = $request->request->get('json2');
It works and it returns me the following:
array(3) {
["status"]=>
string(5) "error"
["code"]=>
int(400)
["msg"]=>
string(18) "data not received"
}
Any ideas on how to make it work and send the parameters?
i build a class for working with guzzle
use Exception;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
class Api
{
protected $client;
protected $url;
public function __construct()
{
$this->client = new Client([
'verify'=>false
]);
$this->url = 'http://localhost/sacrepad/sacrepad-api/public/';
}
public function get($endpoint, $params = [], $headers = [])
{
$response = $this->sendRequest(
'GET',
$this->url . $endpoint,
$params,
$headers
);
return $response;
}
public function post($endpoint, $params = [], $headers = [])
{
$response = $this->sendRequest(
'POST',
$this->url . $endpoint,
$params,
$headers
);
return $response;
}
public function sendRequest($type, $url, $params = [], $headers = [])
{
if ($type == 'GET') {
$data = [
'query' => $params
];
} elseif ($type == 'FILE') {
$type = 'POST';
$data = [
'multipart' => $params // TODO implements later
];
} else {
$data = [
'json' => $params
];
}
if (!empty($headers)) {
$data['headers'] = $headers;
}
$data['headers']['X-REAL-IP'] = $_SERVER['REMOTE_ADDR'];
$data['headers']['User-Agent'] = $_SERVER['HTTP_USER_AGENT'];;
$data['headers']['X-Platform'] = 'web';
try {
$response = $this->client->request(
$type,
$url,
$data
);
if (in_array($response->getStatusCode(), ['200', '403', '404'])) {
return json_decode($response->getBody());
}
return false;
} catch (RequestException $re) {
if (in_array($re->getResponse()->getStatusCode(), ['403', '404', '422'])) {
return json_decode($re->getResponse()->getBody());
}
return json_decode($re->getResponse()->getBody());
} catch (Exception $e) {
return false;
}
}
}
when i want to send a post request it would be like this
$response = (new Api())->post('index.php/',[
'email'=> 'admin#admin.com',
'password' => '123456'
]);
now it will send a post request to index.php and send email and password data i hope it would be helpful

What is the best design pattern to consume REST API

I want to consume a Rest API in Laravel (an MVC framework) but I resort to use __call and was wonder if there is a better design pattern for this.
I know this a bad choice and I'm looking for an alternative pattern but here is my Repository class:
namespace App\Repositories;
use App\Models\OnlinePayment;
use App\Models\Order;
use App\Models\Transaction;
use App\Models\User;
use GuzzleHttp\Client;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
use SoapClient;
class Bank
{
protected $http;
protected $user;
public function __construct()
{
$this->http = new Client;
}
protected function index()
{
$url = config('Bank.url') . '/v2/quantum/users/' . $this->user->national_id . '/report';
$data = [
'user_gender' => $this->user->gender ?? 1,
'user_name' => $this->user->name,
'user_family' => $this->user->family ?? 'خالی',
'user_mobile' => $this->user->mobile,
'user_type' => $this->user->type->name,
];
$options = $this->options($data);
$res = $this->http->request('GET', $url, $options);
$response = json_decode($res->getBody(), true);
return $response;
}
protected function indexData($request)
{
$url = config('Bank.url') . '/v2/quantum/users/' . $this->user->national_id . '/customers';
$options = $this->options($request->all());
$res = $this->http->request('GET', $url, $options);
$response = response()->json(json_decode($res->getBody(), true), $res->getStatusCode());
return $response;
}
protected function show($national_id)
{
$url = config('Bank.url') . '/v2/quantum/users/' . $this->user->national_id . '/customers/' . $national_id;
$options = $this->options([]);
$res = $this->http->request('GET', $url, $options);
if ($res->getStatusCode() == 404) {
abort(404);
}
$response = json_decode($res->getBody(), true);
return $response;
}
protected function store($request)
{
$http = new Client;
$url = config('Bank.url') . '/v2/quantum/users/' . $this->user->national_id . '/customers';
$this->user = auth()->user();
$data = array_merge(
[
'customer_national_id' => $request->national_id,
'customer_gender' => $request->gender,
'customer_name' => $request->name,
'customer_family' => $request->family,
'customer_phone' => $request->phone,
'customer_mobile' => $request->mobile,
'customer_city_id' => $request->city_id,
], [
'user_name' => $this->user->nanfig() is a hidden dependency. The settings should also be passed via the construcme,
'user_family' => $this->user->family ?? 'خالی',
'user_mobile' => $this->user->mobile,
'user_type' => $this->user->type->name,
'user_gender' => $this->user->gender ?? 1,
]
);
$res = $http->request('POST', $url, [
'headers' => [
'Accept' => 'application/json',
'Content-Type' => 'application/json',
'Authorization' => 'Bearer ' . config('Bank.token'),
],
'json' => $data,
'http_errors' => false
]);
if (! in_array($res->getStatusCode(), [200, 422])) {
$error = ValidationException::withMessages([
'name' => 'خطای ' . $res->getStatusCode() . ' در تعویض کالا'
]);
throw $error;
}
$response = response()->json(json_decode($res->getBody(), true), $res->getStatusCode());
return $response;
}
protected function options($data)
{
$options = [
'headers' => [
'Accept' => 'application/json',
'Content-Type' => 'application/json',
'Authorization' => 'Bearer ' . config('Bank.token'),
],
'json' => $data,
'http_errors' => false
];
return $options;
}
public function __call($method, $arguments) {
if (method_exists($this, $method)) {
if (! isset($arguments[0]) || ! $arguments[0] instanceof User) {
$this->user = auth()->user();
} else {
$this->user = $arguments[0];
unset($arguments[0]);
}
return call_user_func_array(array($this, $method), $arguments);
}
}
}
then create an instance of it in controller constructor:
public function __construct()
{
$this->Bank = new Bank();
}
and use it in controller like this:
$response = $this->Bank->indexData($user, $request);
or this:
$response = $this->Bank->indexData($request);
I think the shown class is not a Repository class because a Repository is only responsible for reading and writing the date from a data source. Your class does too much and violates all basic MVC principles.
Some thinks I would fix:
A repository is not responsible for creating the response view data (like JSON)
A repository is not responsible for creating a response object
A repository is independent of the request/response
The method name index makes no sense because a repository is not a Controller action. Don't mix the model layer with the controller layer.
config() is a hidden dependency. The settings should also be passed via the constructor.
Instead use better separation:
Create a class BankApiClient
Dont use magic methods like __call
Instead use public methods like: getUserByNationalId(int $nationalId): UserData
and so on...
Let the controller action create / render the json response with the results of the BankApiClient.
__call is an magic method of php which allow to execute protected method outside of the object instance, this is a rupture of the class visibility.
If you want to call a method from outside it must be public
public function __construct()
{
$this->bank = new Bank()
}
Use Auto injection of the dependency
public function __construct(Bank $bank)
{
$this->bank = $bank;
}

Accessing root value and arguments resolver graphql-php

I am having issues with the following part of my code using graphql-php libraries.
'resolve' =>function($value,$args,$context)
When I run the query:
"http://localhost:8080/index.php?query={certificate(id:"123ecd"){id}}"
I get the below listed message:
{"errors":[{"message":"Internal server error","category":"internal",
"locations":[{"line":1,"column":2}],"path":["certificate"]}],"data":{"certificate":null}}
Secondly when I run a nested query
"http://192.168.211.15:8080/index.php?query{certificates{id,products{id}}}"
I get the below listed response:
{"errors":[{"message":"Internal server error","category":"internal","locations":[{"line":1,"column":26}],"path":["certificates",0,"products"]}
"data":{"certificates":[{"id":"a023gavcx","status":"Valid","products":null}]}}
Below is my complete code:
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\ResolveInfo;
class CertificateType extends ObjectType{
public function __construct(){
$config = [
'name' => 'Certificate',
'fields' => function() {
return [
'id' => [
'type' => Types::nonNull(Types::string()),
],
'number' => [
'type' => Types::int()
],
'first_issue_date' => [
'type' => Types::string()
],
'products' => [
'type' => Types::product(),
'resolve'=> function($value, $args, $context){
$pdo = $context['pdo'];
$cert_id = $value->id;
$result = $pdo->query("select * from products where cert_id = {$cert_id} ");
return $result->fetchObject() ?: null;
}
]
];
}
];
parent::__construct($config);
}
}
use GraphQL\Type\Definition\Type;
class Types extends Type{
protected static $typeInstances = [];
public static function certificate(){
return static::getInstance(CertificateType::class);
}
public static function product(){
return static::getInstance(ProductType::class);
}
protected static function getInstance($class, $arg = null){
if (!isset(static::$typeInstances[$class])) {
$type = new $class($arg);
static::$typeInstances[$class] = $type;
}
return static::$typeInstances[$class];
}
}
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\ResolveInfo;
class ProductType extends ObjectType
{
public function __construct()
{
$config = [
'name' => 'Product',
'fields' => function() {
return [
'id' => [
'type' => Types::nonNull(Types::string()),
],
'primary_activity' => [
'type' => Types::string()
],
'trade_name' => [
'type' => Types::string()
],
];
},
];
parent::__construct($config);
}
}
require_once __DIR__ . '/../../../../autoload.php';
use GraphQL\GraphQL;
use GraphQL\Type\Schema;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
define('BASE_URL', 'http://127.0.0.1:8080');
ini_set('display_errors', 0);
$debug = !empty($_GET['debug']);
if ($debug) {
$phpErrors = [];
set_error_handler(function($severity, $message, $file, $line) use (&$phpErrors) {
$phpErrors[] = new ErrorException($message, 0, $severity, $file, $line);
});
}
try {
$dbHost = 'localhost';
$dbName = '*******';
$dbUsername = 'root';
$dbPassword = '*********';
$pdo = new PDO("mysql:host={$dbHost};dbname={$dbName}", $dbUsername, $dbPassword);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$appContext = [
'pdo' => $pdo ];
if (isset($_SERVER['CONTENT_TYPE']) && strpos($_SERVER['CONTENT_TYPE'], 'application/json') !== false) {
$raw = file_get_contents('php://input') ?: '';
$data = json_decode($raw, true);
} else {
$data = $_REQUEST;
}
$data += ['query' => null, 'variables' => null];
if (null === $data['query']) {
$data['query'] = '{hello}';
}
require __DIR__ . '/types/CertificateType.php';
require __DIR__ . '/types/ProductType.php';
require __DIR__ . '/types/OrganizationType.php';
require __DIR__ . '/Types.php';
$queryType = new ObjectType([
'name' => 'Query',
'fields' => [
'hello' => [
'description' => ' Hello world',
'type' => Types::string(),
'resolve' => function() {
return 'Hello World';
}
],
'certificate' => [
'type' => Types::listOf(Types::certificate()),
'description' => 'This is the certificate identification',
'args' => [
'id' => Types::string()],
'resolve' => function ($rootValue,$args,$context) {
$pdo = $context['pdo'];
$id = $args['id'];
return $pdo->query("SELECT * from certificates where id ={$id}");
return $data->fetchObject() ?: null;
}
],
'certificates' => [
'type' => Types::listOf(Types::certificate()),
'resolve' => function($rootValue, $args, $context) {
$pdo = $context['pdo'];
$result = $pdo->query("select * from certificates order by id limit 10");
return $result->fetchAll(PDO::FETCH_OBJ);
}
],
]
]);
$schema = new Schema([
'query' => $queryType
]);
$result = GraphQL::execute(
$schema,
$data['query'],
null,
$appContext,
(array) $data['variables']
);
if ($debug && !empty($phpErrors)) {
$result['extensions']['phpErrors'] = array_map(
['GraphQL\Error\FormattedError', 'createFromPHPError'],
$phpErrors
);
}
$httpStatus = 200;
} catch (\Exception $error) {
// Handling Exception
// *************************************
$httpStatus = 500;
if (!empty($_GET['debug'])) {
$result['extensions']['exception'] = FormattedError::createFromException($error);
} else {
$result['errors'] = [FormattedError::create('Unexpected Error')];
}
}
header('Content-Type: application/json', true, $httpStatus);
echo json_encode($result);
Can somebody help me resolve these issues. Thanks in advance

Can I call a method from the same method?

I'm in a situation where I need to call the same method if any exception is thrown to ensure I'm not duplicating any code. However, it's not working as I thought. Here's the relevant code:
public static function getFolderObject($folder_id)
{
$client = new Client('https://api.box.com/{version}/folders', [
'version' => '2.0',
'request.options' => [
'headers' => [
'Authorization' => 'Bearer ' . self::getAccessToken(),
]
]
]);
$request = $client->get($folder_id);
try {
$response = $request->send();
$result = $response->json();
$files = $result['item_collection']['entries'];
} catch (BadResponseException $e) {
$result = $e->getResponse()->getStatusCode();
if ($result === 401) {
self::regenerateAccessToken();
self::getFolderObject();
}
}
return count($files) ? $files : false;
}
As you can see I'm calling the method from the method method under the if condition self::getFolderObject(); to prevent duplicate code again in under the if statement from beginning of the method. However, if I duplicate the code it works as expected. Is there any solution to achieve what I want?
You have missed to return the value and assign the folder_id:
public static function getFolderObject($folder_id)
{
$client = new Client('https://api.box.com/{version}/folders', [
'version' => '2.0',
'request.options' => [
'headers' => [
'Authorization' => 'Bearer ' . self::getAccessToken(),
]
]
]);
$request = $client->get($folder_id);
try {
$response = $request->send();
$result = $response->json();
$files = $result['item_collection']['entries'];
} catch (BadResponseException $e) {
$result = $e->getResponse()->getStatusCode();
if ($result === 401) {
self::regenerateAccessToken();
return self::getFolderObject($folder_id);
}
}
return count($files) ? $files : false;
}

Categories