In-Context Checkout: No response handler found for post message response error - paypal-sandbox

I use Advanced In-Context Checkout integration.
I do AJAX and utilize these functions, just as their docs explain it:
paypal.checkout.setup()
paypal.checkout.initXO()
paypal.checkout.startFlow()
paypal.checkout.closeFlow()
And I constantly get this annoying error after Execute the payment step. They didn't bother to explain it anywhere is their API docs. It is just missing.
new Error("No response handler found for post message response "+t.name+" in "+window.location.href);
What does the error mean? What kind of response handler for post message response is expected? How to provide it?
My client side code is as simple as the following:
onCheckoutBtnClick(ev) {
paypal.checkout.initXO();
$.post('/checkout', {
user: JSON.stringify(this.props.user),
data: JSON.stringify(this.props.WCs),
})
.done(res => {
paypal.checkout.startFlow(res.approval_url);
})
.fail(err => {
paypal.checkout.closeFlow();
});
},
And server side is as follows:
router.post('/checkout', (req, res, next) => {
var payment_json = {
// huge config to create a payment
// the pivotal value is "return_url"
redirect_urls: {
"return_url": "http://example.com:3000/complete_payment",
"cancel_url": "http://example.com:3000/cancel_payment"
},
}
});
And return_url code
router.get('/complete_payment', (req, res, next) => {
paypal.payment.execute(req.query.paymentId, execute_payment_json, function (err, payment) {
// After this step the error in thrown on the client
res.redirect('http://example.com:3000/show_complete_page_to_buyer');
})
})

It seems like this is a Sandbox problem only. See this error all the time in Sandbox and newer seen it in production mode.
I have mailed the Paypal developer complaining on the many difference between sandbox and production.

