Cant access Firestore documents from PHP scripts with API key - php

I am new to Firebase/Firestore. I have created 2 projects that access the same data in Firestore.
One is in android and the other a web app in php. I am able to access data in android app but in PHP app
i had to create an API key in the credentials page. I want to use Firestore on trial basis initially but am not able to access the documents . It gives an error
Fatal error: Uncaught RuntimeException: Credentials fetcher does not implement Google\Auth\UpdateMetadataInterface in C:\xampp\htdocs\FirestoreProject\vendor\google\auth\src\FetchAuthTokenCache.php:190 Stack trace: #0 C:\xampp\htdocs\FirestoreProject\vendor\google\gax\src\CredentialsWrapper.php(197): Google\Auth\FetchAuthTokenCache->updateMetadata(Array, 'https://firesto...') #1 [internal function]: Google\ApiCore\CredentialsWrapper->Google\ApiCore{closure}(Object(stdClass)) #2 C:\xampp\htdocs\FirestoreProject\vendor\grpc\grpc\src\lib\ServerStreamingCall.php(44): Grpc\Call->startBatch(Array) #3 C:\xampp\htdocs\FirestoreProject\vendor\grpc\grpc\src\lib\BaseStub.php(364): Grpc\ServerStreamingCall->start(Object(Google\Cloud\Firestore\V1\BatchGetDocumentsRequest), Array, Array) #4 C:\xampp\htdocs\FirestoreProject\vendor\grpc\grpc\src\lib\BaseStub.php(589): Grpc\BaseStub->Grpc{closure}('/google.firesto...', Object(Google\Cloud\Firestore\V1\BatchGetDocumentsRequest), Array, Array, Array) #5 C:\xampp\htdocs\FirestoreProject\ve in C:\xampp\htdocs\FirestoreProject\vendor\google\auth\src\FetchAuthTokenCache.php on line 190
I have installed composer and updated the dependencies and gRPC.
My index.php file reads
<?php
session_start();
require_once 'vendor/autoload.php';
require_once "Firestore.php";
$apiKey = 'WWWWWWWWWWWWWWWWWWWWWW';
$url ='https://console.firebase.google.com/project/prject-ID/firestore?
key=Aasdads';
$fs = new Firestore('Users');
print_r($fs->getDocument('9427349073'));
return;
?>
My Firestore.php file reads
<?php
use Google\Cloud\Core\Exception\GoogleException;
use Google\Cloud\Firestore\FirestoreClient;
class Firestore
{
protected $db;
protected $name; // $name is name of collection
public function __construct(string $collection) // $collection =
// 'Users'
{
if (isset($this)) {
try {
$this->db = new FirestoreClient([
'projectId' => 'XXXXXXXXXXXXXXXXXXX'
]);
$this->name = $collection;
} catch (GoogleException $e) {
print_r($e->getMessage());
}
}else{
}
}
public function getDocument(string $name) // $name is name of document
{
return $this->db->collection($this->name)->document($name)-
>snapshot()->data();
}
}
?>
I tried activating the Credentials Page but they are asking for Credit card for billing to start trial , which i dont have. Cant we test the database without activating the Credentials? What is the difference between testing and trial basis usage ?
Please help
regards
Sanjish
I have made a test.php file after creating a service account and pointing to the key.json file on command prompt using set GOOGLE_APPLICATION_CREDENTIALS
<?php
require_once 'vendor/autoload.php';
session_start();
use Google\Cloud\Firestore\FirestoreClient;
initialize();
function initialize()
{
// Create the Cloud Firestore client
$db = new FirestoreClient([
'projectId' => 'Valbhai-xxx'
]);
$usersRef = $db->collection('Users'); // This works
$snapshot = $usersRef->documents(); // This does not work , gives
// the same error
foreach ($snapshot as $user) {
printf('User: %s' . PHP_EOL, $user->client_name());
}
}
?>

I reproduced your issue on my computer and I noticed that this is because PHP is ignoring the environment variable GOOGLE_APPLICATION_CREDENTIALS, because this is not defined for the user Apache(or httpd) in order to fix this I modified the initialization by using this code block
$db = new FirestoreClient([
'keyFilePath' => '/path/to/credentials.json',
'projectId' => 'my-project-id'
]);
With keyFilePath (this parameter is documented here), Firestore library going to search the GCP credentials using the string of the path instead the environment variable

