I have a couple actions that I use redirects on but after transitioning to a new server all redirects now result in blank pages. I am not getting any errors in the logs and I already tried the suggestions in this question YII2 redirect causes blank page
When I echo var_dump(headers_sent()) it returns false. The Yii debug log displays the 405 status code also. Below is my action.
I've tried even using header("Location: http://www.google.com") and it also results in a blank page
public function actionDashboard()
{
if(strtotime(UserInfo::findOne(Yii::$app->user->Id)->active_until) < strtotime(date("Y-m-d H:i:s"))){
Yii::$app->session->setFlash('warning', 'Please subscribe below.');
return $this->redirect(['site/subscription'], 405);
}
$model = new Score();
$deadlines = new EDeadlines();
return $this->render('dashboard', [
'deadlines' => $deadlines,
'model' => $model,
]);
}
public function actionSubscription()
{
Stripe::setApiKey(Yii::$app->params['stripe_sk']);
$userInfo = UserInfo::findOne(Yii::$app->user->Id);
$userInfo->customer_id != NULL ? $customer = Customer::retrieve($userInfo->customer_id) : $customer = NULL;
$userPayments = StripeInvoice::find()
->where('customer_id=:customer_id', [':customer_id' => $userInfo['customer_id']])
->orderBy(['date' => SORT_DESC])
->all();
$redeem_ch = NULL;
$customer != NULL ? $account_balance = $customer->account_balance : $account_balance = 0;
if($account_balance <= -1000 && $userInfo->refund_redeemed == 0):
$redeem_ch = StripeInvoice::find()->where(['refunded' => 0, 'customer_id' => $userInfo->customer_id])->one();
$userInfo->redeem_charge = $redeem_ch->charge_id;
$userInfo->save();
endif;
return $this->render('subscription', [
'userInfo' => $userInfo,
'customer' => $customer,
'account_balance' => $account_balance,
'userPayments' => $userPayments,
'referral_count' => UserInfo::find()->where(['referrer_code' => $userInfo->your_referral_code])->count(),
]);
}
You're using incorrect status code - 405 is not for redirections:
The HyperText Transfer Protocol (HTTP) 405 Method Not Allowed response status code indicates that the request method is known by the server but is not supported by the target resource.
The server MUST generate an Allow header field in a 405 response containing a list of the target resource's currently supported methods.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/405
You should remove this status from method call:
return $this->redirect(['site/subscription']);
Yii will use temporary redirection (302) which should be fine in this case.
Avoid array
return $this->redirect('site/subscription', 405);
and eventually use url::to
use yii\helpers\Url;
.....
return $this->redirect(Url::to(['/site/subscription'])', 405);
Be sure you effectively need 405 (405 Method Not Allowed) instead of (302 Found = default)
Related
I am trying to redirect user to different url after certain event has fired but I keep receiving this error:
Symfony\Component\HttpFoundation\Response::setContent(): Argument #1 ($content) must be of type ?string, Illuminate\Routing\Redirector given, called in /var/www/html/vendor/laravel/framework/src/Illuminate/Http/Response.php on line 72
I have event listener in EventServiceProvider:
\Slides\Saml2\Events\SignedIn::class => [
SamlLoginListener::class.'#handle',
]
and then in SamlLoginListener:
public function handle(SignedIn $event)
{
$messageId = $event->auth->getLastMessageId();
// your own code preventing reuse of a $messageId to stop replay attacks
$samlUser = $event->auth->getSaml2User();
$user_data = [
'id' => $samlUser->getUserId(),
'attributes' => $samlUser->getAttributes(),
'assertion' => $samlUser->getRawSamlAssertion()
];
AuthController::saml_login($user_data);
}
Then In the AuthController::saml_login I tried all of these but the response was allways the same error:
return redirect()->away($frontend_url, 302, [
'X-SSO-AUTH-TOKENS' => json_encode($data),
]);
//
$response = new RedirectResponse($redirect_url, 302, [
'X-SSO-AUTH-TOKENS' => json_encode($data),
]);
return $response;
//
return redirect($redirect_url, 302, [
'X-SSO-AUTH-TOKENS' => json_encode($data),
]);
I decided to try it again by just returning 'ok' but still received the same error. I tried clearing the cache - no result.
Here is the full error trace: https://pastebin.com/4eZYni0w
The answer to the problem is in the error message. Your error is saying that the redirect helper method expects a string, but you're passing an object.
Not sure what version of Laravel you're using but in Laravel, Redirect responses are instances of the Illuminate\Http\RedirectResponse class and contain the proper headers needed to redirect the user to another URL.
you can try:
return redirect('/frontend_route');
Redirect to named route:
return redirect()->route('frontend_route');
If this your route has parameters like in your case, here's what to do:
return redirect()->route('frontend_route', ['X-SSO-AUTH-TOKENS' => json_encode($data)]);
Hope this helps.
source: Redirects in Laravel 8
I ended up doing this and it worked:
header("Location: " . $redirect_url);
header("X-SSO-AUTH-TOKENS: " . json_encode($data));
exit();
I am trying to integrate the Cashfree payment gateway in my Laravel 8 project. The only issue I face is in the callback URL, where an active session is automatically destroyed after getting the post data from Payment Gateway. I have also added the CSRF exception to Middleware. I have added 'secure' => env('SESSION_SECURE_COOKIE', false) & 'same_site' => null.
I have tried with a redirect()->away($payment_link), iFrame tag, and form submits directly to payment link but still getting the same issue.
The session is getting destroyed in the Mozilla browser, but it works fine in the chrome browser.
Controller (Generate Payment Request, URL, and Process Callback)
class PaymentController extends Controller
{
public function credits_add()
{
AuthCheck();
$this->data['page_name'] = 'Add Credits';
return view('merchant.payment.add_credits', $this->data);
}
public function credits_save(Request $request)
{
$request->validate([
'credit_amount' => 'required',
'credit_transaction_type' => 'required'
]);
if (!empty($request->input('credit_transaction_type')) && $request->input('credit_transaction_type') == 'Cashfree') {
$cashfreeDetails = $this->pay_with_cashfree($request);
if (!empty($cashfreeDetails) && !empty($cashfreeDetails['paymentLink'])) {
return Redirect::to($cashfreeDetails['paymentLink']);
} else {
return redirect('credits/add')->with('errorMessage', 'Sorry! Your transaction has failed.');
}
}
return redirect('credits/add');
}
public function pay_with_cashfree($request)
{
$order = new Order();
$od["orderId"] = "ORDER-84984941";
$od["orderAmount"] = 10000;
$od["orderNote"] = "Subscription";
$od["customerPhone"] = "9000012345";
$od["customerName"] = "Test Name";
$od["customerEmail"] = "test#cashfree.com";
$od["returnUrl"] = route('CreditsSuccess');
$od["notifyUrl"] = route('CreditsSuccess');
$order->create($od);
$linkArray = $order->getLink($od['orderId']);
$detailsArray = $order->getDetails($od['orderId']);
if (!empty($order) && !empty($linkArray) && !empty($linkArray->status) && $linkArray->status == 'OK') {
return array(
'paymentLink' => $linkArray->paymentLink,
'paymentDetails' => $detailsArray
);
} else {
return array();
}
}
public function credits_success(Request $request)
{
$orderId = $request->orderId;
$orderAmount = $request->orderAmount;
$referenceId = $request->referenceId;
$txStatus = $request->txStatus;
$paymentMode = $request->paymentMode;
$txMsg = $request->txMsg;
$txTime = $request->txTime;
$signature = $request->signature;
if ($txStatus == 'SUCCESS') {
return redirect('credits/add')->with('successMessage', $txMsg);
} else {
return redirect('credits/add')->with('errorMessage', $txMsg);
}
}
}
OK I figured out the problem for myself.
The new versions of the browsers might be logging you out because of the new cookie policy.
References https://developers.google.com/search/blog/2020/01/get-ready-for-new-samesitenone-secure
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite
Whenever the cookie is required to be sent to server, the browser sees the SameSite attribute to decide if the cookie to be sent to server or blocked. For user actions, it is sent to the server but for auto-redirects, it doesn't if SameSite is set to 'Strict' or 'Lax' (Lax is going to be the default value now).
Solution: The cookie attribute SameSite can be set to 'None' along with specifying the 'Secure' attribute to 'true'. Setting 'Secure' attribute to 'true' would require your site to run on https. Sites running with http:// protocol will not be able to set 'Secure' cookie. Please set the 'HttpOnly' attribute to 'true' for making it accessible for http requests to the server only.
You can consider the following configuration for cookie:
SESSION_SECURE_COOKIE=true
SAME_SITE=none
You can also refer below tutorial that explains the cashfree integration in laravel:
https://www.w3techpoint.com/laravel/laravel-9-cashfree-payment-gateway-integration
The goal is to register an idle user on my website and redirect it to a payment platform by sending the user data entered in the form via the POST method.
I have a form in POST that I use to create an inactive user if this form is valid. I would then like to redirect my user to an external URL while sending the data from this form in POST to this URL. This URL accepts only specific variable names (these variables are in the associative array of my RedirectResponse) and only in POST.
The user will make his payment on the external link and if the payment is successful I will activate the user later. I identify with the payment platform by sending her 'ID' and she has authorized my domain name.
I tried to use RedirectResponse with status 307 but I think it is not possible to send it POST data.
* #Route("/{id<\d+>?1}/{slug}", methods={"GET", "POST"}, name="show")
* #Security("is_granted('IS_AUTHENTICATED_ANONYMOUSLY')")
*/
public function show(Offre $offre, $slug, Request $request): Response
{
if ($offre->getSlug() !== $slug) {
return $this->redirectToRoute('site_devenir_vip_show', [
'id' => $offre->getId(),
'slug' => $offre->getSlug(),
], Response::HTTP_MOVED_PERMANENTLY);
}
$utilisateur = new User();
$form = $this->createForm(UserType::class, $utilisateur);
$form->handleRequest($request);
if ($form->isSubmitted() === true) {
if ($form->isValid() === true) {
// TODO: create the inactive User here
// TODO: redirect the user on the payment platform
return new RedirectResponse('https://mywebsite.com', 307, [
'NOM' => $utilisateur->getNom(),
'PRENOM' => $utilisateur->getPrenom(),
'TEL' => $utilisateur->getTel(),
'EMAIL' => $utilisateur->getEmail(),
'PAYS' => $utilisateur->getPays(),
'ID' => 'XXXX',
'ABONNEMENT' => 'XXXX',
]);
}
$this->addFlash('error', 'Le formulaire comporte des erreurs.');
}
return $this->render('site/pages/devenir_vip/show.html.twig', [
'offre' => $offre,
'form' => $form->createView(),
]);
}
I am currently redirected to the external link that is in the RedirectResponse but it does not get the parameters. Do you have an idea ?
POST is a request method, not a response "method". Requests have methods (GET, POST, PUT, PATCH, HEAD, etc.) and responses have status codes (200, 404, 500, etc.).
You probably need to create the payment by sending the data to gate using an HTTP client from php and then redirecting the user, if the payment was created. Payment gates often respond with the url you should redirect your user to. Refer to the API documentation for your gate.
Symfony does not include an HTTP client by default (not a proper one anyways). I recommend Guzzle.
Mock code:
if ($form->isSubmitted() === true) {
if ($form->isValid() === true) {
$httpClient = new Client();
$response = $httpClient->post('https://paymentgate.com', [
'key' => 'value',
]);
// Validate response somehow
if ($response->statusCode() !== 200) {
$this->addFlash('error', 'Payment gate failed to respond');
} else {
// Let's assume that the gate returns a json with key 'redirect' containing the url
$json = json_decode($response->getContent());
return new RedirectResponse($json->redirect);
}
}
$this->addFlash('error', 'Le formulaire comporte des erreurs.');
}
I am trying to find the logged in user in my application using Auth but i get trying to get property of non-object which i understand clearly that it is returning null.
In my code below, an event triggers my webhook and post is sent to the address below. The function orderCreateWebhook triggers but that is where the error comes from..
The line $get_template = Order::where('id', Auth::user()->id);. Why is Auth returning null please? I am logged as well because i use auth in this same controller for another function which works fine.
Is it because it a webhook ?
Controller
public function registerOrderCreateWebhook(Request $request)
{
$shop = "feas.myshopify.com";
$token = "8f43d89a64e922d7d343c1173f6d";
$shopify = Shopify::setShopUrl($shop)->setAccessToken($token);
Shopify::setShopUrl($shop)->setAccessToken($token)->post("admin/webhooks.json", ['webhook' =>
['topic' => 'orders/create',
'address' => 'https://larashop.domain.com/order-create-webhook',
'format' => 'json'
]
]);
}
public function orderCreateWebhook(Request $request)
{
$get_template = Order::where('id', Auth::user()->id);
$baseurl = "https://apps.domain.net/smsapi";
$query = "?key=7e3e4d4a6cfebc08eadc&to=number&msg=message&sender_id=Shopify";
$final_uri = $baseurl.$query;
$response = file_get_contents($final_uri);
header ("Content-Type:text/xml");
}
In your function registerOrderCreateWebhook you appear to be making a request to shopify api and providing your webhook as the address which shopify will redirect the user to upon success. If this is correct, that request does not know about the user who generated the original request that made the api request since the request is coming from a completely different origin.
You would need to pass some key along with the url and then obtain the user within orderCreateWebhook. Something like:
Shopify::setShopUrl($shop)->setAccessToken($token)->post("admin/webhooks.json",
['webhook' =>
['topic' => 'orders/create',
'address' => 'https://larashop.domain.com/order-create-webhook/some-unique-key',
'format' => 'json'
]
]);
My suggestion would be to have a unique hash stored somewhere that relates back to the user in your system, perhaps a column in your users table. I wouldn't use the user_id for security reasons. So you would end up with something like:
//route
Route::get('/order-create-webhook/{uniqueKey}', 'YourController#orderCreateWebhook');
//or
Route::post('/order-create-webhook/{uniqueKey}', 'YourController#orderCreateWebhook');
// depending on the request type used by api which calls this endpoint
// controller function
public function orderCreateWebhook($uniqueKey, Request $request)
{
$user = User::where('unique_key', $uniqueKey)->first();
$get_template = Order::where('id', Auth::user()->id);
$baseurl = "https://apps.domain.net/smsapi";
$query = "?key=7e3e4d4a6cfebc08eadc&to=number&msg=message&sender_id=Shopify";
$final_uri = $baseurl.$query;
$response = file_get_contents($final_uri);
header ("Content-Type:text/xml");
}
Is it because it a webhook ?
Yes, you can't use sessions in a webhook. It's the shopify server which is making the call. You should read the doc, it may exist a way to give an unique identifier in your call to shopify api and get it back in the webhook to find your user associated.
just use this to get authenticated user
use the facade in your class/Controller
use Illuminate\Support\Facades\Auth
public function getAuthUser(){
$user = Auth::user()
if(!is_null($user)
{
//user is authenticated
}
else
{
// no user
}
}
I am trying to record the inbound call but so far I am only getting the 404 call not found error when record is activated.
This is my code so far (I am using Laravel and latest Plivo SDK):
public function __construct(Request $request)
{
$this->authId = config('AUTH_ID');
$this->authToken = config('AUTH_TOKEN');
$this->sourceNumber = config('sms.SMS_SOURCE_NUMBER');
$this->_answerURL = config('voiceCall.CALL_ANSWER_URL');
$this->_recordURL = config('voiceCall.INBOUND_RECORD_URL');
$this->_hangupURL = config('voiceCall.HANGUP_URL');
$this->_plivo = new RestClient($this->authId, $this->authToken);
$this->_response = new Response();
$this->_mp3Url = 'https://s3.amazonaws.com/plivocloud/Trumpet.mp3';
$this->_request = $request;
}
The answer method:
public function answer()
{
$response = $this->_response;
$response->addPlay($this->_mp3Url);
$response->addRecord([
'action' => $this->_recordURL,
'startOnDialAnswer' => "true",
'redirect' => "false",
'maxLength' => 600
]);
Log::useDailyFiles(storage_path().'/logs/debug.log');
Log::info([
'Record' => 'This is from inbound answer',
'Response' => $response
]);
return response($response->toXML(), 200)
->header('Content-Type', 'text/xml');
}
The record method:
public function record()
{
Log::useDailyFiles(storage_path().'/logs/debug.log');
$uuid = $this->_request->input('CallUUID');
Log::info(['This is Call UUID' => $uuid]);
$response = $this->_plivo->calls->startRecording($uuid);
Log::info([
'Record' => 'This is from record inbound record',
'Response' => $response,
'CallUUID' => $this->_request->input('CallUUID'),
'Request' => $this->_request->all(),
]);
}
The request is giving back the proper call uuid, and
$response = $this->_plivo->calls->startRecording($uuid);
is the code which is used in the docs. Does anyone have an idea what am I doing wrong here?
Plivo Sales Engineer here.
Is this an incoming call to your Plivo number? I see that you're returning an XML that contains a Play and Record element. This Record XML will take care of recording the call after the Play ends.
Are you making a Record API request to record this again? Which Call UUID are you passing to this API request?
For an inbound call, the Call UUID is sent to the answer URL. Are you using this Call UUID?