The sandbox has issues for me also that often correct themselves on a refresh. Using the Chrome developers tools (Ctrl-Shift-I) and reviewing the console log I see this stack trace:
types.js:19 Uncaught Error: No handler found for post message ack for message: postrobot_method from http://localhost:50834 in https://www.sandbox.paypal.com/webapps/hermes/button
at Object._RECEIVE_MESSAGE_TYPE.(anonymous function) [as postrobot_message_ack] (https://www.paypalobjects.com/api/checkout.js:2514:33)
at receiveMessage (https://www.paypalobjects.com/api/checkout.js:2465:77)
at messageListener (https://www.paypalobjects.com/api/checkout.js:2486:13)
I've also observed the error can be triggered by unhandled javascript exceptions elsewhere in my code.

I solved wrapping the button init function in $(window).load()

Related

Accessing response error data in next.js using SWR

I have a form data which on submit I a sending to backend if there is an error I have process the error and show it on page. Request is getting posted fine but when getting a backend response I never go to catch error loop. Appreciate any help in resolving this.
Thanks
const [errorMessage, setErrorMessage] = useState('')
mutate(
`${api}`,
fetcher('POST', `${api`, body: JSON.stringify(data))
)
.then((data) => {
... do something
})
.catch((error) => {
setErrorMessage(data.error.message)
console.error(error)
})
}
backend response data :
{"trace_id":"abc","errors":[{"code":122,"message":" Error While
Submitting."}]}
The .catch clause will only fire if there is an error executing the network request. But in this case, it's working - it sends a request and gets a response. So only the then clause is fired. However, the response contains an error.
There are a few ways to make it so the error response gets 'caught' - either you configure your graphql library to look inside each response to check for 'errors' property to be non-empty and throw, or you can do that inside the then clause in your example.

How to access backend errors with Redux createAsyncThunk

I am not sure how I am supposed to get the errors that come from the backend when a POST request is sent to the backend. If I use plain axios calls, I can simply get the errors from the response object in the catch block with:
error.response.data.errors
But when using Redux and using createAsyncThunk method, on a 400 status code from the server, a rejected action is dispatched and the error object I get is a generic one like so:
{
message: "Request failed with status code 400"
name: "Error"
stack: "Error: Request failed with status code 400\n...."
}
How can I get the server errors, just like using axios?
You can make use of the rejectWithValue function from redux-toolkit to include the server error as the payload property of your rejected action.
It would be something like this (untested code because I’m on my phone)
const myAction = createAsyncThunk(
‘actionName’,
async ( arg, {rejectWithValue} ) => {
try {
const res = await axios.post(…);
return res.data;
} catch (error) {
return rejectWithValue( error.response.data.errors );
}
});
I think what you can do is add an additional check for the errors and also wrap the axios post request with a try catch block.
Note : In your case the request is failing so I guess there must be some error with the way you are making a request.

Meteor publication send custom sanitized error to client in publication

I am not sure if I am just doing something wrong or if this is actually not working. I want to display the original publication error on the client, in case I catched one:
Meteor.publish('somePub', function (args) {
const self = this
try {
// ... publication logic
catch (pubErr) {
self.error(pubErr)
}
})
On the client I am "catching" this error via the onStop callback:
Meteor.subscribe('somePub', args, {
onStop: function (e) {
// display e to user
}
})
However, while on the server the pubErr is a Meteor.Error and according to the documentation it should be sent to the client, the client just receives a generic sanitized error message:
on the server
{
stack: "useful stack of actual method calls",
error: "somePub.failed",
reason: "somePub.invalidArguments",
details: { arg: undefined }
}
on the client
{
stack: "long list of ddp-message calls",
isClientSafe: true,
error: 500,
reason: "Internal server error",
details: undefined,
message: "Internal server error [500]",
errorType: "Meteor.Error"
}
Note: I also tried to add the error to itself as sanitizedError field, as in the documentation mentioned, but no success either.
Am I missing something here?
Actually I found the answer to the issue after being pointed into the right direction.
The example code works fine on a new project, so I checked why not in my project and I found, that I did not surround the arguments validation using SimpleSchema by the try/catch (unfortunately my question was poorly designed as it missed this important fact, mainly because I abstracted away the schema validation from the publication creation):
Meteor.publish('somePub', function (args) {
pubSchema.validate(args) // throws on fail
const self = this
try {
// ... publication logic
catch (pubErr) {
self.error(pubErr)
}
})
So I thought this could not be the issue's source but here is the thing: Simple Schema is not a pure Meteor package but a NPM package and won't throw a Meteor.Error but a custom instance of Error, that actually has the same attributes (error, errorType, details) like a Meteor.Error, see this part of the source code of a validation context.
So in order to pass the correct information of a SimpleSchema validation error to the client you should
wrap it in a try/catch
add the isClientSafe flag to it
alternatively convert it to a Meteor.Error
Attach a custom Meteor.Error as sanitizedError property to it

Insert new collection after function runs on server

When I return the geocode from googles API I'm trying to save it into my database. I've been trying to use the code below, to just insert a Test document with no luck. I think it has something to do with meteor being asynchronous. If I run the insert function before the googleMapsClient.geocode function it works fine. Can someone show me what I'm doing wrong.
Meteor.methods({
'myTestFunction'() {
googleMapsClient.geocode({
address: 'test address'
}, function(err, response) {
if (!err) {
Test.insert({test: 'test name'});
}
});
}
});
I see now where you got the idea to run the NPM library on the client side, but this is not what you really want here. You should be getting some errors on the server side of your meteor instance when you run the initial piece of code you gave us here. The problem is that the google npm library runs in it's own thread, this prevents us from using Meteor's methods. The easiest thing you could do is wrap the function with Meteor.wrapAsync so it would look something like this.
try {
var wrappedGeocode = Meteor.wrapAsync(googleMapsClient.geocode);
var results = wrappedGeocode({ address : "testAddress" });
console.log("results ", results);
Test.insert({ test : results });
} catch (err) {
throw new Meteor.Error('error code', 'error message');
}
You can find more info by looking at this thread, there are others dealing with the same issue as well
You should run the googleMapsClient.geocode() function on the client side, and the Test.insert() function on the server side (via a method). Try this:
Server side
Meteor.methods({
'insertIntoTest'(json) {
Test.insert({results: json.results});
}
});
Client side
googleMapsClient.geocode({
address: 'test address'
}, function(err, response) {
if (!err) {
Meteor.call('insertIntoTest', response.json);
}
});
Meteor Methods should be available on the both the server and client sides. Therefore make sure that your method is accessible by server; via proper importing on /server/main.js or proper folder structuring.
(If a method contains a secret logic run on the server, it should be isolated from the method runs on both server & client, though)

Express.js get http method in controller

I am building a registration form (passport-local as authentication, forms as form helper).
Because the registration only knows GET and POST I would like to do the whole handling in one function.
With other words I am searching after something like:
exports.register = function(req, res){
if (req.isPost) {
// do form handling
}
res.render('user/registration.html.swig', { form: form.toHTML() });
};
The answer was quite easy
exports.register = function(req, res) {
if (req.method == "POST") {
// do form handling
}
res.render('user/registration.html.swig', { form: form.toHTML() });
};
But I searched a long time for this approach in the express guide.
Finally the node documentation has such detailed information:
http://nodejs.org/api/http.html#http_http_request_options_callback
Now you can use a package in npm => "method-override", which provides a middle-ware layer that overrides the "req.method" property.
Basically your client can send a POST request with a modified "req.method", something like /registration/passportID?_method=PUT.
The
?_method=XXXXX
portion is for the middle-ware to identify that this is an undercover PUT request.
The flow is that the client sends a POST req with data to your server side, and the middle-ware translates the req and run the corresponding "app.put..." route.
I think this is a way of compromise. For more info: method-override

Resources