Related

How do I authenticate a service account in Google Cloud Services in PHP?

While developing Recaptcha Enterprise for use of the V2 "I am not a robot" checkbox, I am stuck on this error:
Fatal error: Uncaught DomainException: Could not load the default credentials. Browse to https://developers.google.com/accounts/docs/application-default-credentials for more information
I follow the link and have settled on this to authenticate:
use Google\Cloud\Storage\StorageClient;
$storage = new StorageClient([
'keyFile' => json_decode(file_get_contents($path_to_keyfile), true),
'projectId' => 'MY_PROJECT'
]);
I cannot find anything else that suggests I need to do anything more than this, and this link to the constructor API doesn't suggest I can pass it in as a parameter and then proceed. I do not want to use environment variables for this project, I want to connect manually in the code. What am I missing? I can confirm I have a working service account.
If it's helpful, the code I'm trying to run after I presumably authenticate is this:
// ==================== CAPTCHA ===================
use Google\Cloud\RecaptchaEnterprise\V1\RecaptchaEnterpriseServiceClient;
use Google\Cloud\RecaptchaEnterprise\V1\Event;
use Google\Cloud\RecaptchaEnterprise\V1\Assessment;
use Google\Cloud\RecaptchaEnterprise\V1\TokenProperties\InvalidReason;
$captcha_response = $_POST['g-recaptcha-response'];
$site_key = "123456789abc";
$client = new RecaptchaEnterpriseServiceClient();
define('SITE_KEY', $site_key);
define('TOKEN', $captcha_response);
define('PROTECTED_ACTION', 'signup');
define('PARENT_PROJECT', 'projects/MY_PROJECT');
$event = (new Event())
->setSiteKey(SITE_KEY)
->setExpectedAction(PROTECTED_ACTION)
->setToken(TOKEN);
$assessment = (new Assessment())
->setEvent($event);
try {
$response = $client->createAssessment(
PARENT_PROJECT,
$assessment
);
if ($response->getTokenProperties()->getValid() == false) {
printf('The CreateAssessment() call failed because the token was invalid for the following reason: ');
printf(InvalidReason::name($response->getTokenProperties()->getInvalidReason()));
} else {
if ($response->getEvent()->getExpectedAction() == PROTECTED_ACTION) {
printf('The score for the protection action is:');
printf($response->getRiskAnalysis()->getScore());
}
else
{
printf('The action attribute in your reCAPTCHA tag does not match the action you are expecting to score');
}
}
} catch (exception $e) {
printf('CreateAssessment() call failed with the following error: ');
printf($e);
}
Here's how I got it working. Thanks to John Hanley for the help in a previous answer. The documentation had lead me to believe that (for whatever reason) Storage was required, but that was not the case: it was as simple as providing the path to the key via the credentials parameter. Not the keyFile parameter.
if (empty($_POST['g-recaptcha-response']))
die("You have failed the not-a-robot check.");
$captcha_response = $_POST['g-recaptcha-response'];
require 'composer/vendor/autoload.php';
use Google\Cloud\RecaptchaEnterprise\V1\RecaptchaEnterpriseServiceClient;
use Google\Cloud\RecaptchaEnterprise\V1\Event;
use Google\Cloud\RecaptchaEnterprise\V1\Assessment;
use Google\Cloud\RecaptchaEnterprise\V1\TokenProperties\InvalidReason;
$path_to_keyfile = "MY_PROJECT-1234567890abc.json";
$site_key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
$client = new RecaptchaEnterpriseServiceClient([
'credentials' => $path_to_keyfile,
'projectId' => 'MY_PROJECT'
]);
define('SITE_KEY', $site_key);
define('TOKEN', $captcha_response);
define('PROTECTED_ACTION', 'signup');
define('PARENT_PROJECT', 'projects/MY_PROJECT');
$event = (new Event())
->setSiteKey(SITE_KEY)
->setExpectedAction(PROTECTED_ACTION)
->setToken(TOKEN);
$assessment = (new Assessment())
->setEvent($event);
try {
$response = $client->createAssessment(PARENT_PROJECT, $assessment);
if ($response->getTokenProperties()->getValid() == false) {
printf('The CreateAssessment() call failed because the token was invalid for the following reason: ');
printf(InvalidReason::name($response->getTokenProperties()->getInvalidReason()));
exit;
} else {
if ($response->getEvent()->getExpectedAction() == PROTECTED_ACTION) {
// Closer to 1 = human, to 0 = robot.
$bot_score = $response->getRiskAnalysis()->getScore();
// do what you want with the score here...
} else {
die('The action attribute in your reCAPTCHA tag does not match the action you are expecting to score');
}
}
} catch (exception $e) {
printf('CreateAssessment() call failed with the following error: ');
printf($e);
exit;
}
Your problem is that you are not specifying the service account to use in the client constructor and the system is falling back to using ADC (Application Default Credentials).
ADC will check the environment variable GOOGLE_APPLICATION_CREDENTIALS for the service account JSON key file.
You can set the environment variable before running your program:
Windows:
set GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
Linux:
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
Or modify your program by changing this line of code:
$client = new RecaptchaEnterpriseServiceClient();
To this:
$options = ['keyFile' => $path_to_keyfile];
$client = new RecaptchaEnterpriseServiceClient($options);
Note 1:
If you are running your program on a Google Cloud computer service such as Compute Engine, App Engine, Cloud Run, ... the default service account will be used if neither of the above methods are implemented.
Note 2:
While developing, another method is to use the CLI's application default credentials. Run the following command using the Google Cloud SDK CLI:
gcloud auth application-default login
However, I have not verified that the reCAPTCHA Enterprise library checks for this type of credential.

