woocommerce store api + reactjs - add to cart not working - javascript

I have a react app Im working on to create a new frontend for an already live woocommerce site. I'm using this endpoint /wp-json/wc/store/v1/cart/add-item like so -
let config = {
method: "post",
url: "http://localhost:8010/proxy/wp-json/wc/store/v1/cart/add-item",
data: {
id : id,
quantity: 1,
variation: [
{
attribute: "Color",
value: color,
},
{
attribute: "Size",
value: size,
}
]
}
}
console.log(config)
const resp = await axios(config).then((response) => {
console.log(response.data)
})
.catch((error) => {
console.log(error.response.data);
});
Which is giving me a successful json response showing I have the item added -
items_count: 1
Then I have a cart component to api call and render -
useEffect(() => {
getCart();
}, []);
const getCart = async () => {
let config = {
method: "get",
url: "http://localhost:8010/proxy/wp-json/wc/store/v1/cart"
}
await axios(config).then((response) => {
console.log(response.data)
})
.catch((error) => {
console.log(error.response.data);
});
}
However when navigating to this page/component or any other, the api call is returning an empty cart - items_count: 0
On the checkout page I tried using a different endpoint wp-json/wc/store/v1/checkout but this is giving me an error -
code: "woocommerce_rest_cart_empty" data: {status: 400} message: "Cannot create order from empty cart."
Any ideas why this is happening?

It's possible that the request isn't setting a cookie which will prevent the cart from working as expected. In my experience, I can make a build of my React app and activate it as a WordPress theme. Then the add-to-cart works as expected. But if I'm using the live preview of the app instead, the add-to-cart will not work because the cookie is missing. Here's a GitHub issue about it.
https://github.com/woocommerce/woocommerce-blocks/issues/5683

Related

Apollo Client is not refreshing data after mutation in NextJS?

Here is the page to create a User
const [createType, { loading, data }] = useMutation(CREATE_USER_CLASS) //mutation query
const createUserClass = async (event) => {
event.preventDefault();
try {
const { data } = await createType({
variables: {
userClassName,
},
refetchQueries: [{ query: STACKINFO }],
options: {
awaitRefetchQueries: true,
},
});
setNotification({
message: 'User class created successfully',
code: 200,
});
handleClose();
} catch (e) {
setNotification({ message: e.message, code: 400 });
handleClose();
}
};
The thing is I can see inside the network tab the API is calling twice, which is not a good way, but I can see the newly added data , but the page is not refreshing. Kindly help me
I was also struggling with a similar problem and I stepped into your question. I don't know which version of Apollo Client you are using, but I think that instead of using refetchQueries() method, you can try to use update() to clear the cache. This way you will notify UI of the change. Something like this:
createType({
variables: {
userClassName,
},
update(cache) {
cache.modify({
fields: {
// Field you want to udpate
},
});
},
})
This is a link for reference from official documentation's page:
https://www.apollographql.com/docs/react/data/mutations/#:~:text=12-,update
I hope it helps!

Stripe php integration Error: ReferenceError: sessionId is not defined

