Shopify API returns empty cart - ajax

Using this API: https://help.shopify.com/en/themes/development/getting-started/using-ajax-api#add-to-cart
From my messenger bot I call cart/add.js multiple times with the variant id and quantity and it returns a success message, but I call cart.js to retrieve the items, the cart is always empty.
I'm adding items to the cart like this:
$cartAPI = 'https://'.$shopKey.':'.$shopSecret.'#'.$shopUrl.'/cart/add.js';
$request = $client->request('POST', $cartAPI, [
'form_params' => [
'id' => (int) $productID,
'quantity' => 1
]
]);
And retrieving cart like this:
$cartAPI = 'https://'.$shopKey.':'.$shopSecret.'#'.$shopUrl.'/cart.js';
$request = $client->get($cartAPI);
I tried to include cookies in the Guzzle call like so
$this->client = new Client(['cookies' => true]); and both calls use the same client instance, but it still returns an empty cart.
I don't use CloudFlare or any Caching mechanism for this.
What am I doing wrong?

You are doing something wrong. Why would you make a call to Shopify with a key and a secret? Are you not selling yourself a little short here? I mean if I examined your source code, and saw a key and secret, I would be able to use that to do anything I want. Is that the goal here? Allowing anyone on the Internet to make you look silly? Shopify has a button you can place anywhere to add products to a cart. You can use that. It is secure.

Solution i figured out here for anyone having the same issue. I needed to use the cart cookie. Ended up doing something like:
$cartCookie = Cache::tags(['user:' .$userId, 'cookies'])->get('cart');
if (!$cartCookie) {
$client = new Client(['cookies' => true]);
} else {
$cookieJar = CookieJar::fromArray([
'cart' => $cartCookie,
], conf('shop.url'));
$client = new Client(['cookies' => $cookieJar]);
}
Cookie is stored in the cache the first time the user adds an item to the cart and used for recurrent adds. I had to put it in Cache since I'm building a chatbot but you can just use cookies from your browser.

Related

laravel: redirect to same controller with query parameters when cookie exists

First, here's a little background on what I'm trying to accomplish:
I'm building a SaaS app, and on the marketing site, the user can select a plan which will direct them to the registration page. I'm using a very similar flow to Mailchimp.
Once they register, they have to verify their email. Once they verify their email, they "complete" their account with information like address, city, etc.
Then, they're taken to the paywall.
My problem
I need a way of remembering which plan they wanted from the marketing site when they land on the paywall. To do this I was going to set a cookie.
If a cookie exists of a certain value, I want to redirect to that same route, but add a query parameter such as ?plan=free
Here is my controller function tied to the route route('paywall')
/**
* Returns all the data needed for the paywall
*/
public function paywall() {
if ($plan_intent = Cookie::get('plan-intent')) {
return redirect()->route('paywall', ['plan' => $plan_intent]);
}
$account = auth()->user()->accounts->first();
$billingAccount = $account->billingAccount;
$contactDetails = $account->contactDetails();
return view('account.paywall', [
'plans' => Plan::all(),
'intent' => $account->createSetupIntent(),
'currentPlan' => $account->plan,
'contactDetails' => $contactDetails,
'billingAccount' => $billingAccount,
'states' => State::all()
]);
}
The code above is causing a redirection loop: (site name) redirected you too many times.
How can I conditionally add query parameters to the same route and redirect to the same route?
I had to do a check to see if the param was there. That's why the redirect loop was happening:
if ($plan_intent = Cookie::get('plan-intent') && !request()->input('plan')) {
return redirect()->route('paywall', ['plan' => $plan_intent]);
}

Acessing auth user attribute

I am in the guzzle controller making a request to an external api.
I wanna use an id from the user who is logged in.
I have been doing the request with a static id, but now i want it dynamically.
I tried like this:
$science = Auth::user()->science_id;
$client = new Client(['headers' => ['Accept' => 'application/json']]);
$request = $client->get(
'https://url_to_the_api/'.$science.'/degree',
[
'auth' => ['client', 'secret'],
]
);
$data = $request->getBody()->getContents();
return $data;
And i have the error
500(internal server error)
and this message:
"Trying to get property 'science_id' of non-object"
What am i missing?
Thanks for your time
If you are using it in web app then make sure you first check if user is already authenticated by using auth middleware or manually by using Auth::check() function.
Or
If you are trying to hit this by api that will not work here because session will not be maintained in that case. That's why JWT tokens were introduced to maintain the state of an application.
I've solved it like this:
$science = auth('api')->user()->science_id;
Thanks for the help!

