I'm new to Twilio. I'm using Twilio for phone verification of my app. I'm using Laravel 5.5 for the backend & APIs. I've successfully sent the SMS to phone. I'm getting the call from Twilio but it says an application error. It doesn't read what I want to hear.
Below I'm giving every detail of my code.
Used composer require twilio/sdk for Twilio.
This is my Controller.
use Twilio\Rest\Client;
use Twilio\Twiml;
class AppUserController extends Controller{
private $account_sid;
private $auth_token;
private $twilio_number;
public function __construct(){
$this->account_sid = Config::get('envvalue.account_sid');
$this->auth_token = Config::get('envvalue.auth_token');
$this->twilio_number = Config::get('envvalue.twilio_number');
}
public function reVerification(Request $request){
$client = new Client($this->account_sid, $this->auth_token);
try {
$client->account->calls->create(
$receiverNumber,
$this->twilio_number,
array(
"url" => "http://demo.bitcanny.com/marine-admin/public/api/twiml/"
)
);
return response()->json([
'success' => true,
'statusCode' => '200',
'message' => 'Otp send again'
], 200);
}
catch (Exception $e) {
return $e->getMessage();
}
}
public function twiml(){
// A message for Twilio's TTS engine to repeat
$sayMessage = 'Hello.';
$twiml = new Twiml();
$twiml->say($sayMessage);
$response = Response::make($twiml, 200);
$response->header('Content-Type', 'text/xml');
return $response;
}
}
I found the solution. There's a silly mistake. I didn't use Response in the header of my controller.
use Response;
Related
i use the latest v2 paypal php sdk sandbox and samples with laravel framework, the create order always success but when capture the order it always fails
and return this error:
"{"name":"UNPROCESSABLE_ENTITY",
"details":[
{"issue":"COMPLIANCE_VIOLATION",
"description":"Transaction cannot be processed due to a possible compliance violation. To get more information about the transaction, call Customer Support."}],
"message":"The requested action could not be performed, semantically incorrect, or failed business validation.",
"debug_id":"d701744348160",
"links":[{"href":"https://developer.paypal.com/docs/api/orders/v2/#error-COMPLIANCE_VIOLATION","rel":"information_link","method":"GET"}]}
my web.php file :
Route::get('capture_order', 'PayController#capture_order')->name('capture_order');
Route::get('create_order', 'PayController#create_order')->name('create_order');
Route::get('cancel', 'PayController#cancel')->name('payment.cancel');
Route::get('return', 'PayController#return')->name('payment.return');
Route::get('success', 'PayController#success')->name('payment.success');
& the PayController :
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use PayPalCheckoutSdk\Core\PayPalHttpClient;
use PayPalCheckoutSdk\Core\SandboxEnvironment;
use PayPalCheckoutSdk\Orders\OrdersCreateRequest;
use PayPalCheckoutSdk\Orders\OrdersCaptureRequest;
class PayController extends Controller
{
public $clientId;
public $clientSecret;
public $client;
public $cancel_url = 'http://localhost:8000/cancel';
public $return_url = 'http://localhost:8000/return';
public function __construct()
{
$mode = config('paypal.mode', 'sandbox');
if ($mode == "live") {
$this->clientId = config('paypal.live.client_id');
$this->clientSecret = config('paypal.live.client_secret');
} else {
$this->clientId = config('paypal.sandbox.client_id');
$this->clientSecret = config('paypal.sandbox.client_secret');
}
$environment = new SandboxEnvironment($this->clientId, $this->clientSecret);
$this->client = new PayPalHttpClient($environment);
}
private function buildRequestBody()
{
return [
'intent' => 'CAPTURE',
'application_context' =>[ "cancel_url" => $this->cancel_url,
"return_url" => $this->return_url],
'purchase_units' =>
[
0 => [
'amount' =>
[
'currency_code' => 'USD',
'value' => '20'
]
]
]
];
}
public function create_order()
{
$request = new OrdersCreateRequest();
$request->prefer('return=representation');
$request->body = $this->buildRequestBody();
try {
$response = $this->client->execute($request);
foreach ($response->result->links as $key => $value) {
if ($value->rel == "approve")
{
return redirect($value->href);
}
}
}catch (\Exception $ex) {
echo $ex->statusCode;
print_r($ex->getMessage());
}
}
public function capture_order(Request $request)
{
// if ($request->token) {
$request = new OrdersCaptureRequest($request->token);
$request->prefer('return=representation');
try {
$response = $this->client->execute($request);
}catch (\Exception $ex) {
echo $ex->statusCode;
dd($ex->getMessage());
}
// }
}
/**
* Responds with a welcome message with instructions
*
* #return \Illuminate\Http\Response
*/
public function cancel(Request $request)
{
dump($request->all());
dd('Your payment is canceled. You can create cancel page here.');
}
/**
* Responds with a welcome message with instructions
*
* #return \Illuminate\Http\Response
*/
public function return(Request $request)
{
if ($request->token) {
return redirect()->route('capture_order', [
'token' => $request->token,
'PayerID' => $request->PayerID
]);
}
dd($request->all());
}
}
i use paypal php sdk with a sandbox account.
can i use the old paypal version or it's completely deprecated ?
waiting your help :)
COMPLIANCE_VIOLATION
This problem is most likely related to the country of the receiving sandbox Business account. Create a new account for a different country such as US, then create a new REST app that uses that sandbox account, and test its sandbox clientid/secret in sandbox mode instead.
For later use in live mode, ensure that if the live business account is from one of the countries that require it, that the live account has a valid auto sweep withdrawal method active and enabled on the account, such as a US bank or local visa card. If you need help configuring auto sweep for live mode, contact PayPal's business support
i call the support and the response was:
Funds received into Egyptian accounts need to be automatically withdrawn to an attached funding source, such as a bank. You can set this up by going into the account settings section of the account, then the "money, banks and cards" section and at the bottom of that page you'll find "automatic withdrawal" where you can specify a financial instrument to use for automatic withdrawals -- https://www.sandbox.paypal.com/businessmanage/account/money
thanks for u all :)
I am trying to implement Paypal Sandbox in my project. I have created a trait inside the app folder:
use GuzzleHttp\Client;
trait ConsumesExternalServices
{
public function makeRequest(
$method,
$requestUrl,
$queryParams = [],
$formParams = [],
$headers = [],
$isJsonRequest=false
) {
$client = new Client([
'base_uri' => $this->baseUri,
]);
if (method_exists($this, 'resolveAuthorization')) {
$this->resolveAuthorization($queryParams, $formParams, $headers);
}
$response = $client->request($method, $requestUrl, [
$isJsonRequest ? 'json' : 'form_params' => $formParams,
'headers' => $headers,
'query' => $queryParams,
]);
$response = $response->getBody()->getContents();
if (method_exists($this, 'decodeResponse')) {
$response = $this->decodeResponse($response);
}
return $response;
}
}
I have also created the Paypal Services:
use App\Traits\ConsumesExternalServices;
class PaypalServices
{
use ConsumesExternalServices;
protected $baseUri;
protected $clientId;
protected $clientSecret;
public function __construct()
{
$this->baseUri = config('services.paypal.base_uri');
$this->clientId = config('services.paypal.client_id');
$this->clientSecret = config('services.paypal.client_secret');
}
public function resolveAuthorization(&$queryParams, &$formParams, &$headers)
{
$headers['Authorization']=$this->resolveAccessToken();
}
public function decodeResponse($response)
{
return json_decode($response);
}
public function resolveAccessToken()
{
$credentials = base64_encode("{$this->clientId} : {$this->clientSecret}");
return "Basic {$credentials}";
}
}
I am trying to integrate my sandbox account with my project but whenever I use tinker and try to make a request, I get the following error:
Psy Shell v0.10.8 (PHP 7.4.15 — cli) by Justin Hileman
>>> $paypal=new App\Services\PaypalServices;
=> App\Services\PaypalServices {#3473}
>>> $paypal->makeRequest('GET','v1/invoicing/invoices');
GuzzleHttp\Exception\ClientException with message 'Client error: `GET https://api-m.sandbox.paypal.com/v1/invoicing/invoices` resulted in a `401 Unauthorized` response:{"error":"invalid_client","error_description":"Client Authentication failed"}
I have no idea what is the problem. Laravel version is 8 and I am using Paypal Malaysia account.
I have mentioned in .env file:
PAYPAL_BASE_URI=https://api-m.sandbox.paypal.com
PAYPAL_CLIENT_ID=
PAYPAL_CLIENT_SECRET=
Inside my config/servies.php file:
'paypal' => [
'base_uri' => env('PAYPAL_BASE_URI'),
'client_id' => env('PAYPAL_CLIENT_ID'),
'client_secret' => env('PAYPAL_CLIENT_SECRET')
],
What client-id are you using? is it sandbox? If you use a live one with the base_uri set to sandbox, it will error with that 401. You need a valid clientid+secret for the environment you're testing in, from your REST apps. If you still have issues, create a new REST app there and ensure you copy-paste from it correctly.
I am using Symfony HTTP client in an event subscriber and I set timeout to 0.1. The problem is I want the code to skip the HTTP request if took more than 0.1 second and it timedout and meanwhile no error/exception needs to be thrown. I tried try and catch but it does not work.
public function checkToken()
{
try {
$response = $this->client->request('POST','url/of/api', [
'json' => ['token' => $_ENV['USER_TOKEN']],
'timeout' => 0.1,
]);
}catch (\Exception $e){
}
}
Why it can not be handled via try and catch?
Its because responses are lazy in Symfony.
As this document mentioned:
https://symfony.com/doc/current/http_client.html#handling-exceptions
A solution is to call getContent method in try section.
private $client;
private $user_data;
public function __construct(HttpClientInterface $client)
{
$this->client = $client;
}
public function checkToken(RequestEvent $event)
{
try {
$response = $this->client->request('POST', 'url/of/api', [
'json' => ['token' => $_ENV['USER_TOKEN']],
'timeout' => 0.1,
]);
$this->user_data = $response->getContent();
} catch (\Exception $e) {
echo $e->getMessage();
}
}
I've been struggling with this for hours now, if not days and can't seem to fix it.
My Requests to Cloud Functions are being denied with error code: 401: UNAUTHENTICATED.
My Code is as follow:
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . FIREBASE_SERIVCE_PATH);
$client = new Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(Google_Service_CloudFunctions::CLOUD_PLATFORM);
$httpClient = $client->authorize();
$promise = $httpClient->requestAsync("POST", "<MyCloudFunctionExecutionUri>", ['json' => ['data' => []]]);
$promise->then(
function (ResponseInterface $res) {
echo "<pre>";
print_r($res->getStatusCode());
echo "</pre>";
},
function (RequestException $e) {
echo $e->getMessage() . "\n";
echo $e->getRequest()->getMethod();
}
);
$promise->wait();
I'm currently executing this from localhost as I'm still in development phase.
My FIREBASE_SERIVCE_PATH constant links to my service_account js
My Cloud Function index.js:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
// CORS Express middleware to enable CORS Requests.
const cors = require('cors')({
origin: true,
});
exports.testFunction = functions.https.onCall((data, context) => {
return new Promise((resolve, reject) => {
resolve("Ok:)");
});
});
// [END all]
My Cloud Function Logs:
Function execution took 459 ms, finished with status code: 401
What am I doing wrong so I get Unauthenticated?
PS: My testFunction works perfectly when invoked from my Flutter mobile app who uses: https://pub.dartlang.org/packages/cloud_functions
Update:
I have followed this guide: https://developers.google.com/api-client-library/php/auth/service-accounts but in the "Delegating domain-wide authority to the service account" section, it only states If my application runs in a Google Apps domain, however I wont using Google Apps domain, and plus I'm on localhost.
First of all thanks to Doug Stevenson for the answer above! It helped me to get a working solution for callable functions (functions.https.onCall).
The main idea is that such functions expect the auth context of the Firebase User that already logged in. It's not a Service Account, it's a user record in the Authentication section of your Firebase project. So, first, we have to authorize a user, get the ID token from response and then use this token for the request to call a callable function.
So, below is my working snippet (from the Drupal 8 project actually).
use Exception;
use Google_Client;
use Google_Service_CloudFunctions;
use GuzzleHttp\Psr7;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Promise;
use GuzzleHttp\RequestOptions;
$client = new Google_Client();
$config_path = <PATH TO SERVICE ACCOUNT JSON FILE>;
$json = file_get_contents($config_path);
$config = json_decode($json, TRUE);
$project_id = $config['project_id'];
$options = [RequestOptions::SYNCHRONOUS => TRUE];
$client->setAuthConfig($config_path);
$client->addScope(Google_Service_CloudFunctions::CLOUD_PLATFORM);
$httpClient = $client->authorize();
$handler = $httpClient->getConfig('handler');
/** #var \Psr\Http\Message\ResponseInterface $res */
$res = $httpClient->request('POST', "https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=<YOUR FIREBASE PROJECT API KEY>", [
'json' => [
'email' => <FIREBASE USER EMAIL>,
'password' => <FIREBASE USER PASSWORD>,
'returnSecureToken' => TRUE,
],
]);
$json = $res->getBody()->getContents();
$data = json_decode($json);
$id_token = $data->idToken;
$request = new Request('POST', "https://us-central1-$project_id.cloudfunctions.net/<YOUR CLOUD FUNCTION NAME>", [
'Content-Type' => 'application/json',
'Authorization' => "Bearer $id_token",
], Psr7\stream_for(json_encode([
'data' => [],
])));
try {
$promise = Promise\promise_for($handler($request, $options));
}
catch (Exception $e) {
$promise = Promise\rejection_for($e);
}
try {
/** #var \Psr\Http\Message\ResponseInterface $res */
$res = $promise->wait();
$json = $res->getBody()->getContents();
$data = json_decode($json);
...
}
catch (Exception $e) {
}
Callable functions impose a protocol on top of regular HTTP functions. Normally you invoke them using the Firebase client SDK. Since you don't have an SDK to work with that implements the protocol, you'll have to follow it yourself. You can't just invoke them like a normal HTTP function.
If you don't want to implement the protocol, you should instead use a regular HTTP function, and stop using the client SDK in your mobile app.
I am trying to configure guard with an OAuth 2 connection.
I am trying to do this with a redirection in the getCredentials function to the Microsoft login website but I can't make it work. I don't know how I can make it worked.
It seems there is no redirection possible in this function.
public function getCredentials(Request $request)
{
$provider = new Microsoft([
'clientId' => '0000000032624',
'clientSecret' => 'my-secret',
'redirectUri' => 'https://mysite/oauthlogin'
]);
if(!$request->query->has('code')){
// If we don't have an authorization code then get one
$authUrl = $provider->getAuthorizationUrl();
$request->getSession()->set('oauth2state', $provider->getState());
//This doesn't work
return new RedirectResponse($authUrl);
// Check given state against previously stored one to mitigate CSRF attack
}elseif ( empty($request->query->get('state')) || ($request->query->get('state')!==$request->getSession()->get('oauth2state')) ){
return null;
}else{
// Try to get an access token (using the authorization code grant)
$token = $provider->getAccessToken('authorization_code', [
'code' => $request->query->get('code')
]);
try {
//when log with microsoft, check if user is allowed
// We got an access token, let's now get the user's details
$user = $provider->getResourceOwner($token);
} catch (Exception $e) {
// Failed to get user details
}
}
}
public function getUser($credentials, UserProviderInterface $userProvider)
{
return $userProvider->loadUserByUsername($user->getEmail());
}
public function checkCredentials($credentials, UserInterface $user)
{
// check credentials - e.g. make sure the password is valid
// no credential check is needed in this case
// return true to cause authentication success
return true;
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
$url = $this->router->generate('homepage');
return new RedirectResponse($url);
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
$data = array(
'message' => strtr($exception->getMessageKey(), $exception->getMessageData())
// or to translate this message
// $this->translator->trans($exception->getMessageKey(), $exception->getMessageData())
);
$request->getSession()->set(Security::AUTHENTICATION_ERROR, $data);
$url = $this->router->generate('login');
return new RedirectResponse($url);
}
Function getCredentials() is not supposed to return a Response, it provide the credentials used in getUser().
In the getUser() documentation :
The credentials are the return value from getCredentials()
You may throw an AuthenticationException if you wish. If you return
null, then a UsernameNotFoundException is thrown for you.
In case of exception thrown, onAuthenticationFailure() is called and here you can return your RedirectResponse.
For more detailled informations, see the source code of the \Symfony\Component\Security\Guard\GuardAuthenticatorInterface which contains a lots of explanations in its methods.