Adding media to GMB location using GMB API giving error - php

I am getting this response when I try to post location image in GMB API.
For media category of ADDITIONAL, LOGO, COVER it save successfully.But when another Category is selected got this response in return. Categories options are following according to documentation.
COVER,
PROFILE,
LOGO,
EXTERIOR,
INTERIOR,
PRODUCT,
AT_WORK,
FOOD_AND_DRINK,
MENU,
COMMON_AREA,
ROOMS,
TEAMS,
ADDITIONAL
Here is my code
/**
* Edit Media for Location
* #param Acconunt ID | Int
* #param Request | mixed
* #return JSON
*/
public function createMedia($id, $request)
{
$location = $request->get('loc_id');
if($this->checkAccess($id)){
if($this->googleClient->getAccessToken()){
$gmb = new GoogleMyBusiness($this->googleClient);
try {
foreach ($request->get('file_list') as $media) {
$data['category'] = $request->get('category');
$data['media_format'] = $media['mediaFormat'];
$data['source_url'] = $media['sourceUrl'];
$media_body = $this->createMediaBodyfromArray($data);
$post = $gmb->accounts_locations_media->create($location,$media_body);
}
return response()->json(['message' => 'Media created Successfully!']);
} catch (Exception $e) {
return response()->json(['message' => 'Media not created Successfully!'],500);
}
return;
}else{
return response()->json(['message' => 'Couldn`t create Media'],500);
}
}
}
/**
* Make Nedia Object to add Media in Google Location
* #return Google_Service_MyBusiness_MediaItem
*/
public function createMediaBodyfromArray($data)
{
$media_body = new Google_Service_MyBusiness_MediaItem;
// Location Accosiation Object
$loc_acc = new Google_Service_MyBusiness_LocationAssociation;
$loc_acc->setCategory($data['category']);
$media_body->setLocationAssociation($loc_acc);
$media_body->setMediaFormat($data['media_format']);
$media_body->setSourceUrl($data['source_url']);
return $media_body;
}
request to POST /v4/accounts/{aid}/locations/{lid}/media
returns:
​{
"error": {
"code": 400,
"message": "Request contains an invalid argument.",
"status": "INVALID_ARGUMENT",
"details": [
{
"#type": "type.googleapis.com/google.mybusiness.v4.ValidationError",
"errorDetails": [
{
"code": 3,
"message": "Photo tag \'photos_at_work\' does not apply to this location",
"value": "photos_at_work"
}
]
}
]
}
}

Related

Get response of google indexing api in codeigniter