How to find referer of redirect to oauth client's callback

I am having trouble setting up a generic oauth client (and can't find good material on google).
I have this as my route to receive the callback from the oauth process:
Route::get('/oauth/callback', function (Request $request) {
$http = new GuzzleHttp\Client;
$response = $http->post('https://www.wunderlist.com/oauth/access_token', [
'client_id' => 'xxxxxxxxxxxxxxx',
'client_secret' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
'code' => $request->code
]);
});
but in order to make it generic, I must be able to identify where the redirect came from.
something in the lines of
$service = App\Service::where(<field>, $request-><information about the referer>);
does Request contain any kind of information that can help me identify the source of the redirect? I looked at the object with dd() and couldn't find anything
You should use request()->headers->get('referer') to check the referrer url.
I managed to work around the problem by defining the callback url so that it contains a query parameter identifying the service.
This means that I tell the service to callback to /oauth/callback?service=XXX
and I find it in my services table like this:
$service = Service::where('slug', Input::get('service'))->firstOrFail();

How to keep session data using Codeigniter and Tank Auth

I'm using Codeigniter and Tank Auth for a e-commerce website. I'm finding that if a customer puts items into the cart (using the Codeigniter built in cart class) and then registers on the site the session is lost along with their cart (I'm presuming it generates a new session for some reason instead of keeping the same session).
Has anyone come across this problem before? and is there a simply solution that I have overlooked.
Thanks
As far as the most recent code looks like, the only place the hole session is deleted is in the logout() function, Tank_auth.php Line 118:
https://github.com/ilkon/Tank-Auth/blob/master/application/libraries/Tank_auth.php#L118
The example usage of Tank Auth uses logout() in activate() and reset_email() - check your code for those methods. You could also change the Tank Auth logout function to something like this:
function logout($keep_session = false)
{
$this->delete_autologin();
// See http://codeigniter.com/forums/viewreply/662369/ as the reason for the next line
$this->ci->session->set_userdata(array('user_id' => '', 'username' => '', 'status' => ''));
if(!$keep_session)
$this->ci->session->sess_destroy();
}
... and the use it like this: $this->tankauth->logout(true);

Magento - Customer Not Logged in After Redirect From External Page

I'm having a lot of trouble getting a customer to stay logged in after I have created a new account. I'm creating them an account and adding products to a cart from an external site, and then sending them to Magento store. What I want to have happen is:
A customer goes to a signup page and enters relevant information.
They go to a new page where they can choose to add free samples to their cart.
After picking samples. their account is created and they are redirected to the Magento store with the samples in their cart.
The problem I'm having is between steps 2 and 3. I create an account using the Magento's SOAP API with the following:
$customerInfo = array('firstname' => $custFirstname, 'lastname' => $custLastname, 'email' => $email, 'password_hash' => md5( $new_password ), 'store_id' => 34, 'website_id' => 25,'group_id' => 9);
// Call API method customer.create
$newCustomerId = $client->call( $session, 'customer.create', array( $customerInfo ) );
I then return their customer ID, which I pass to another function which actually logs them in and adds products to their cart:
public static function _addSamplesToCart($customer_id, $sample_one, $sample_two, $sample_three){
Mage::getSingleton("core/session", array("name" => "frontend"));
$customerSession = Mage::getSingleton('customer/session', array("name" => "frontend"));
$customerSession->init("customer_bn_us");
$customerSession->loginById($customer_id);
$cart = Mage::getSingleton('checkout/cart');
$cart->addProductsByIds($idArray);
$cart->save();
$cart->getCheckoutSession()->setCartWasUpdated(true);
}
These functions are actually called from AJAX post requests, so when I get a successful return value from _addSamplesToCart, I do a simple javascript redirect (window.location ="http://www.myhostname.net/welcome") and it correctly takes me there, but I'm not logged in.
I've been looking around all afternoon and trying a few different things and nothing has worked. I've also tried doing a hidden form submit to /customer/account/loginPost and it still doesn't work. I have verified that it's correctly creating an account in Magento. My only hunch is that I'm doing this with a mix of AJAX and PHP so somehow the cookies or sessions are getting mixed up?
If you are trying to login from an hostname different from the one used by the Magento store, it cannot work. You can verify this by checking if a frontend cookie is created after the AJAX call.
I suggest you to create a new controller in Magento that receives the id of the customer just created and executes the code you wrote in your function:
www.myhostname.net/autologin/myaction/13 (where 13 is the id of the customer just created).
Obviously you should add something else to avoid security issues.

Resources