Reputation: 74
I have a webhook set up that lives in imports/api in my application. This is a Stripe webhook and I’m trying update Campaign collection. I’m using a Meteor method to make this call however nothing happens. If I add the call back to it, I receive no error or results. However if I take this same Meteor Method an include it in main.js on the server in a Meteor startup function it runs fine. I’ve also tried just using the update function for a collection and it won’t work either. Main.js includes this file and I cannot figure out why this doesn’t work nor will push an error. The most important part of this line is the bottom where Paid == true, this is where the logic is. The console will spit out the information but the method won’t run. What could be the issue?
import bodyParser from 'body-parser';
import { Picker } from 'meteor/meteorhacks:picker';
import {Campaign} from '../api/campaigns';
let campaignID;
let chargeAmount;
let chargeID;
let hasPaid = false;
//This will run outside the updateCampaign function fine and works as expected
Campaign.update({_id: "BAxBhk4ae3AdHxxEQ"}, {$set: {chargeTrx: "chargeID", amount: "555"}});
function updateCampaign(){
//these consoles will print and prove the function runs
console.log('campaignID type:' + campaignID)
console.log('chargeIDtype:' + chargeID)
console.log('amount type:' + chargeAmount)
//doesn't work even with strings prefilled
Campaign.update({_id: "BAxBhk4ae3AdHxxEQ"}, {$set: {chargeTrx: "chargeID", amount: "333"}});
//This didn't run either but would run outside of this function
Meteor.call("updateCampaignForPayment", campaignID, chargeAmount, chargeID, (err, result) => {
if (err){
console.log('error')
}
});
}
// Middleware declaration
Picker.middleware(bodyParser.json({
limit: '10MB',
verify: function(req,res,buf) {
var url = req.originalUrl;
if (url.startsWith('/webhook')) {
req.rawBody = buf.toString();
let newResponse = req.rawBody;
//stripe returns to 2 objects, this makes it two arrays to parse it
let parsedResponse = JSON.parse('[' + newResponse.replace(/}{/g, '},{') + ']');
parsedResponse = parsedResponse[0].data.object;
//break down two further objects
if (parsedResponse.object == "charge"){
chargeID = parsedResponse.id;
hasPaid = parsedResponse.paid;
chargeAmount = parsedResponse.amount / 100;
}
else if (parsedResponse.object == "checkout.session"){
let campaignIDArray = parsedResponse.success_url.split('/');
campaignID = campaignIDArray[5];
}
// If user has paid, update campaign
if (hasPaid == true && chargeID && campaignID && chargeAmount){
console.log(hasPaid, chargeID, campaignID, chargeAmount)
//
updateCampaign();
}
}
}
}));
Upvotes: 0
Views: 229
Reputation: 8423
Any calls outside of the current Meteor environment (such as in callback functions or middleware handlers) to a construct, which requires Meteor environment, are to be bound using the Meteor environment.
In your case this seems to be updateCampaign
, because it makes calls to the Meteor-Mongo Collection:
const updateCampaign = Meteor.bindEnvironment(function () {
const updated = Campaign.update({_id: "BAxBhk4ae3AdHxxEQ"}, {$set: {chargeTrx: "chargeID", amount: "333"}});
const callResult = Meteor.call("updateCampaignForPayment", campaignID, chargeAmount, chargeID);
})
Please also note, that the collection inside this function is running in async mode and only within Meteor environment code you can write code in a sync way and let it handle the async. You can always "wait" for the result there using async/await
:
function async updateCampaign(){
const updated = await Campaign.update({_id: "BAxBhk4ae3AdHxxEQ"}, {$set: {chargeTrx: "chargeID", amount: "333"}});
//This didn't run either but would run outside of this function
const callResult = await Meteor.call("updateCampaignForPayment", campaignID, chargeAmount, chargeID);
}
or you use Promise.await
, if you want to avoid async/await
:
function updateCampaign(){
const updated = Promise.await(Campaign.update({_id: "BAxBhk4ae3AdHxxEQ"}, {$set: {chargeTrx: "chargeID", amount: "333"}}))
//This didn't run either but would run outside of this function
const callResult = Promise.await(Meteor.call("updateCampaignForPayment", campaignID, chargeAmount, chargeID))
}
Readings:
https://guide.meteor.com/using-npm-packages.html#bind-environment
https://docs.meteor.com/api/methods.html#Meteor-call
https://guide.meteor.com/using-npm-packages.html#promises
https://github.com/meteor/meteor/tree/devel/packages/promise
Upvotes: 2