Paypal recurring Smart Payment Button - button

Is it possible with the Smart Payment Button for Paypal recurring payments to pass additional parameters like an invoice id for example.
paypal.Buttons({
createSubscription: function(data, actions) {
return actions.subscription.create({
'plan_id': 'P-2UF78835G6983425GLSM44AM'
});
},
onApprove: function(data, actions) {
alert('You have successfully created subscription ' + data.subscriptionID);
}
}).render('#paypal-button-container');
This is the example code from https://developer.paypal.com/docs/subscriptions/integrate/#4-create-a-subscription
and it says:
Calls PayPal using actions.subscription.create() to create a subscription for your plan and includes the plan ID, subscriber details, shipping, and other details.
But I can't pass anything besides the plan_id.

You can add the custom_id field as explained on this page
In that case, your code would look like
return actions.subscription.create({
'custom_id': 'my-custom-code-for-integration',
'plan_id': 'P-2UF78835G6983425GLSM44AM'
});

The underlying API is /v1/billing/subscriptions
Here is the reference: https://developer.paypal.com/docs/api/subscriptions/v1/#subscriptions_create
It does not appear to have a field for an invoice_id -- so, the answer to your question is No, it is not possible.
You will get a unique PayPal subscription profile ID in the resulting response, e.g. "id": "I-BW452GLLEP1G" -- So, what you can do is store that profile ID in your own invoice record.
Example of a createSubscription function that calls a server that can check for pre-existing active duplicates before creating the subscription (or return an error otherwise)
createSubscription: function(data, actions) {
return fetch('/path/on/your/server/paypal/subscription/create/', {
method: 'post'
}).then(function(res) {
return res.json();
}).then(function(serverData) {
console.log(serverData);
return serverData.id;
});
},

Related

custom javascript cannot return client ID var google tag manager

I have tried to get the client ID with custom javascript but it cannot return the value. Below is the code is tried. Would like to seek help from all experts. Thanks.
function () {
return function () {
try {
var trackers = ga.getAll();
trackers.forEach(function(tracker) {
var cid = tracker.get('clientId');
tracker.set('dimension1', cid);
});
} catch (e) {}
}
}
It cannot return a normal client ID
Your custom variable returns a function, not a value (since the function is never actually executed).
A better way to get the clientId for each current tracker is to use a custom task in Google Analytics (tasks are basically individual steps in the tracker lifecycle, from checking if a client id exists to assemble the payload to actually sending the data). A task is a Javascript function that is added to the GA tag via the "set fields" configuration. Tasks have access to the tracker data model and can add, remove or modify values from the payload.
The only task you can use via GTM is the customTask, which as the name suggests, adds custom capabilities to the tracker.
If you create a custom javascript variable called e.g. "getClientId" with the following code:
function() {
// Modify customDimensionIndex to match the index number you want to send the data to
var customDimensionIndex = 5;
return function(model) {
model.set('dimension' + customDimensionIndex, model.get('clientId'));
}
}
then go to your GA settings tag, and in the "set field" configuration set the field name "customTask" with the variable as value, the clientId will be extracted from the data model and added to the payload as custom dimension.
Better than my explanation is Simo Ahavas GTM tip for setting the client id via custom tasks.

How can I get other users' profiles details in meteor

I have got problem accessing the user profile details of the users other then the current user.
The goal is to display a little footer under a each of the posts in the kind of blog entries list . Footer should consist of the post and author details (like date, username etc.).
Blog entry is identified by authors' _id but the point is that I can not access
Meteor.users.find({_id : authorId});
Resulting cursor seems to be the same as Meteor.user (not 'users') and consists of one only document, and is valid for the current user ID only. For others, like authors ID, I can only get an empty collection.
The question is, if is there any way, other then next Meteor.users subscription to get authors profile (like username profile.nick etc) ???
Update: You can Publish Composite package if you want to get blog entry and user details in a single subscription. See the following sample code and edit as per your collection schemas,
Meteor.publishComposite('blogEntries', function (blogEntryIds) {
return [{
find: function() {
return BlogEntries.find({ courseId: { $in: blogEntryIds }});
// you can also do -> return BlogEntries.find();
// or -> return BlogEntries.find({ courseId: blogEntryId });
},
children: [{
find: function(blogEntry) {
return Meteor.users.find({
id: blogEntry.authorId
}, {
fields: {
"profile": 1,
"emails": 1
}
});
}
}}
}]
});
End of update
You need to publish Meteor.users from the server to be able to use it on client. accounts package will publish current user, that's why you are only seeing current user's information.
In a file in server folder or in Meteor.isServer if block do something like this
//authorIds = ["authorId1", "authorId2];
Meteor.publish('authors', function (authorIds) {
return Meteor.users.find({ _id : { $in: authorIds }});
});
or
Meteor.publish('author', function (authorId) {
return Meteor.users.find({ _id : authorId });
});
Then on client side subscribe to this publication, in template's onCreated function, with something like this
Meteor.subscribe('author', authorId); //or Meteor.subscribe('author', authorIds);
or
template.subscribe('author', authorId); //or template.subscribe('author', authorIds);
If you want to show only username (or a few other fields), you can save them in post document along with authorId. For example:
post:{
...
authorId: someValue,
authorName: someValue
}
You can use them in your templates as a field of a post.
If you have too many fields which you do not want to embed in post document, (so you want to keep only authorId), you can use publish-composite when you make your posts publication. (See example 1)
You do not need to publish all your users and their profiles.