I'm stuck at integrating stripe's prebuild payment gateway to my project.
I'm coding very simple Eshop (without login/registration and shopping cart) just a simple project with a form and stripe checkout as a way to pay...
I was following official stripe documentation but I struggle to find an answer how to implement their "simple prebuilt checkout page" to procedural PHP.
Currently I'm stuck on getting this error...the provided code is what I have used from their official documentation "still getting error ReferenceError: sessionId is not defined in the console in devtools ://
Also IDK how to configure endpoint on my server when coding it all without PHP framework such as Slim/Laravel...al examples provided by stripe use Slim framework when configuring endpoints....any ideas?
<?php
//config PHP
require_once("vendor/autoload.php");
// === SET UP STRIPE PAYMENT GATEWAY ===
$stripe = [
"secret_key" => "sk_test_4eC39HqLyjWDarjtT1zdp7dc",
"publishable_key" => "pk_test_TYooMQauvdEDq54NiTphI7jx",
];
\Stripe\Stripe::setApiKey($stripe['secret_key']);
?>
<?php
//create-checkout-session.php
require_once '_includes/config.php';
// ?session_id={CHECKOUT_SESSION_ID} means the redirect will have the session ID set as a query param
$checkout_session = \Stripe\Checkout\Session::create([
'success_url' => 'http://localhost:8888/Avanza---Eshop/success.php?session_id={CHECKOUT_SESSION_ID}',
'cancel_url' => 'http://localhost:8888/Avanza---Eshop/canceled.php',
'payment_method_types' => ['card'], //, 'alipay'
'mode' => 'payment',
'line_items' => [[
'amount' => 2000,
'currency' => 'usd',
'name' => 'mikina',
'quantity' => 1,
]]
]);
header('Content-type: application/json');
echo json_encode(['sessionId' => $checkout_session['id']]);
<!--order.php actual page that will be displayed to users-->
<button style="width: 100px; height: 100px" id="checkout-button"></button>
<script type="text/javascript">
// Create an instance of the Stripe object with your publishable API key
var stripe = Stripe('pk_test_51HjoRfIaBaXJG6udQspXdLRNwMesCriMwZoR7nGCF0hZtu2Zp9FUxCFWwVpwwU4BZs7fTxJtYorVTuoK1vqXp2Uw002r6qvmO7'); // removed for Stackoverflow post
var checkoutButton = document.getElementById('checkout-button');
checkoutButton.addEventListener('click', function() {
// Create a new Checkout Session using the server-side endpoint you
// created in step 3.
fetch('create-checkout-session.php', {
method: 'POST',
})
.then(function(response) {
return response.json();
})
.then(function(session) {
return stripe.redirectToCheckout({ sessionId: sessionId});
})
.then(function(result) {
// If `redirectToCheckout` fails due to a browser or network
// error, you should display the localized error message to your
// customer using `error.message`.
if (result.error) {
alert(result.error.message);
}
})
.catch(function(error) {
console.error('Error:', error);
});
});
</script>
I think you need to replace return stripe.redirectToCheckout({ sessionId: sessionId}); with return stripe.redirectToCheckout({ sessionId: session.sessionId});
It's worked for me. If you see more errors or face any problems, loot at the browser console Network tab.
$(function() {
var stripe = Stripe('<?= Config::STRIPE_PUB_KEY ?>'); // here write: pk_test_5...
$(document).on('click', '.buy_now_btn', function(e) {
let id = $(this).attr('id');
$(this).text('Please wait...');
$.ajax({
url: 'action.php',
method: 'post',
data: {
id: id,
stripe_payment_process: 1
},
dataType: 'json',
success: function(response) {
console.log(response);
return stripe.redirectToCheckout({
sessionId: response.id
});
},
})
})
});

(Nuxt) Page not re-rendering data on reload

I am trying create a to fetch data from the server and show them to the user. But the issue is that nothing apart from the dummy information is displayed.
Basically there are two scenarios:
1. Navigating to the page from some other link (This works as expected)
Explanation: Such as going from http://localhost:3000/ to http://localhost:3000/assignments/explore and it renders all the fetched contents as expected.
Vue plugin ss
2. Entering the page directly through the url or press refresh
Explanation: By directly typing http://localhost:3000/assignments/explore in the url nothing is displayed apart from the dummy card
Vue plugin ss
As you can see the length of the assignment state is 1 instead of 3 and the vuex action saveAssignments is also missing in this case
Template tag in explore.vue
...
<div v-for="assignment in assignments" :key="assignment._id">
<Card :assignment="assignment"></Card>
</div>
...
Script Tag in explore.vue
fetch() {
this.$store.dispatch('assignment/fetchAssignment')
},
computed: {
assignments() {
return this.$store.state.assignment.assignments
},
},
assignment.js //Vuex Store
export const state = () => ({
assignments: [ //dummy data
{
_id: '5f1295181ebf00dd0070de1',
title: 'dummy',
Description: 'asfd',
Price: 50,
createdAt: '2020-07-18T06:22:09.037Z',
updatedAt: '2020-07-18T06:22:09.037Z',
__v: 0,
id: '5f12951081ebf00dd0070de1',
},
],
})
export const mutations = {
saveAssignments(state, newAssignments) {
state.assignments = state.assignments.concat(newAssignments)
},
}
export const actions = {
async fetchAssignment({ commit }) {
const data = await this.$axios.$get('assignments')
commit('saveAssignments', data)
},
}
Any help will be appreciated
Found the solution
I just had to add the return statement before the dispatch function in fetch()
fetch(){
return this.$store.dispatch('assignment/fetchAssignment')
}
Found my answer here
Nuxtjs async await in a page doesnt work on page refresh

Next Js Custom Routes and SSR