I am trying to setup google indexing api in codeigniter, I have done all steps on google cloud and search console part.
It works, but returning success message on all options event when url is not submited, that is why I want to get exact response from google instead of a created success message.
How can I display exact response from google return $stringBody;? or check for the correct response ?
Here is my controller :
namespace App\Controllers;
use App\Models\LanguageModel;
use App\Models\IndexingModel;
class IndexingController extends BaseController
{
public function initController(\CodeIgniter\HTTP\RequestInterface $request, \CodeIgniter\HTTP\ResponseInterface $response, \Psr\Log\LoggerInterface $logger)
{
parent::initController($request, $response, $logger);
$this->indexingModel = new IndexingModel();
}
public function GoogleUrl()
{
checkPermission('indexing_api');
$data['title'] = trans("indexing_api");
$data["selectedLangId"] = inputGet('lang');
if (empty($data["selectedLangId"])) {
$data["selectedLangId"] = $this->activeLang->id;
}
echo view('admin/includes/_header', $data);
echo view('admin/indexing_api', $data);
echo view('admin/includes/_footer');
}
/**
* indexing Tools Post
*/
public function indexingToolsPost()
{
checkPermission('indexing_api');
$slug = inputPost('slug');
$urltype = inputPost('urltype');
$val = \Config\Services::validation();
$val->setRule('slug', trans("slug"), 'required|max_length[500]');
if (!$this->validate(getValRules($val))) {
$this->session->setFlashdata('errors', $val->getErrors());
return redirect()->to(adminUrl('indexing_api?slug=' . cleanStr($slug)))->withInput();
} else {
$this->indexingModel->AddUrlToGoogle($slug, $urltype);
$this->session->setFlashdata('success', trans("msg_added"));
resetCacheDataOnChange();
return redirect()->to(adminUrl('indexing_api?slug=' . cleanStr($slug)));
}
$this->session->setFlashdata('error', trans("msg_error"));
return redirect()->to(adminUrl('indexing_api?slug=' . cleanStr($slug)))->withInput();
}
}
And This is my model :
namespace App\Models;
use CodeIgniter\Model;
use Google_Client;
class IndexingModel extends BaseModel {
public function AddUrlToGoogle($google_url, $Urltype){
require_once APPPATH . 'ThirdParty/google-api-php-client/vendor/autoload.php';
$client = new Google_Client();
$client->setAuthConfig(APPPATH . 'ThirdParty/google-api-php-client/xxxxxxxxx.json');
$client->addScope('https://www.googleapis.com/auth/indexing');
$httpClient = $client->authorize();
$endpoint = 'https://indexing.googleapis.com/v3/urlNotifications:publish';
$array = ['url' => $google_url, 'type' => $Urltype];
$content = json_encode($array);
$response = $httpClient->post($endpoint,['body' => $content]);
$body = $response->getBody();
$stringBody = (string)$body;
return $stringBody;
}
public function AddUrlToBing($google_url, $Urltype){
}
public function AddUrlToYandex($google_url, $Urltype){
}
}
This is a success response when I try it out of codeigniter and print_r($stringBody);
{ "urlNotificationMetadata": { "url": "https://example.com/some-text", "latestUpdate": { "url": "https://example.com/some-text", "type": "URL_UPDATED", "notifyTime": "2023-01-29T01:51:13.140372319Z" } } }
And this is an error response :
{ "error": { "code": 400, "message": "Unknown notification type. 'type' attribute is required.", "status": "INVALID_ARGUMENT" } }
But In codeigniter I get a text message "url submited" even if url not submited.
Currently you are not handling the actual response of IndexingModel->AddUrlToGoogle(). It seems your code has a validation before, so it claims, if no validation error occurs, its always a success.
So the first question to ask is, why your validation is not working here - or is it?
Secondly you could handle the actual response in any case:
IndexingController
class IndexingController extends BaseController
public function indexingToolsPost()
{
if (!$this->validate(getValRules($val))) {
// validation error
$this->session->setFlashdata('errors', $val->getErrors());
return redirect()->to(adminUrl('indexing_api?slug=' . cleanStr($slug)))->withInput();
} else {
// no validation error
$apiResponseBody = $this->indexingModel->AddUrlToGoogle($slug, $urltype);
if(array_key_exists('error', $apiResponseBody)) {
// its an error!
// either set the actual messsage
$this->session->setFlashdata('error', $apiResponseBody['error']['message']);
// OR translate it
$this->session->setFlashdata('error', trans($apiResponseBody['error']['message']));
} else {
// Its a success!
$this->session->setFlashdata('success', trans("msg_added"));
}
// ...
}
return redirect()->to(adminUrl('indexing_api?slug=' . cleanStr($slug)))->withInput();
}
And in the model, return the response as an array:
IndexingModel
public function AddUrlToGoogle($google_url, $Urltype) {
// ...
$response = $httpClient->post($endpoint,['body' => $content]);
return json_decode($response->getBody() ?? '', true); // return an array
}

Laravel set value on object to nothing doesn't work

I'm working in PHP 7.4 and Laravel 8. My model, AvailableIntegration has a column casted to an object called api_schema, I need to retain the data in the table, but for the show endpoint, set the values to null, my attempt doesn't error, and neither does it work, the original value is retained.
What am I missing?
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function show($id)
{
$integration = AvailableIntegration::where('id', $id)
->where('is_enabled', true)
->first();
if (!$integration) {
return response()->json([
'message' => "The requested integration cannot be found or is unavailable."
], 404);
}
foreach ($integration->api_schema as $key => $value) {
$integration->api_schema->{$key} = null;
}
return response()->json([
'message' => "Integration",
'integration' => $integration
], 200);
}
Desired outcome is for all the fields to be null
Raw data from model's column:
{
"channel_name": "{form_field__channel_name}"
}

Yii2 paypal payment integration

