I've created a Cloud Code function for creating a new Stripe customer, which works okay. What I can't figure out is the returning of the customer ID to the calling code;
Calling Code
Parse.Cloud.run(
'createCustomer',
{
email: user.get('email'),
username: user.get('username')
},
{
success: function(customerId) {
// never called
console.log('Customer created: ' + customerId);
},
error: function() {
console.log('Error function');
}
}
);
Function
Parse.Cloud.define(
'createCustomer',
function(request, response) {
var email = request.params.email,
description = 'Username: ' + request.params.username;
Parse.Config.get().then(function(config) {
var Stripe = require('stripe');
Stripe.initialize(config.get('stripe_secret_test'));
Stripe.Customers.create({
description: description,
email: email
})
.then(function(customer) {
console.log(customer.id); // Logs out fine
response.success(customer.id);
});
});
}
);
Basically, the success callback in the calling code is never fired, so I can't access the customer ID I want to return. What am I missing? Thanks!
Turns out Cloud functions don't seem to play well if called from within Cloud Code, they run but I couldn't find a way to return a value.
Instead I used a Cloud Code Module, since this function only ever needed to be called from within Cloud Code. Final code is below;
Calling Code (User beforeSave)
var createCustomerModule = require('cloud/stripe/CreateCustomer.js');
createCustomerModule.createCustomer(
user.get('email'),
user.get('username'),
{
success: function(customer) {
request.object.set('stripeCustomerId', customer.id);
response.success();
},
error: function() {
response.error('Failed to create a new Stripe customer');
}
}
);
Function (cloud/stripe/CreateCustomer.js)
exports.createCustomer = function(email, username, callbacks) {
var description = 'Username: ' + username;
Parse.Config.get().then(function(config) {
var Stripe = require('stripe');
Stripe.initialize(config.get('stripe_secret_test'));
// Attempt to create the customer
Stripe.Customers.create({
description: description,
email: email
})
.then(callbacks.success, callbacks.error);
});
};
Related
I’m having an issue with my project. In my angularjs controller a function is being executed and then my function to make a call to my database to update a record is executing without waiting for the first function to complete and therefore sending over an undefined result variable.
Below you can find my code snippets with my attempts so far.
Submit button function:
$scope.submitNewStarters = function () {
// result is returning as undefined <<<<< Issue
var result = $scope.sendNewStarterDetailsToApi();
$scope.updateArchivedImportFlag(result);
};
Controller function handling the logic:
$scope.sendNewStarterDetailsToApi = function () {
swal({
title: "Confirmation",
text: "Are you sure you want to import the new starter details?",
icon: "info",
dangerMode: true,
buttons: ["No", "Yes"]
}).then(function (approve) {
if (approve) {
// Get each of the new starter details that have been set to true for import.
var newStartsToImport = $scope.tableParams.data.filter(x => x.imported == true);
for (let i = 0; i < newStartsToImport.length; i++) {
// Parses the current new starter object into a stringified object to be sent to the api.
$scope.newStartsToImport = $scope.createApiObject(newStartsToImport[i]);
// A check to ensure that nothing has went wrong and that the stringify object has worked.
if ($scope.newStartsToImport !== "") {
apiFactory.postNewStarterDetailsToApi($scope.newStartsToImport).then(function (response) {
var isSuccessful = response.data.d.WasSuccessful;
if (isSuccessful)
toastr.success("New starter details successfully sent to API.", "Success!");
else {
var errorMessage = response.data.d.ErrorMessage;
toastr.error("New starter details were unsuccessfully sent to API. Please try again. \n" + errorMessage, "Error!");
}
});
}
else {
toastr("An error has occurred when attempting to create the data object to be sent to API. The process has stopped!", "Error!");
break;
}
}
return newStartsToImport;
}
else
toastr.info("No new starter details were sent to API", "Information!");
});
};
Factory function for API call:
postNewStarterDetailsToApi: function (data) {
return $http({
url: "https://www.example.com/services/service.svc/Import",
method: "POST",
data: data,
headers: {
'Content-Type': 'application/json; charset=utf-8',
}
}).then(function successCallbwack(response) {
// this callback will be called asynchronously
// when the response is available
return response;
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
console.log('An error has occured during the function call postNewStarterDetailsToApi(): ', response);
});
}
So with the concept of promises how am I able to execute the sendNewStarterDetailsToApi function, wait for it to complete and then return the populated array? Once the populated array (result) is returned then execute the updateArchivedImportFlag function.
Below I've added an illustration of what I'd like to achieve:
The approach I am using is , save all the promises in an array .
Use any promise library or es6 Promise, and use .all function to wait for all promises to execute
The syntax i wrote is not totally correct. Since you are using angular js , you can use $q.all
$scope.sendNewStarterDetailsToApi = function () {
swal({
title: "Confirmation",
text: "Are you sure you want to import the new starter details?",
icon: "info",
dangerMode: true,
buttons: ["No", "Yes"]
}).then(function (approve) {
var res = [];
if (approve) {
// Get each of the new starter details that have been set to true for import.
var newStartsToImport = $scope.tableParams.data.filter(x => x.imported == true);
for (let i = 0; i < newStartsToImport.length; i++) {
// Parses the current new starter object into a stringified object to be sent to the api.
$scope.newStartsToImport = $scope.createApiObject(newStartsToImport[i]);
// A check to ensure that nothing has went wrong and that the stringify object has worked.
if ($scope.newStartsToImport !== "") {
res.push(apiFactory.postNewStarterDetailsToApi($scope.newStartsToImport))
}
else {
toastr("An error has occurred when attempting to create the data object to be sent to API. The process has stopped!", "Error!");
break;
}
}
return Promise.all(res);
}
else
toastr.info("No new starter details were sent to API", "Information!");
}).then(function (data) {
data.forEach((response) => {
var isSuccessful = response.data.d.WasSuccessful;
if (isSuccessful)
toastr.success("New starter details successfully sent to API.", "Success!");
else {
var errorMessage = response.data.d.ErrorMessage;
toastr.error("New starter details were unsuccessfully sent to API. Please try again. \n" + errorMessage, "Error!");
}
})
}).then((res) => {
//call Submit new starters
})
};
Tried loads of different variations with my cloud code and I can't get it to work. Basically I've got a push notification function, and in this function I want to add an object to a PFUser's array, but you can't use a master key in Xcode so here's what I have:
Parse.Cloud.define("iOSPush", function (request, response) {
console.log("Inside iOSPush");
var data = request.params.data;
var not_class = request.params.not_class;
var not_objectid = request.params.not_objectid;
var not_date = request.params.not_date;
var userid = request.params.userid;
var recipientUser = new Parse.Query(Parse.User);
recipientUser.equalTo("objectId", userid);
// set installation query:
var pushQuery = new Parse.Query(Parse.Installation);
pushQuery.equalTo('deviceType', 'ios');
pushQuery.matchesQuery('user', recipientUser);
pushQuery.find({ useMasterKey: true }).then(function(object) {
response.success(object);
console.log("pushQuery got " + object.length);
}, function(error) {
response.error(error);
console.error("pushQuery find failed. error = " + error.message);
});
// send push notification query:
Parse.Push.send({
where: pushQuery,
data: data
}, { useMasterKey: true }).then(function() {
console.log("### push sent!");
// create notification:
var notification = {
"title": not_class,
"body": request.params.data.alert,
"class": not_class,
"objectId": not_objectid,
"date": not_date
};
// get notifications:
var tmp_notifications = recipientUser.get("notifications");
// add notification:
tmp_notifications.push(notification);
// update with notifications:
recipientUser.set("notifications", tmp_notifications);
recipientUser.save();
}, function(error) {
console.error("### push error" + error.message);
});
response.success('success. end of iospush');
});
The Xcode cloud function I have provides the correct information, the function gets to the end.. just the function is not setting the notifications for some reason
I ended up figuring out the answer to this post myself. The reason this didn't work is because I needed to first fetch the user object in a separate query, then save it using the master key. I also found out that there's a function for appending data onto an existing array without having to create another one (parseObject.add()):
var userQ = new Parse.Query(Parse.User);
userQ.get(userid, {
success: function(theuser) {
console.log("### got userrrrrrrrrr!");
theuser.add("notifications", n_object);
theuser.save(null, {useMasterKey:true});
},
error: function(object, error) {
// The object was not retrieved successfully.
// error is a Parse.Error with an error code and message.
}
});
This set of code was executed just before:
response.success('success. end of iospush');
I want to get some parameters and use them to reset password function from firebase.
This is how my link looks like:
http://localhost:8080/passwordreset?mode=resetPassword&oobCode=y6FIOAtRUKYf88Rt5OlEwxUuTyEmb3M4gquZSIseX2UAAAFevpj-gw&apiKey=AIzaSyBaCCvq-ZEfQmdrL7fmElXDjZF_J-tku2I
I want to get mode, oobCode and apiKey.
Here is what I have for now:
export default {
data: function() {
return {
passwordNew: '',
passwordConfirm: '',
mode:'',
actionCode: '',
continueUrl: '',
}
},
methods: {
handleResetPassword: function() {
var accountEmail;
firebase.auth().verifyPasswordResetCode(actionCode).then(function(email) {
var accountEmail = email;
firebase.auth().confirmPasswordReset(this.actionCode, this.passwordNew).then(function(resp) {
alert("Password reset success");
this.$router.push('hello')
}).catch(function(error) {
// Error occurred during confirmation. The code might have expired or the
// password is too weak.
console.log("error 1")
});
}).catch(function(error) {
// Invalid or expired action code. Ask user to try to reset the password
// again.
console.log("error 2")
});
},
}
}
From Firebase documentation:
Some user management actions, such as updating a user's email address
and resetting a user's password, result in emails being sent to the
user. These emails contain links that recipients can open to complete
or cancel the user management action. By default, user management
emails link to the default action handler, which is a web page hosted
at a URL in your project's Firebase Hosting domain.
link: https://firebase.google.com/docs/auth/custom-email-handler
You need to get those parameters and store them on variables, from firebase documentation i got those snippets and just wrote the getParameterByName function:
function getParameterByName( name ){
name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
var regexS = "[\\?&]"+name+"=([^&#]*)";
var regex = new RegExp( regexS );
var results = regex.exec( window.location.href );
if( results == null )
return "";
else
return decodeURIComponent(results[1].replace(/\+/g, " "));
}
// Get the action to complete.
var mode = getParameterByName('mode');
// Get the one-time code from the query parameter.
var actionCode = getParameterByName('oobCode');
// (Optional) Get the continue URL from the query parameter if available.
var continueUrl = getParameterByName('continueUrl');
You need to get those parameters first and verify the actioncode on the verifyPasswordResetCode method, then you can change the password and store it along with the action code to the method.
In your export default :
data: function() {
return {
passwordNew: '',
passwordConfirm: '',
mode: mode,
actionCode: actionCode,
continueUrl: continueUrl,
}
},
methods: {
handleResetPassword: function() {
var passwordNew = this.passwordNew
var actionCode = this.actionCode
firebase.auth().verifyPasswordResetCode(actionCode).then(function(email) {
console.log("ActionCode: "+ actionCode);
firebase.auth().confirmPasswordReset(actionCode, passwordNew).then(function(resp) {
alert("Password reset success");
this.$router.push('hello')
}).catch(function(error) {
console.log("error 1"+ error)
});
}).catch(function(error) {
console.log("Action code is invalid"+ error)
});
},
}
This question already has an answer here:
How come Angular doesn't update with scope here?
(1 answer)
Closed 8 years ago.
I'm writing my first angularjs app, and it's beginning to make sense. However, I have a sign up form that isn't getting the messages in some cases to alert users to problems. I'm using Firebase to authenticate, which works fine. But I'm storing users by a unique username as the key. So before I run the $createUser function, I do a quick query to see if there's already a user object with this key-- if not, I create the user.
The problem is when there is an existing user with this username. The console log value prints fine, but the error message (bound to $scope.authMsg) doesn't show up the first time-- but if I click the "register" button again, then the message shows up in the expected message div.
Any hints on the message issue (or suggestions for this code) would be appreciated!
$scope.register = function() {
$scope.authMsg = '';
var ref = new Firebase(FIREBASE_URL);
$scope.authObj = $firebaseAuth(ref);
// check if the username is taken
ref.child("/users/"+$scope.account.username).on("value", function(snapshot) {
if (snapshot.val()) {
//
// PROBLEM HERE!!
//
$scope.authMsg = 'Username exists-- did you forget your password?'; // doesn't show on page until second submit
console.log('Username exists-- did you forget your password?'); // prints to console as expected
} else {
$scope.authObj.$createUser({ email: $scope.account.email, password: $scope.account.password })
.then(function(userData) {
console.dir(userData);
return $scope.authObj.$authWithPassword({
email: $scope.account.email,
password: $scope.account.password
});
}).then(function(authData) {
// we created a user and are now logged in-- store user info
var userdata = {};
userdata[$scope.account.username] = {
uid: authData.uid,
first_name: $scope.account.first_name,
last_name: $scope.account.last_name,
email: $scope.account.email,
full_name: $scope.account.first_name+' '+$scope.account.last_name
};
var usersRef = ref.child("users");
// save the userdata
usersRef.set(userdata);
console.log("Logged in as:", authData.uid);
$state.go('app.dashboard');
}).catch(function(error) {
$scope.authMsg = error;
console.error("Error: ", error);
});
}
}, function (errorObject) {
$scope.authMsg = 'The read failed: ' + errorObject.code;
console.log('The read failed: ' + errorObject.code);
});
};
I'm assuming, the Firebase callback does not involve an angular digest cycle.
To handle this, write
if (snapshot.val()) {
$scope.$apply(function() {
$scope.authMsg = 'Username exists— did you forget your password?';
});
A useful reading about the topic: http://jimhoskins.com/2012/12/17/angularjs-and-apply.html
I have followed Authentication Tutorial, but running into some issues.
I have a php backend api which resides in another domain, http://rest.api {local development}
The ember js application uses ember-app-kit and connects to the rest api.
When the user submits the login form it sends the username/email with password to one of the route defined in the rest api Session Controller
import AuthManager from 'lms/config/auth_manager';
var SessionNewController = Ember.ObjectController.extend({
attemptedTransition : null,
loginText : 'Log In',
actions: {
loginUser : function() {
var self = this;
var router = this.get('target');
var data = this.getProperties('identity', 'password');
var attemptedTrans = this.get('attemptedTransition');
$.post('http://rest.api/login',
data,
function(results) {
console.log(results.session);
console.log(results.user_id);
AuthManager.authenticate(results.session, results.user_id);
if(attemptedTrans) {
attemptedTrans.retry();
self.set('attemptedTransition', null);
} else {
router.transitionTo('index');
}
}
)
}
}
});
export default SessionNewController;
After receiving the api result in the results variable which looks like this :
Object {success: "user login success", session: "2OmwKLPclC.YhYAT3745467my7t0m2uo", user_id: "1"}
But as soon as I capture the data and send it to the AuthManager which resides in Auth Manager Code
import User from 'lms/models/user';
import Application from 'lms/adapters/application';
var AuthManager = Ember.Object.extend({
init: function() {
this._super();
var accessToken = $.cookie('access_token');
var authUserId = $.cookie('auth_user');
if(!Ember.isEmpty(accessToken) || !Ember.isEmpty(authUserId)) {
this.authenticate(accessToken, authUserId);
}
},
isAuthenticated: function() {
return !Ember.isEmpty(this.get('ApiKey.accessToken')) && !Ember.isEmpty(this.get('ApiKey.user'));
},
authenticate: function(accessToken, userId) {
$.ajaxSetup({
headers: { 'Authorization': 'Bearer ' + accessToken }
});
var user = User.store.find(userId);
console.log(user);
this.set('ApiKey', ApiKey.create({
accessToken: accessToken,
user: user
}));
},
reset: function() {
this.set('ApiKey', null);
$.ajaxSetup({
headers: { 'Authorization': 'Bearer None' }
});
},
apiKeyObserver: function() {
Application.accessToken = this.get('apikey.accessToken');
if (Ember.isEmpty(this.get('ApiKey'))) {
$.removeCookie('access_token');
$.removeCookie('auth_user');
} else {
$.cookie('access_token', this.get('ApiKey.accessToken'));
$.cookie('auth_user', this.get('ApiKey.user.id'));
}
}.observes('ApiKey')
});
export default AuthManager;
I got an error in the console saying
Uncaught TypeError: Object function () {
if (!wasApplied) {
Class.proto(); // prepare prototype...
}
o_defineProperty(this, GUID_KEY, undefinedDescriptor);
o_defineProperty(this, '_super', undefinedDescriptor);
var m = met...<omitted>...e' new.js:23
(anonymous function) new.js:23
jQuery.Callbacks.fire jquery.js:1037
jQuery.Callbacks.self.fireWith jquery.js:1148
done jquery.js:8074
jQuery.ajaxTransport.send.callback jquery.js:8598
It is not able to pass the variables to the imported function.
Finally got this working. The error that was I doing is after extending the Ember.Object.extend() on auth_manager.js, I didn't create the object anywhere. Thats why it couldnt set create a cookie and throwing that error message.
All I had to do was, .create() after extending the object.
Don't know whether it is the right method or not. But it certainly works.