Meteor observeChanges vs manual update

I have a simple todo schema: (just a sample to draw my question)
{
title: {
type: string
},
value: {
type: string
},
author: {
type: object
},
"author._id": {
type: string
},
"author.firstName": {
type: string
},
"author.lastName": {
type: string
},
}
The author entries are from meteor.user. If the meteor user changes the firstName or lastName i have to update the todo. I have two possibilities:
observerChanges (server side) to users collection and update all todos from this user with the new firstname/lastname
if i call the user update method i can call a method to update all todos
when it's better to use cursor.observeChanges and when it's better to call a update method manual? And why?
As the comment says, you should not store the author name / email in the document if it is mutable:
Store the ID of the user only in the document, the UserID is immutable.
When building your ToDo template, look up the User information by ID: you would need to publish a Publication for user by Id, and subscribe to it on the client with the userId as parameter.
Meteor.publish('userById', function(userId) {
return Meteor.users.find({_id: userId}, {limit:1});
});
in your route / template.onCreated depending on your Router, assuming the document is called doc
this.subscribe('userById', this.doc.author._id);
in the template helper
Template.todoTemplate.helpers({
'Author': function() {
return Meteor.users.findOne({_id: this.doc.author._id});
}
});
and call the Author info in the template
<Template name="todoTemplate">
First Name: {{Author.first_name}}
Last Name: {{Author.last_name}}
</Template>
I think you shouldn't rely on the second method, because sometimes you (or your teammate) might forget to update it. Moreover, if you're denormalizing user data in other collections, users knowing Meteor might just call your Meteor.method or manipulate db from the browser console...
You can use this package:
meteor add matb33:collection-hooks
It adds some hooks to your mongo insert/update/remove call
For example:
Meteor.users.after.update(function (userId, doc, fieldNames, modifier, options) {
if (this.previous.firstName === doc.firstName && this.previous.lastName === doc.lastName) {
return;
}
Todos.update({'author._id': doc._id}, {
$set: {
'author.firstName': doc.firstName,
'author.lastName': doc.lastName,
}
})
}, {fetchPrevious: true})
(To update the Todos collection efficiently, make sure to add index to author field)
This is just a handier way than writing your own observeChanges, and better than manually updating Todos collection every time you update the users collection, because you might forgot to call it in some case, or some hacker user just calls Meteor.users.update(Meteor.userId(), {...}) perhaps...
But still, I think you should always add some auto-correct mechanism to avoid wrong data being displayed, because no matter which method you choose, some error will occur (maybe the server watching the db just crashes right after users update). You can check on the client side when displaying content, if author.firstName doesn't match Meteor.users.findOne(author._id) (but you have to publish the user though...), than call a method to tell the server to update it.

Meteor Iron Router resubscribe on Rights change with meteor-roles