I am using this https://www.yiiframework.com/extension/bitcko/yii2-bitcko-paypal-api#usage With yii2 to enable payments my code looks like this.
public function actionMakePayment(){
if(!Yii::$app->user->getIsGuest()){
// Setup order information array
$params = [
'order'=>[
'description'=>'Payment description',
'subtotal'=>45,
'shippingCost'=>0,
'total'=>45,
'currency'=>'USD',
]
];
// In case of payment success this will return the payment object that contains all information about the order
// In case of failure it will return Null
Yii::$app->PayPalRestApi->processPayment($params);
}else{
Yii::$app->response->redirect(Url::to(['site/signup'], true));
}
Everything is went as per my expectation this call is returning somthing like this to dom.
{ "id": "PAYID-LTKUAVA8WK14445NN137182H", "intent": "sale", "state": "approved", "cart": "9RE74926AX5730813", "payer": { "payment_method": "paypal", "status": "UNVERIFIED", "payer_info": { "first_name": "Susi", "last_name": "Flo", "payer_id": "KWPDGYRP2KCK4", "shipping_address": { "recipient_name": "Susi Flo", "line1": "Suso", "line2": "bldg", "city": "Spring hill", "state": "FL", "postal_code": "34604", "country_code": "US" }, "phone": "3526003902", "country_code": "US" } }, "transactions": [ { "amount": { "total": "45.00", "currency": "USD", "details": { "subtotal": "45.00", "shipping": "0.00", "insurance": "0.00", "handling_fee": "0.00", "shipping_discount": "0.00" } }, "payee": { "merchant_id": "NHN6S6KT4FF6N", "email": "arunwebber2-facilitator#gmail.com" }, "description": "Payment description", "invoice_number": "5cd5404d624a9", "soft_descriptor": "PAYPAL *TESTFACILIT", "item_list": { "items": [ { "name": "Item one", "price": "45.00", "currency": "USD", "tax": "0.00", "quantity": 1 } ], "shipping_address": { "recipient_name": "Susi Flo", "line1": "Suso", "line2": "bldg", "city": "Spring hill", "state": "FL", "postal_code": "34604", "country_code": "US" } }, "related_resources": [ { "sale": { "id": "6LN25215GP1183020", "state": "completed", "amount": { "total": "45.00", "currency": "USD", "details": { "subtotal": "45.00", "shipping": "0.00", "insurance": "0.00", "handling_fee": "0.00", "shipping_discount": "0.00" } }, "payment_mode": "INSTANT_TRANSFER", "protection_eligibility": "ELIGIBLE", "protection_eligibility_type": "ITEM_NOT_RECEIVED_ELIGIBLE,UNAUTHORIZED_PAYMENT_ELIGIBLE", "transaction_fee": { "value": "2.43", "currency": "USD" }, "receipt_id": "3896118010137330", "parent_payment": "PAYID-LTKUAVA8WK14445NN137182H", "create_time": "2019-05-10T09:30:10Z", "update_time": "2019-05-10T09:30:10Z", "links": [ { "href": "https://api.sandbox.paypal.com/v1/payments/sale/6LN25215GP1183020", "rel": "self", "method": "GET" }, { "href": "https://api.sandbox.paypal.com/v1/payments/sale/6LN25215GP1183020/refund", "rel": "refund", "method": "POST" }, { "href": "https://api.sandbox.paypal.com/v1/payments/payment/PAYID-LTKUAVA8WK14445NN137182H", "rel": "parent_payment", "method": "GET" } ], "soft_descriptor": "PAYPAL *TESTFACILIT" } } ] } ], "create_time": "2019-05-10T09:11:48Z", "update_time": "2019-05-10T09:30:10Z", "links": [ { "href": "https://api.sandbox.paypal.com/v1/payments/payment/PAYID-LTKUAVA8WK14445NN137182H", "rel": "self", "method": "GET" } ] }
How can I store this to my database? for a specefi user id i can get user id with this.
echo Yii::$app->user->id;
I want to store this value along with the user id how can I do that? And a payment success message to the user :)
Update
Looks like the component class needs to be fully copied and edited before it can correctly override the checkOut() method as the property $apiContext accessed in the method is private rather than being $protected so either you copy that whole component and place it in you frontend/components directory and change it accordingly and then use.
Above all that class is poorly designed and written too, it would be better if you use the following component that i have been using in my Yii2 projects. I havent removed the extra code and have pasted the file as is in the answer. you can remove/comment the part related to the BalanceHistory TransactionHistory and the email part. you need to install paypal checkout sdk via composer or add below in your composer.json
"paypal/paypal-checkout-sdk": "1.0.1"
Paypal Component
<?php
namespace frontend\components;
use Yii;
use common\models\{
User,
BalanceHistory,
TransactionHistory
};
use yii\base\Component;
use common\components\Helper;
use PayPalCheckoutSdk\Core\{
PayPalHttpClient,
SandboxEnvironment,
ProductionEnvironment
};
use PayPalCheckoutSdk\Orders\{
OrdersGetRequest,
OrdersCreateRequest,
OrdersCaptureRequest
};
class Paypal extends Component
{
/**
* The Pyapal Client Id
*
* #var mixed
*/
public $clientId;
/**
* The Paypal client Secret
*
* #var mixed
*/
public $clientSecret;
/**
* API context object
*
* #var mixed
*/
private $httpClient; // paypal's http client
/**
* #var mixed
*/
private $user_id;
/**
* Override Yii's object init()
*
* #return null
*/
public function init()
{
$this->httpClient = new PayPalHttpClient(
Yii::$app->params['paypal']['mode'] == 'sandbox' ?
new SandboxEnvironment($this->clientId, $this->clientSecret) :
new ProductionEnvironment($this->clientId, $this->clientSecret)
);
$this->user_id = Yii::$app->user->id;
Yii::info("User: {$this->user_id} Init PayPal", 'paypal');
}
/**
* Returns the context object
*
* #return object
*/
public function getClient()
{
return $this->httpClient;
}
/**
* Set the payment methods and other objects necessary for making the payment
*
* #param decimal $price the amount to be charged
*
* #return string $approvalUrl
*/
public function createOrder($price)
{
//create order request
$request = new OrdersCreateRequest();
$request->prefer('return=representation');
setlocale(LC_MONETARY, 'en_US.UTF-8');
$price = sprintf('%01.2f', $price);
Yii::info("User: {$this->user_id} Setting payment for amount: {$price}", 'paypal');
//build the request body
$requestBody = [
'intent' => 'CAPTURE',
'purchase_units' =>
[
0 =>
[
'amount' =>
[
'currency_code' => 'USD',
'value' => $price,
],
],
],
'application_context' => [
'shipping_preference' => 'NO_SHIPPING'
]
];
$request->body = $requestBody;
//call PayPal to set up a transaction
$client = $this->getClient();
$response = $client->execute($request);
return json_encode($response->result, JSON_PRETTY_PRINT);
}
/**
* #param $orderId
*/
public function getOrder($orderId)
{
// 3. Call PayPal to get the transaction details
$request = new OrdersGetRequest($orderId);
$client = $this->getClient();
$response = $client->execute($request);
return json_encode($response->result, JSON_PRETTY_PRINT);
}
/**
* Retrieves Order Capture Details for the given order ID
*
* #param string $orderId the payment id of the transaction
*
* #return mixed
*/
public function captureOrder($orderId)
{
$request = new OrdersCaptureRequest($orderId);
//Call PayPal to capture an authorization
$client = $this->getClient();
$transaction = Yii::$app->db->beginTransaction();
try {
$response = $client->execute($request);
//get payment variables for email
$paymentId = $response->result->id;
$paymentStatus = $response->result->status;
$paypalTransaction = $response->result->purchase_units[0]->payments->captures[0];
$payedAmount = $paypalTransaction->amount->value;
$txnId = $paypalTransaction->id;
$userId = $this->user_id;
//get the user
$model = User::findOne($userId);
$profile = $model->businessProfile;
$prevBalance = $profile->balance;
if ($paymentStatus == 'COMPLETED') {
Yii::info("User: {$userId} payment amount:{$payedAmount} approved updating balance.", 'paypal');
//update balance
$newBalance = $profile->updateBalance($payedAmount);
Yii::info("User: {$userId} balance updated.", 'paypal');
$data = [
'amount' => $payedAmount,
'type' => TransactionHistory::BALANCE_ADDED,
'description' => "Funds added to account",
'user' => [
'id' => $userId,
'balance' => $newBalance,
],
];
Yii::info("User: {$userId} adding transaction history.", 'paypal');
TransactionHistory::add($data);
//update subscription status if required
if ($profile->subscription_status !== 'active') {
$profile->updateStatus('active');
}
Yii::info("User: {$userId} adding balance history:{$payedAmount}.", 'paypal');
//send the success email to the user and admin
$this->sendNotification($model, $response->result);
//set session flash with success
Yii::$app->session->setFlash(
'success',
'Your Payment is processed and you will receive an email with the details shortly'
);
} else {
Yii::warning("User: {$userId} payment amount:{$payedAmount} NOT approved.", 'paypal');
//send the error email to the user and admin
$this->sendNotification($model, $response->result, 'error');
//set session flash with error
Yii::$app->session->setFlash(
'danger',
'Your Payment was not approved, an email has been sent with the details.'
);
}
//update balance history
BalanceHistory::add(
$profile->user_id,
$prevBalance,
$payedAmount,
$paymentId,
$paymentStatus,
$txnId,
$response
);
//commit the transaction
$transaction->commit();
Yii::info(
"User: {$userId} payment Success prevBalance: {$prevBalance} payedAmount:{$payedAmount}.",
'paypal'
);
return json_encode($response->result, JSON_PRETTY_PRINT);
} catch (\Exception $e) {
//roll back the transaction
$transaction->rollBack();
Yii::error("ERROR EXCEPTION", 'paypal');
Yii::error($e->getMessage(), 'paypal');
Yii::error($e->getTraceAsString(), 'paypal');
//send error email to the developers
Helper::sendExceptionEmail(
"TC : Exception on PayPal Balance",
$e->getMessage(),
$e->getTraceAsString()
);
//set session flash with error
Yii::$app->session->setFlash('danger', $e->getMessage());
}
}
/**
* Sends Success Email for the transaction
*
* #param \common\models\User $model the user model object
* #param $response the paypal Order Capture object
* #param string $type the type of the notification to be sent
*
* #return null
*/
public function sendNotification(
\common\models\User $model,
$response,
$type = 'success'
) {
Yii::info("User: {$this->user_id} Sending notifications type:{$type}", 'paypal');
$paymentId = $response->id;
$paymentStatus = $response->status;
$paypalTransaction = $response->purchase_units[0]->payments->captures[0];
$payedAmount = $paypalTransaction->amount->value;
//payment creation time
$paymentCreateTime = new \DateTime(
$paypalTransaction->create_time,
new \DateTimeZone('UTC')
);
//payment update time
$paymentUpdateTime = new \DateTime(
$paypalTransaction->update_time,
new \DateTimeZone('UTC')
);
//payer/billing info for email
$payerInfo = $response->payer;
$payerEmail = $payerInfo->email_address;
$payerFirstName = $payerInfo->name->given_name;
$payerLastName = $payerInfo->name->surname;
$billingInfo = [
'billing_info' => [
'email' => $payerEmail,
'full_name' => "$payerFirstName $payerLastName",
],
];
if (property_exists($response->purchase_units[0], 'shipping')) {
$payerAddress = property_exists($response->purchase_units[0]->shipping->address, 'address_line_1');
$isStateAvailable = property_exists($response->purchase_units[0]->shipping->address, 'admin_area_1');
$isPostCodeAvailable = property_exists($response->purchase_units[0]->shipping->address, 'postal_code');
$iscountryCodeAvailable = property_exists($response->purchase_units[0]->shipping->address, 'country_code');
//#codingStandardsIgnoreStart
$payerState = $isStateAvailable ? $response->purchase_units[0]->shipping->address->admin_area_1 : 'NA';
$payerPostalCode = $isPostCodeAvailable ? $response->purchase_units[0]->shipping->address->postal_code : 'NA';
$payerCountryCode = $iscountryCodeAvailable ? $response->purchase_units[0]->shipping->address->country_code : 'NA';
//#codingStandardsIgnoreEnd
$billingInfo['billing_info'] = array_merge(
$billingInfo['billing_info'],
[
'address' => $payerAddress,
'state' => $payerState,
'country' => $payerCountryCode,
'post_code' => $payerPostalCode,
]
);
}
//email params
$data = [
'user' => [
'email' => $model->email,
'name' => $model->username,
],
'payment_id' => $paymentId,
'amount' => $payedAmount,
'status' => $paymentStatus,
'create_time_utc' => $paymentCreateTime,
'update_time_utc' => $paymentUpdateTime,
];
$data = array_merge($data, $billingInfo);
//check the notification email type and set params accordingly
if ($type == 'success') {
$txnId = $paypalTransaction->id;
$data['txn_id'] = $txnId;
$subject = Yii::$app->id . ': Your Account has been recharged.';
$view = '#frontend/views/user/mail/payment-complete';
} else {
$subject = Yii::$app->id . ': Transaction failed.';
$view = '#frontend/views/user/mail/payment-failed';
}
Yii::info("User: {$this->user_id} Sending email to user:{$model->email} type: {$type}", 'paypal');
//send email to user
$model->sendEmail($subject, $view, $data, $model->email);
//send notification to admin for Payment Received
$data['user']['email'] = Yii::$app->params['adminEmail'];
$subject = ($type == 'success') ?
Yii::$app->id . ': New Transaction in Account.' :
Yii::$app->user->id . ': A Transaction Failed for the user.';
Yii::info(
"User: {$this->user_id} Sending email to admin " . Yii::$app->params['adminEmail'] . " type: {$type}",
'paypal'
);
//send admin email
$model->sendEmail($subject, $view, $data, Yii::$app->params['adminEmail']);
}
}
Usage
You can call createOrder and then the captureOrder respectively. I was using it with ajax approach so i had separate actions defined like below
/**
* Displays fail message to the user
*
* #param string $token the cancel token
*
* #return mixed
* #throws \Exception
*/
public function actionPaymentCancel($token)
{
Yii::warning("Payment Cancel : token: {$token}.", 'paypal');
return $this->render(
'payment-cancelled',
[
'data' => $token,
]
);
}
/**
* Shows the payment details & success message to the user
*
* #param string $paymentId the payment id
*
* #return mixed
* #throws \Exception
*/
public function actionPaymentComplete($paymentId)
{
$history = BalanceHistory::findOne(['payment_id' => $paymentId]);
return $this->render(
'payment-complete',
[
'data' => $history,
]
);
}
/**
* Captures the Paypal order and verifies it
*
* #param string $orderId the Paypal order object's id
*
* #return mixed
*/
public function actionCaptureOrder($orderId)
{
$orderInfo = Yii::$app->paypal->captureOrder($orderId);
return $orderInfo;
}
/**
* Creates the order and
*
* #param string $amount the price of the order
*
* #return mixed
*/
public function actionCreateOrder($amount)
{
if (!Yii::$app->user->isGuest) {
$order = Yii::$app->paypal->createOrder($amount);
return $order;
}
throw new Exception("You are not logged in.", 404);
}
/**
* Executes the payement and checkouts to the paypal to confirm
*
* #param string $token the paypal token
*
* #return mixed
*/
public function actionPaymentExecute($orderId)
{
//get transaction details
$details = Yii::$app->paypal->getOrder($orderId);
$details = json_decode($details);
//added check for duplicate hits to return url from Paypal
if (null !== BalanceHistory::transactionExists($orderId)) {
//redirect to payment complete
return $this->redirect(['payment-complete', 'paymentId' => $orderId]);
}
if ($details->status == 'COMPLETED') {
//redirect to payment complete
return $this->redirect(['payment-complete', 'paymentId' => $orderId]);
} else {
//redirect to the payment failed page
return $this->redirect(['payment-failed', 'paymentId' => $orderId]);
}
}
ALso keep in mind that you need to declare a param with live and local ENV for the paypal gateway which turns sandbox environment ON/OFF.
params-local.php
<?php
'paypal'=>[
'sandbox'=>true
]
?>
params.php
<?php
'paypal'=>[
'sandbox'=>false
]
?>
Paypal PHP-SDK Provides you the setCustom() to add a custom field value, you can use it to send the user id and then retrieve it with the response in the transaction object after the payment is executed.
What you are using is just a custom component using the Paypal SDK functions,you should extend the class bitcko\paypalrestapi\PayPalRestApi.php to override the function checkOut() and add the ->setCustom(Yii::$app->user->id) to the chain in this line, as it does not provide any way to set the custom field, so just copy the whole code of the method into your new class and add the above.
Your class should look like below.
NOTE: Add the file inside common/components folder.
<?php
namespace common\components;
use bitcko\paypalrestapi\PayPalRestApi as PayPalBase;
use PayPal\Api\Amount;
use PayPal\Api\Details;
use PayPal\Api\Item;
use PayPal\Api\ItemList;
use PayPal\Api\Payer;
use PayPal\Api\Payment;
use PayPal\Api\RedirectUrls;
use PayPal\Api\Transaction;
use PayPal\Exception\PayPalConnectionException;
use yii\helpers\Url;
use Yii;
class PaypalRestApi extends PayPalBase
{
public function checkOut($params)
{
$payer = new Payer();
$payer->setPaymentMethod($params['method']);
$orderList = [];
foreach ($params['order']['items'] as $orderItem) {
$item = new Item();
$item->setName($orderItem['name'])
->setCurrency($orderItem['currency'])
->setQuantity($orderItem['quantity'])
->setPrice($orderItem['price']);
$orderList[] = $item;
}
$itemList = new ItemList();
$itemList->setItems($orderList);
$details = new Details();
$details->setShipping($params['order']['shippingCost'])
->setSubtotal($params['order']['subtotal']);
$amount = new Amount();
$amount->setCurrency($params['order']['currency'])
->setTotal($params['order']['total'])
->setDetails($details);
$transaction = new Transaction();
$transaction->setAmount($amount)
->setItemList($itemList)
->setDescription($params['order']['description'])
->setCustom(Yii::$app->user->id)
->setInvoiceNumber(uniqid());
$redirectUrl = Url::to([$this->redirectUrl], true);
$redirectUrls = new RedirectUrls();
$redirectUrls->setReturnUrl("$redirectUrl?success=true")
->setCancelUrl("$redirectUrl?success=false");
$payment = new Payment();
$payment->setIntent($params['intent'])
->setPayer($payer)
->setRedirectUrls($redirectUrls)
->setTransactions(array($transaction));
try {
$payment->create($this->apiContext);
return \Yii::$app->controller->redirect($payment->getApprovalLink());
} catch (PayPalConnectionException $ex) {
// This will print the detailed information on the exception.
//REALLY HELPFUL FOR DEBUGGING
\Yii::$app->response->format = \yii\web\Response::FORMAT_HTML;
\Yii::$app->response->data = $ex->getData();
}
}
}
Now change your configurations for the PayPalRestApi component class in the common/config/main.php or frontend/config/main.php whichever you are using, to the new class you created
'components'=> [
...
'PayPalRestApi'=>[
'class'=>'common\components\PayPalRestApi',
]
...
]
so now you can get the same user id by using
$response = \yii\helpers\Json::decode( Yii::$app->PayPalRestApi->processPayment($params));
$user_id = $response['transactions'][0]['custom'];