I am using apollo with next and recently I noticed that custom routes breaks SSR. Usually if you navigate through pages apollo caches the query and when you are on the page the next time, it serves everything from cache. However with custom routes, the cache is never used.
I also noticed that when I click on these pages, an error flashes in the console. But it goes away very fast and I wasn't able to copy it here.
Server.js
//
server.get('/about-us', (req, res) => app.render(req, res, '/about'));
server.get('/about', (req, res) => res.redirect(301, '/about-us'));
Menu Click Handler
const navigate = link => () => {
Router.push(link);
};
Menu Items
export const menu = [
{
name: 'Home',
url: '/',
},
{
name: 'Catalogs',
url: '/catalogs',
},
{
name: 'Shop',
url: '/shop',
},
{
name: 'Wholesale',
url: '/wholesale',
},
{
name: 'About Us',
url: '/about-us',
prefetch: true,
},
{
name: 'Contact Us',
url: '/contact-us',
prefetch: true,
},
];
Based on a suggestion from nextjs spectrum I tried prefetching custom pages in the TopNav Component but it didn't work.
const prefetch = url => {
if (process.browser) {
console.log('prefetching these urls', url);
Router.prefetch(url);
}
};
useEffect(() => {
menu.forEach(menuItem => {
if (menuItem.prefetch) {
prefetch(menuItem.url);
}
});
}, []);
I was able to figure out the problem. This is not really well documented but you need to prefetch the component. So for my case instead of prefetching /about-us I should have prefetched /about.
That's why there is as prop in the link component. Nextjs 9 just got released which fixes this issue.
https://nextjs.org/blog/next-9#dynamic-route-segments
For nextjs 9 you can save your file as [pid].js and it will catch all paths in a specific route. i.e for /products/test-product you have to create folder products and inside that add [pid].js.
I needed to query for product based on slug so I added this and voila, I have access to the slug inside my component.
Product.getInitialProps = async ({ query }) => {
return { slug: query.pid };
};
These issues were pretty frustrating before next 9 but it's heavily simplified and it helped me fully remove server.js.

React | Facebook JS API : Error code 100 when trying to upload multiple images to my page feed

In a first function, I upload multiple images to page-id/photos and receive a positive response with all the ids of these images.
The next part however is where I'm stuck; I am now trying to create a post with multiple images to my Facebook page timeline. However, I'm getting a weird error response claiming that I already have uploaded my images.
I've even followed Facebook's own example from their documentation using Open Graph Explorer, but that just returns another error
Function to send image:
(works without a problem)
sendFacebookImagePost(page) {
const attached_media = []
for(let i = 0; i < this.state.upload_imgsrc.length; i++) {
let reader = new FileReader();
reader.onload = (e) => {
let arrayBuffer = e.target.result;
let blob = new Blob([arrayBuffer], { type: this.state.upload_imgsrc[i].type });
let data = new FormData()
data.append("source", blob)
data.append("message", this.state.fb_message)
data.append("no_story", true)
data.append("published", true)
axios({
method: "post",
url: "https://graph.facebook.com/" + page.id + "/photos?access_token=" + page.accessToken,
data: data
})
.then(response => {
attached_media.push({media_fbid: response.data.id})
if (attached_media.length === this.state.upload_imgsrc.length) {
this.sendFacebookPost(page, attached_media)
}
})
.catch(error => {
console.log(error);
})
}
reader.readAsArrayBuffer(this.state.upload_imgsrc[i]);
}
}
Function to send post:
(Here is where the error happens)
sendFacebookPost(page, attached_media) {
let data = {
message: this.state.fb_message,
link: this.state.fb_link,
attached_media: attached_media
// this is what attached_media returns:
// [
// {media_fbid: response.data.id},
// {media_fbid: response.data.id}
// ]
}
axios({
method: "post",
url: "https://graph.facebook.com/" + page.id + "/feed?access_token=" + page.accessToken,
data: data
})
.then( () => this.setState({fb_successMessage: "Post successful!", fb_errorMessage: ""}) )
.catch(error => {
console.log(error);
})
}
Error code
error: {
code: 100
error_subcode: 1366051
error_user_msg: "These photos were already posted."
error_user_title: "Already Posted"
fbtrace_id: "Cl9TUTntOZK"
is_transient: false
message: "Invalid parameter"
type: "OAuthException"
}
My try on Open Graph Explorer
Problem solved.
The part that went wrong is where I add the following to my image post:
data.append("published", true). Apparently, images you want to use in a multi photo post have to be set to published: false before they can be used in a post. Otherwise, Facebook sees this as already uploaded.

Categories

Resources