I am writing a meteor application with a user-role-system (alanning:roles) My Roles are group based. When a user knows my group url, it is allowed to access the group an get the role "defaultUser" in this group.
localUser is allowed to subscribe to all the local stuff of a group.
based on the group's ID, I also publish some contents.
The Problem is: the Subscription does not resubscribe.
Workflow:
user accesses app,
calls meteor-method to get the default role
gets the default role
subscribes to a publication
the publication (complete-group) publishes the contents if the user has the right role
My Publication looks like:
Meteor.publish "thisGroupPublic", (id) ->
return db.groups.find({_id: id}, {fields: {onlypublicones...}}
Meteor.publishComposite "thisGroupReactive", (id) ->
return {
find: () ->
if !Roles.userIsInRole(#userId, "defaultUser", id)
#ready()
console.log("[thisGroupReactive] => No Rights")
return;
return db.groups.find({_id: id});
children: [
{
find: (group) ->
return db.contents.find({groups: {$in: [group._id]}}, {fields: {apikey: 0}})
}
]
}
The user subscribes the subscription "thisGroupPublic" when the user is on the login page and gets the role "defaultUser" on its first visit to the group as a logged in user. But how do I need to configure iron:router to
resubscribe this subscription that the contents are shown and not only the public stuff?
Say that the user is on a route /something
You have some data that changes and you create a session variable:
Session.set("someDataThatChanges", myChangedData)
Your publish function takes some sort of input, which it uses to return different data from the collection:
Meteor.publish("myCollection", function(input){
return myCollection.find(
// do something here based on 'input'
);
});
Iron Router has a .subscribe method that is the same as Meteor.subscribe and also a subscriptions key that takes a function. You can wrap a Tracker.autorun around your .subscribe and put in your session variable to automatically re-subscribe to something based on the changing value of that session variable.
Router.route("/something", {
name: "templateName",
// a place to put your subscriptions
subscriptions: function() {
console.log("this in router ", this);
Tracker.autorun(function(){
this.subscribe('myCollection', Session.get("someDataThatChanges");
});
},
});

How to honour user privacy settings in Meteor

I have a set of users defined like this:
Accounts.createUser({
username:'Simon',
email:'simon#email.com',
profile:{
firstname:'Simon',
lastname:'Surname',
location:'Home Address',
privacy: {
location:0,
emails:0 } //Location and emails are private and should not be disclosed
}
});
My question is how can I publish this user's record for other users to view, taking into account the profile privacy settings. In this example, I have set the privacy for location and emails to zero with the intention that this information is not published for this user.
I would like to publish it using the standard method:
Meteor.publish("usersWithPublicEmails", function () {
return Meteor.users.find();
});
But I cannot see a way to specify the selector or fields in such a way that only public information will be published.
I have tried adding additional publications of the form:
Meteor.publish("allUsers", function () {
return Meteor.users.find( {}, {fields:{username:1}} );
});
Meteor.publish("usersWithPublicEmails", function () {
return Meteor.users.find( {"profile.privacy.emails":1}, {fields:{username:1, emails:1}} );
});
but the selector does not seem to be returning the emails as I expected. I am looking for optimal way to do this from a performance point of view.
Mongodb is not a relational database so whenever I want to join or query based on metadata I remember I have to do things differently. In your case I would make a separate Collection for user privacy if I wanted to query on user privacy. In addition, if I cared about performance I probably would never want "all of x", I would just want enough to show the user, thus paginate. With these two ideas in mind you can easily get what you want: query based on privacy settings and performance.
Privacy = new Mongo.Collection("privacy");
Whenever we want to add privacy to an account:
Privacy.insert({
emails: 1,
userId: account._id,
});
Then later, one page at a time, showing ten results each page, tracking with currentPage:
Meteor.publish("usersWithPublicEmails function (currentPage) {
var results = []
var privacyResults = Privacy.find({"emails":1}, {skip: currentPage,
limit: 10});
var result;
while (privacyResults.hasNext() ) {
result = privacyResult.next();
results.append(Meteor.users.find({_id: result.userId});
}
return result;
});
I didn't test this code, it may have errors, but it should give you the general idea. The drawback here is that you have to keep privacy and users in sync, but these are the kinds of problems you run into when you're not using a relational database.
Mongodb has a way to do this kind of reference lookup with less code, but it still happens on demand and I prefer the flexibility of doing it myself. If you're interested take a look at Database references
That's because you have a typo in your publish function's fields object, instead of email you've typed emails
So the correct function would be:
Meteor.publish("usersWithPublicEmails", function () {
return Meteor.users.find( {"profile.privacy.emails":1}, {fields:{username:1, email:1}} );
});
Furthermore, you're already publishing all usernames in your allUsers publication, therefore, in order to add the missing data for relevant public users, you'll just need this:
Meteor.publish("usersWithPublicEmails", function () {
return Meteor.users.find( {"profile.privacy.emails":1}, {fields:{email:1}} );
});
and Meteor will automatically merge those records for you.
A simple solution in the end. I had missed the additional subscription in my router:
Router.route('/users', {
name: 'userList',
waitOn: function(){
return Meteor.subscribe('allUsers') &&
Meteor.subscribe('usersWithPublicEmails');
},
data: function(){
return Meteor.users.find();
}
});
A basic mistake:-(

Resources