Fetch exception

I have video rooms (via Twig) being created on my page when the users want to start a video chat between each other. When they leave the room, the room is being deleted after a period of time so when I try to access it, it drops an error ({room_id} does not exist}. Below is the function:
/**
* #Route("/video/join/{room_name}", name="videochat_join")
*
* #param $room_name
*
* #return RedirectResponse|Response
*
* #throws \Twilio\Exceptions\ConfigurationException
* #throws \Twilio\Exceptions\TwilioException
*/
public function joinVideo($room_name)
{
$user = $this->getCurrentUser();
$twilio = new Client(getenv('TWILIO_API_KEY'), getenv('TWILIO_API_SECRET'));
$room = $twilio->video->v1->rooms($room_name)->fetch();
$roomSid = $room->sid;
$token = new AccessToken(getenv('TWILIO_ACCOUNT_SID'), getenv('TWILIO_API_KEY'), getenv('TWILIO_API_SECRET'), 3600, $user->getEmail());
$videoGrant = new VideoGrant();
$videoGrant->setRoom($room_name);
$token->addGrant($videoGrant);
return $this->render('chat/video_join.html.twig', [
'roomSid' => $roomSid,
'roomName' => $room_name,
'accessToken' => $token->toJWT(),
]);
};
How can I catch if the room is no longer available and forward user to 404_room.html.twig? Because it doesn't redirect to the default 404 template.
The error is:
RestException
Twilio\Exceptions\RestException:
[HTTP 404] Unable to fetch record: The requested resource /Rooms/1_2room808823 was not found
at vendor/twilio/sdk/Twilio/Version.php:85
at Twilio\Version->exception(object(Response), 'Unable to fetch record')
(vendor/twilio/sdk/Twilio/Version.php:109)
at Twilio\Version->fetch('GET', '/Rooms/1_2room808823', array())
(vendor/twilio/sdk/Twilio/Rest/Video/V1/RoomContext.php:58)
at Twilio\Rest\Video\V1\RoomContext->fetch()
(src/Controller/Chat/VideoController.php:93)
at App\Controller\Chat\VideoController->joinVideo('1_2room808823')
(vendor/symfony/http-kernel/HttpKernel.php:149)
at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), 1)
(vendor/symfony/http-kernel/HttpKernel.php:66)
at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), 1, true)
(vendor/symfony/http-kernel/Kernel.php:188)
at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
(public/index.php:37)
I have tried to do:
try{
($twilio->video->v1->rooms($room_name)->fetch());
echo "Room exists"; //this one is working fine
} catch ( TwilioException $e ) {
echo 'Caught exception: ', $e->getMessage(), "\n"; //this doesn't
}
...without luck
Add the following use statements to the top of your Controller class.
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Twilio\Exceptions\RestException;
Then wrap your code in a try/catch block. If you catch the expected RestException, then you can throw a NotFoundHttpException to force the 404 response. For example:
/**
* #Route("/video/join/{room_name}", name="videochat_join")
*
* #param $room_name
*
* #return RedirectResponse|Response
*
* #throws \Twilio\Exceptions\ConfigurationException
* #throws \Twilio\Exceptions\TwilioException
*/
public function joinVideo($room_name)
{
try {
$user = $this->getCurrentUser();
$twilio = new Client(getenv('TWILIO_API_KEY'), getenv('TWILIO_API_SECRET'));
$room = $twilio->video->v1->rooms($room_name)->fetch();
$roomSid = $room->sid;
$token = new AccessToken(getenv('TWILIO_ACCOUNT_SID'), getenv('TWILIO_API_KEY'), getenv('TWILIO_API_SECRET'), 3600, $user->getEmail());
$videoGrant = new VideoGrant();
$videoGrant->setRoom($room_name);
$token->addGrant($videoGrant);
return $this->render('chat/video_join.html.twig', [
'roomSid' => $roomSid,
'roomName' => $room_name,
'accessToken' => $token->toJWT(),
]);
}
catch (RestException $exception) {
throw new NotFoundHttpException("'{$room_name}' could not be found");
}
}