How to install and use Facebook PHP SDK without Composer

I'm trying to embed Server Side conversion in a website (due to iOS 14 update) but I'm experiencing issues with the PHP SDK so everytime I try a conversion code in a page it turns out Fatal Error.
So my question is, how can I use/embed correctly these conversions code?
Thanks in advance to who will answer
EDIT: To explain better
I Downloaded the Facebook Php SDK from here https://php-download.com/package/facebook/php-sdk-v4 and then I uploaded in my website root, after that I've included the following code(from https://developers.facebook.com/docs/marketing-api/conversions-api/payload-helper ) in a thank you page to track "purchase" conversion:
<?php
define('SDK_DIR', __DIR__ . '/..'); // Path to the SDK directory
$loader = include SDK_DIR . '/vendor/autoload.php';
use FacebookAds\Api;
use FacebookAds\Logger\CurlLogger;
use FacebookAds\Object\ServerSide\Content;
use FacebookAds\Object\ServerSide\CustomData;
use FacebookAds\Object\ServerSide\DeliveryCategory;
use FacebookAds\Object\ServerSide\Event;
use FacebookAds\Object\ServerSide\EventRequest;
use FacebookAds\Object\ServerSide\Gender;
use FacebookAds\Object\ServerSide\UserData;
// Configuration.
// Should fill in value before running this script
$access_token = null;
$pixel_id = null;
if (is_null($access_token) || is_null($pixel_id)) {
throw new Exception(
'You must set your access token and pixel id before executing'
);
}
// Initialize
Api::init(null, null, $access_token);
$api = Api::instance();
$api->setLogger(new CurlLogger());
$events = array();
$user_data_0 = (new UserData())
->setEmail("hashed email");
$custom_data_0 = (new CustomData())
->setValue(142.52)
->setCurrency("USD");
$event_0 = (new Event())
->setEventName("Purchase")
->setEventTime(1620379012)
->setUserData($user_data_0)
->setCustomData($custom_data_0)
->setActionSource("email");
array_push($events, $event_0);
$request = (new EventRequest($pixel_id))
->setEvents($events);
$request->execute();
Of course this code do not contain token and pixel ID but in the website I filled all the variables with the right values.
I also adjusted the require on top with the right path and then i got the following error in the page:
Fatal error: Uncaught Error: Class 'FacebookAds\Api' not found in mywebsite/public_html/template/includes/analyticstracking2.inc.php:60 Stack trace: #0 /mywebsite/public_html/it/thankyou_page.php(134): require() #1 {main} thrown in mywebsite/public_html/template/includes/analyticstracking2.inc.php on line 60
On line 60 there's the following: Api::init(null, null, $access_token);
Onestly I do not understand where the issue it's coming from.
Now to answer to 'why do not use composer' I can't from a shared hosting server, if someone knows howo to do maybe I can start from there.

