Saleor Integration with Stripe Webhooks - react-native

I've been combing through the Saleor docs (following these: https://docs.saleor.io/docs/3.x/developer/available-plugins/stripe and https://docs.saleor.io/docs/3.x/developer/checkout). However, I have found what seems to be an issue (maybe just my ignorance).
This is my rough frontend code, I'll offer a short walkthrough
const onCompletePurchase = async () => {
createPaymentIntentMutation.mutate(undefined, {
onSuccess: () => {
completePaymentMutation.mutate(undefined, {
onSuccess: async ({ data }) => {
console.log(data);
const clientSecret = JSON.parse(data.confirmationData as string).client_secret;
confirmPayment(clientSecret, {
paymentMethodType: "Card",
}).then((result) => {
const { error, paymentIntent } = result;
if (error) {
console.log(error);
} else if (paymentIntent) {
console.log(JSON.stringify(paymentIntent, null, 2));
completePaymentMutation.mutate(undefined, {
onSuccess: () => {
navigation.navigate("CartLanding");
setCheckout({} as Checkout);
},
onError: (error) => {
console.log(error);
},
});
} else {
console.log("Something went wrong");
}
});
},
onError: (error) => {
console.log(error);
},
});
},
onError: (error) => {
console.log(error);
},
});
};
Walkthrough - (Follows these steps https://docs.saleor.io/docs/3.x/developer/available-plugins/stripe)
Creates the payment intent (through saleor)
Completes the payment to get the confirmation information IE: Client Secret (through saleor)
Once gets Client Secret, confirms the payment through stripe
Where issue occurs - Tries to get the order from completing the payment again as detailed in the docs as below
Finalizing a payment
When the customer finalizes a payment, Stripe sends a webhook notification with all details related to this payment. Saleor asynchronously receives the notification and completes checkout process.
On client-side, when stripe.confirmCardPayment doesn't return an error as [described here](https://stripe.com/docs/payments/accept-a-payment?platform=web&ui=elements#web-submit-payment),
client-side can call checkoutComplete one more time. Saleor confirms that the payment has success status and returns an order object.
However, I believe the issue is this. I call "checkoutComplete" at the same time that saleor receives the webhook notification, resulting in an error with the clients request. If I do for example, setTimeout for 2 seconds, and THEN call checkoutComplete, it works fine, but I believe there is an issue with both of these being called. Am I missing something? or is there a better way to do this WITHOUT using a setTimeout?
Thanks and feel free to ask some questions to figure out the specifics.

Related

The OAuth response flow failed

I'm using aws amplify along with react-native-inappbrowser. I enabled Google SSO authentication and it is working fine, but when I added GitHub auth it doesn't work as expected.
I added a listener using Hub.listen('auth', async (data) => {...} and the urlOpener in my awsConfig looks like this:
onst urlOpener = async (url, redirectUrl, settings) => {
try {
if (await InAppBrowser.isAvailable()) {
const { type, url: newUrl } = await InAppBrowser.openAuth(
url,
redirectUrl,
{ ...inAppBrowserSettings, ...settings },
);
if (type === 'success') {
Linking.openURL(newUrl);
}
} else {
Linking.openURL(url);
}
} catch (error) {
Alert.alert(error.message);
}
};
The Hub.listener looks like this:
useEffect(() => {
const unsubscribe = Hub.listen('auth', async (data) => {
const { payload } = data;
const user = payload.data;
switch (payload.event) {
case AuthEnum.SIGN_IN:
handleSignIn(user);
break;
case AuthEnum.SIGN_OUT:
handleSignOut();
break;
case AuthEnum.SIGN_IN_FAILURE:
handleSignInFailure();
break;
}
});
return () => unsubscribe();
}, []);
When I try to authenticate using GitHub, the GitHub API returns the correct token but the aws Hub catches a SIGN_IN_FAILURE and the data looks like this:
{
"channel": "auth",
"payload": {
"event": "signIn_failure",
"data": {},
"message": "The OAuth response flow failed"
},
"source": "Auth",
"patternInfo": []
}
I'm not sure why this is happening. A solution could be to remove the listener in case of GitHub auth, but I'm not sure how to do that since the InAppBrowser.openAuth() is used for both the Google SSO and GitHub auth.
Make sure to let me know if the info I provided isn't enough. Any suggestions/help would be great!
I don't think AWS Amplify support github oauth. I believe the supported ones are: Google, Apple, Facebook & Amazon
Supported social logins

Call Nextjs API from within Netlify function

I got a serverless Netlify function like this:
exports.handler = async function(event, context) {
return {
statusCode: 200,
body: JSON.stringify({message: "Hello World"})
};
}
When called by this url <site-name>/.netlify/functions/helloworld
I do get the message {"message":"Hello World"}
I also got a pages/api/mailingList.js Nextjs API endpoint:
const axios = require('axios');
export default async function handler(req, res) {
//console.log(req.query.mail);
if (req.method === "PUT") {
axios
.put(
"https://api.sendgrid.com/v3/marketing/contacts",
{
contacts: [{ email: `${req.query.mail}` }],
list_ids: [process.env.SENDGRID_MAILING_LIST_ID],
},
{
headers: {
"content-type": "application/json",
Authorization: `Bearer ${process.env.SENDGRID_API_KEY}`,
},
}
)
.then((result) => {
res.status(200).send({
message:
"Your email has been successfully added to the mailing list. Welcome 👋",
});
})
.catch((err) => {
res.status(500).send({
message:
"Oups, there was a problem with your subscription, please try again or contact us",
});
console.error(err);
});
}
}
This mailing list API endpoint, do work when using curl from the terminal with PUT as the method:
curl -X PUT -d mail=helloworld#gmail.com https://netlify.app/api/mailingList
The API endpoint also work from the URL (/api/mailingList?mail=helloworld#gmail.com) when removing the if (req.method === "PUT") { part from the mailingList.js
However, I am NOT able to get the API endpoint to be called from within the Netlify function.
(Preferably the mailingList API should be possible to call multiple times with different mailing list IDs from the Netlify function helloworld.js based on different logic /api/mailingList?mail=helloworld#gmail.com&listid=xxx)
To get the API endpoint to be called at all, from the function, I have tried adding a axios call from the helloworld.js to mailingList.js like this
const axios = require('axios');
exports.handler = async function(event, context) {
const mail = "helloworld#gmail.com";
// add to mailinglist
axios
.put("/api/mailingList?mail="+mail)
.then((result) => {
if (result.status === 200) {
toast.success(result.data.message);
}
})
.catch((err) => {
console.log(err);
});
}
This result in the following error from the browser: error decoding lambda response: invalid status code returned from lambda: 0
(I do not get any error msg from the Netlify log, either helloworld.js or mailingList.js)
Clearly, there is something wrong with how I call the mailigList.js from helloworld.js. Would greatly appreciate if some one could give me some advice and show me what I am doing wrong.
How can I call the API endpoint (mailigList.js) from within the Netlify function helloworld.js? (Preferably multiple times with different mailing list IDs: /api/mailingList?mail=helloworld#gmail.com&listid=xxx)
Found the solution in this article: https://travishorn.com/netlify-lambda-functions-from-scratch-1186f61c659e
const axios = require('axios');
const mail = "helloworld#gmail.com";
exports.handler = (event, context, callback) => {
axios.put("https://<domain>.netlify.app/api/mailingList?mail="+mail)
.then((res) => {
callback(null, {
statusCode: 200,
body: res.data.title,
});
})
.catch((err) => {
callback(err);
});
};

sending back api data to vue in express returns empty object

I'm trying to send some data back from my express app using the following in my app.js this data comes from a 3rd party api and I want to send it back to my front end application. I am able to see the content in my express api but it doesn't seem to deliver a result to my front end?? anyone have any ideas as to why I'm getting log below in the console.
I suspect it has to do with some async or timeout issue with the express app but I haven't been able to fix the issue myself.
function getFish(){
axios.get('https://www.fishwatch.gov/api/species')
.then(function (response) {
console.log(response)
return response
})
.catch(function (error) {
console.log(error);
})
}
app.get('/getFish', async(req,res) =>{
let fish = await getFish()
res.json({fishes: fish})
})
when I try to log the data in my app, I only get an empty object
{}
here is my vue code to log the value's returned by my express api.
created:function(){
this.fetchFish()
},
methods: {
fetchFish(){
fetch('http://localhost:3000/getFish')
.then((response) => {
return response.json();
})
.then((data) => {
console.log(data);
});
}
}
You need to return the axios promise in your server's getFish function or the /getFish route won't be awaiting anything:
function getFish(){
// New `return` statement
return axios.get('https://www.fishwatch.gov/api/species')
.then(function (response) {
console.log(response)
return response
})
.catch(function (error) {
console.log(error);
})
}

handle network request failed in react native

I'm facing an issue while using react native fetch api. many times request got failure . I have a high speed connection. but many times it got failed.
that issue is happening In android,ios both.
const shoppingApi = 'myserverlink';
async function Sendshoppinapi(data) {
try {
let response = await fetch(shoppingApi, {
method: 'POST',
headers: {
'Accept': 'application/json',
'content-type':'multipart/form-data'
},
body: data
});
let responseJson = await response.json();
return responseJson;
}
catch (error) {
Alert.alert(error.toString())
}
}
export {Sendshoppinapi};
data that I sending server as post request
add_to_wishlist = (item,index) => {
{
let data = new FormData();
data.append('methodName', 'add_to_wishlist');
data.append('user_id', global.userid)
data.append('item_id', this.props.navigation.state.params.itemid.toString())
Sendshoppinapi(data).then((responseJson)=>{
console.warn(responseJson);
if(responseJson.responseCode == '200'){
this.setState({fav:false})
Alert.alert('SHOPPING','Item added to wishlist successfully.',[{text: 'OK',},],{ cancelable: false })
}
else{
this.setState({fav:false})
Alert.alert('SHOPPING','Item already .',[{text: 'OK',},],{ cancelable: false })
}
})}
}
Error that when request got failed
I've quoted an answer I used for another post - however I have added await.
You can check the status of the call, to determine perhaps why the network call failed. Try using fetch's ok to check whether the response was valid, for example:
.then(function(response) {
if (!response.ok) {
//throw error
} else {
//valid response
}
})
Using await:
let response = await fetch(url)
if (response.ok) return await response.json()
You can also access the response's status like:
response.status;
or also, statusText such as:
response.statusText;
checkout the below:
https://developer.mozilla.org/en-US/docs/Web/API/Response/statusText
https://developer.mozilla.org/en-US/docs/Web/API/Response/status
https://www.tjvantoll.com/2015/09/13/fetch-and-errors/
Use then() function with promises. (Requested code snippet)
fetch(shoppingApi, {
method: 'POST',
headers: {
'Accept': 'application/json',
'content-type':'multipart/form-data'
},
body: data
})
.then((resp) => {
return resp.json()
})
.then((resp) => {
//resp contains your json data
});
You also can make your function returns a Promise, and use it with then():
function sendShoppingApi(data) {
return new Promise((resolve, reject) => {
fetch(shoppingApi, {
method: 'POST',
headers: {
'Accept': 'application/json',
'content-type':'multipart/form-data'
},
body: data
})
.then((resp) => {
return resp.json();
})
.then((resp) => {
resolve(resp);
/*
you should also check if data is valid, if something went wrong
you can reject the promise:
if(!dataOK)
reject("error message");
*/
});
});
}
So now you can do something like this:
sendShoppingApi(data)
.then((resp) => {
//do stuff with your data
})
.catch((err) => {
//handle error
});
UPDATE
could be a duplicate of this: React Native fetch() Network Request Failed
For the case when you are running the app on the android device, the API is on a computer and both of them are on the same network I have added some possible things to check. I haven't detailed specific solutions since there are many answers on each topic.
Do a quick check with ngrok https://ngrok.com/ on the free plan to see if that works. If yes:
Make sure the API is accessible by trying to access it on the device browser (most important is to check if you allow the port at inbound rules, firewall).
If you are using HTTPS, you might get an error if your react native env is not properly configured to accept not trusted certificates, assuming you are using a non trusted one. Do a check without HTTPS, only with HTTP, to see if it's the case. https://github.com/facebook/react-native/issues/20488

Is there any callback for on leave, on join , on typing in vue.js?

About
I am learning Vue.js with Laravel. Presently, practicing on sending real time text messages between 2 users.
Below code sends message to another user
var url = "http://localhost:6001/apps/My_appId/events?auth_key=My_Key";
var socketId = Echo.socketId();
var request = {
"channel": "private-Send-Message-Channel.2",
"name": "MessengerEvent",
"data": {
"msg": message
},
"socket_id": socketId
};
axios.post(url,
JSON.stringify(request))
.then((response) => {
//Success callback
}
);
Receive the message
window.Echo.private('Send-Message-Channel.2')
.on('MessengerEvent', (e) => {
//Receive the message
}
);
Question: Is there any callback for on leave, on join , on typing, total users?
You need to user a presence channel. As described these channels are also private:
All presence channels are also private channels
You can set up a presence channel by using .join.
Echo.join(`chat.${roomId}`)
.here((users) => {
//
})
.joining((user) => {
console.log(user.name);
})
.leaving((user) => {
console.log(user.name);
});
There you have access to the callback that you are looking for.