FOSRestBundle return object error

I use FOERestBundle and class View. And when I validate entity I have object error like this and this is:
[
{
"property_path": "main_skill",
"message": "This value should not be blank."
},
{
"property_path": "type",
"message": "This value should not be blank."
},
{
"property_path": "description",
"message": "This value should not be blank."
}
]
I need return object error when user not valid security token like this
[
{
"property_path": "main_skill",
"message": "This value should not be blank."
},
]
now I have plain text. This my end point
/**
* Update existing Bit from the submitted data.
*
* #ApiDoc(
* resource = true,
* description = "Update single Bit",
* parameters={
* {"name"="status", "dataType"="string", "required"=false, "description"="status for bit"},
* {"name"="text", "dataType"="string", "required"=true, "description"="text for rejected"},
* {"name"="token", "dataType"="string", "required"=true, "description"="is equally md5('email'.secret_word)"}
* },
* statusCodes = {
* 200 = "Bit successful update",
* 400 = "Secret token is not valid"
* },
* section="Bit"
* )
* #RestView()
*
* #param Request $request
* #param string $id
*
* #return View
*/
public function putBitAction(Request $request, $id)
{
$manager = $this->getDoctrine()->getManager();
$token = $this->get('request')->request->get('token');
$user = $this->getDoctrine()->getRepository('MyBundle:Users')->findOneBySecuritytoken($token);
$bit = $manager->getRepository('MyBundle:Bit')->find($id);
$view = View::create();
if (!empty($user) && !empty($bit) && !empty($token)) {
*some logic
$view = $this->view($bit, 200);
return $this->handleView($view);
}
} else {
$view = $this->view('Secret token is not valid', 400);
return $this->handleView($view);
}
}
now I have plain text
Response Body [Raw]
"Secret token is not valid"
this is return object error validate and this is ok
[
{
"property_path": "main_skill",
"message": "This value should not be blank."
},
{
"property_path": "type",
"message": "This value should not be blank."
},
{
"property_path": "description",
"message": "This value should not be blank."
}
]
How to return custom error like object not plain text?
Just pass your data like an array and tell the view to render it as json should generate an output like you wanted to
$view = $this->view(
array(
'property_path' => 'main_skill',
'message' => "error"
//whatever your object/array structure is
),
500 //error code for the error
);
$view->setFormat('json');
return $this->handleView($view);
You can use Symfony's HTTPExceptions as these will be handled by FOSRestBundle.
See: http://symfony.com/doc/current/bundles/FOSRestBundle/4-exception-controller-support.html
public function putBitAction(Request $request, $id)
{
$token = $request->get('token');
if (null === $token) {
throw new BadRequestHttpException('Provide a secret token');
}
$manager = $this->getDoctrine()->getManager();
$user = $manager->getRepository('MyBundle:Users')->findOneBySecuritytoken($token);
if (null === $user) {
throw new BadRequestHttpException('Secret token is not valid');
}
$bit = $manager->getRepository('MyBundle:Bit')->find($id);
if (null === $token) {
throw new NotFoundHttpException('Bid not found');
}
$view = $this->view($bit, 200);
return $this->handleView($view);
}
And how is this a PUT request? You should rename is to getBidAction.

Categories