How to fix "Class not found" Error for the Google Sheets API?

I am trying to set up a website that has google sheets API functionality, due to the constraints of the hosting service, I installed the API on my local computer with Composer before uploading everything onto the site. However, when I try creating the Google_Service_Sheets object, it says that the class cannot be found.
I've tried recreating the autoload.php file, and also adding a seperate require function:
require_once "./googleapi/google-api-php-client-2.2.3/vendor/google/apiclient-services/src/Google/Service/Sheets.php";
Main code:
require_once $configs["googleapifilev2"];
require_once "./googleapi/google-api-php-client-2.2.3/vendor/google/apiclient-services/src/Google/Service/Sheets.php";
$client = new \Google_Client();
$client->setApplicationName('test');
$client->setScopes([\Google_Service_Sheets::SPREADSHEETS]);
$client->setAccessType('offline');
$client->setAuthConfig($configs["googlecredentials"]);
$service = new \Google_Service_Sheets($client);
autoload.php code:
<?php
// autoload.php #generated by Composer
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit68a7a3a3b2a74c49476ad55dd7b1c990::getLoader();
An error occurs only when I call the Google_Service_Sheets object, but not the Google_Client.
Error message:
Fatal error: Uncaught Error: Class 'Google_Service_Sheets_Resource_Spreadsheets' not found in /storage/ssd3/963/10211963/public_html/googleapi/google-api-php-client-2.2.3/vendor/google/apiclient-services/src/Google/Service/Sheets.php:69
Stack trace:
#0 /storage/ssd3/963/10211963/public_html/twowvotingaction.php(56): Google_Service_Sheets->__construct(Object(Google_Client))
#1 {main} thrown in /storage/ssd3/963/10211963/public_html/googleapi/google-api-php-client-2.2.3/vendor/google/apiclient-services/src/Google/Service/Sheets.php on line 69
(Related lines in the API sheets.php file):
public function __construct(Google_Client $client, $rootUrl = null)
{
parent::__construct($client);
$this->rootUrl = $rootUrl ?: 'https://sheets.googleapis.com/';
$this->servicePath = '';
$this->batchPath = 'batch';
$this->version = 'v4';
$this->serviceName = 'sheets';
$this->spreadsheets = new Google_Service_Sheets_Resource_Spreadsheets( //Line 69
$this,
$this->serviceName,
'spreadsheets',
For some reason, when uploading the files, I accidentally put the ./googleapi/google-api-php-client-2.2.3/vendor/google/apiclient-services/src/Google/Service/Sheets folder, which defines the class, in the wrong directory, I moved it, and it now works.

Magento 2 access Rest API interface from root file

I have created a script file in root and I want to create a new customer from that file below is my code for that.
use Magento\Framework\App\Bootstrap;
//use Magento\Customer\Api\Data\CustomerInterface;
require __DIR__ . '/../../app/bootstrap.php';
$bootstrap = Bootstrap::create(BP, $_SERVER);
$obj = $bootstrap->getObjectManager();
$obj->get('Magento\Framework\App\State')->setAreaCode('frontend');
$customerData = [
'customer' => [
'email' => 'demo#user.com',
'firstname' => 'John',
'lastname' => 'Wick',
],
'password' => 'John123'
];
$customer=$obj->get('\Magento\Customer\Api\AccountManagementInterface');
$customer->createAccount($customerData);
but when i run this code it gives me below error.
Fatal error: Uncaught TypeError: Argument 1 passed to Magento\Customer\Model\AccountManagement\Interceptor::createAccount() must be an instance of Magento\Customer\Api\Data\CustomerInterface, array given, called in C:\wamp64\www\mg\m2\rest\v3\Customer.php on line 82 and defined in C:\wamp64\www\mg\m2\generated\code\Magento\Customer\Model\AccountManagement\Interceptor.php:124
Stack trace:
0 C:\wamp64\www\mg\m2\rest\v3\Customer.php(82): Magento\Customer\Model\AccountManagement\Interceptor->createAccount(Array)
1 C:\wamp64\www\mg\m2\rest\v3\api.php(7): require_once('C:\wamp64\www\m...')
2 {main}
thrown in
C:\wamp64\www\mg\m2\generated\code\Magento\Customer\Model\AccountManagement\Interceptor.php on line
124
Please help. actually i want to access web api method directly from code and get response so that i can modify that response accordingly. because we already have app running in magento 1.9. so we don't want to change response
It's just like the error message says. You have to pass an implementation of Magento\Customer\Api\Data\CustomerInterface to the createAccount method.
So instead of passing a simple array like $customerData, you should create a new instance of a CustomerInterface implementation instead ... and fill it with the required data.
Searching through their github repo I found this:
Magento\Customer\Model\Data\Customer
https://github.com/magento/magento2/search?utf8=%E2%9C%93&q=%22implements+Magento%5CCustomer%5CApi%5CData%5CCustomerInterface%22&type=
So unless you want to create your own implementation, this is what you should pass to createAccount
You should be able to create one via the factory like so:
try {
$objectManager = $bootstrap->getObjectManager();
$objectManager->get(Magento\Framework\App\State::class)
->setAreaCode(\Magento\Framework\App\Area::AREA_FRONTEND);
/** #var \Magento\Customer\Api\Data\CustomerInterfaceFactory $customerFactory */
$customerFactory = $objectManager->create(\Magento\Customer\Api\Data\CustomerInterfaceFactory::class);
$customer = $customerFactory->create();
$customer
->setEmail('justincase#test123.xyz')
->setFirstname('Justin')
->setLastname('Case');
/** #var \Magento\Customer\Api\AccountManagementInterface $accountManager */
$accountManager = $objectManager->create(\Magento\Customer\Api\AccountManagementInterface::class);
$accountManager->createAccount($customer);
} catch (Exception $e) {
echo $e->getMessage();
}
Ok, since I was curious, I quickly (lol) installed magento2 myself. With the above example I was able to create a customer on a fresh magento2 install.

How to properly set up Google cloud vision on my localhost in PHP?

I want to use Google cloud Vision for detecting image properties. I have created an account with Google Cloud and found the exact solution on one of their code snippet here (https://cloud.google.com/vision/docs/detecting-properties#vision-image-property-detection-gcs-php).
I copied and adjust it to what I want to achieve. I installed their package using composer google/cloud-vision.
So here is my code:
<?php
namespace Google\Cloud\Samples\Vision;
use Google\Cloud\Vision\VisionClient;
$projectId = 'YOUR_PROJECT_ID';
$path = 'event1.jpg';
function detect_image_property($projectId, $path)
{
$vision = new VisionClient([
'projectId' => $projectId,
]);
$image = $vision->image(file_get_contents($path), [
'IMAGE_PROPERTIES'
]);
$result = $vision->annotate($image);
print("Properties:\n");
foreach ($result->imageProperties()->colors() as $color) {
$rgb = $color['color'];
printf("red:%s\n", $rgb['red']);
printf("green:%s\n", $rgb['green']);
printf("blue:%s\n\n", $rgb['blue']);
}
}
detect_image_property($projectId, $path);
?>
So when I run my code it throws this error:
Fatal error: Uncaught Error: Class 'Google\Cloud\Vision\VisionClient' not found in C:\xampp\htdocs\vision\index.php:12 Stack trace: #0 C:\xampp\htdocs\vision\index.php(28): Google\Cloud\Samples\Vision\detect_image_property('YOUR_PROJECT_ID', 'event1.jpg') #1 {main} thrown in C:\xampp\htdocs\vision\index.php on line 12
Now am wondering what is the next step for me, also what will be my
$projectId = 'YOUR_PROJECT_ID'
*Please, if this question needs more explanation let me know in the comment instead of downvoting.
Thanks.
#Abiodun Adetona
Project-Id : This is the private key, we've to generate using Google cloud vision for example - https://cloud.google.com/vision/docs/libraries#client-libraries-install-php
As per the error, we can say it's not able to find your file - Google\Cloud\Samples\Vision;
To avoid this we've to load
require __DIR__ . '/vendor/autoload.php'; file before using them
namespace Google\Cloud\Samples\Vision;

Categories