Dynamically setting up the PayPal Checkout Transaction using JASON - paypal-sandbox

Depending on the goods being purchased I would like to create a JASON object to be placed into the Transaction area of the PAYPAL transaction. I keep failing no matter what I do. Following is the javascript code I am using to test:
paypal.Button.render({
env: 'sandbox',
client: {
sandbox: 'demo_sandbox_client_id'
},
payment: function (data, actions) {
var oAmount = {},
oAmount_details = {};
oAmount.total = '30.11';
oAmount.currency = "USD";
oAmount_details.subtotal = '30.00';
oAmount_details.tax = '00.11';
oAmount.details = oAmount_details;
return actions.payment.create({
transactions: [{
amount: oAmount
/*
amount: {
total: '30.11',
currency: 'USD',
details: {
subtotal: '30.00',
tax: '0.11'
}
}
*/
}]
});
},
onAuthorize: function (data, actions) {
return actions.payment.execute()
.then(function () {
window.alert('Thank you for your purchase!');
});
}
}, '#paypal-button');
*Note if you comment out:
amount: oAmount
and then uncomment:
amount: {
total: '30.11',
currency: 'USD',
details: {
subtotal: '30.00',
tax: '0.11'
}
}
then it will work.
Any help will be greatly appreciated.
fiddle

Related

How do I create a custom connect stripe account and pass account id to payment intent method using firebase functions?

I am trying to collect and transfer payments using firebase cloud functions in my react native app. I'm using the stripe.accounts.create and stripe.paymentIntents.create functions as well as library axios. I'm really not too sure how to create the connect account and pass the account id created into the payment intent method. I get the following error in the firebase logs 'code: 'StripeInvalidRequestError: Can only apply an application_fee_amount when the PaymentIntent is attempting a direct payment (using an OAuth key or Stripe-Account header) or destination payment (using transfer_data[destination])'
when trying to run my code below. Can someone please assist? I don't think the connectAcc.id is null since I can see it in my stripe dashboard logs in the response body where the account is created:
Response body
{
"id": "acct_**********U5",
"object": "account",
"business_profile": {
"mcc": "5734",
"name": null,
"product_description": null,
"support_address": null,
"support_email": null,
"support_phone": null,
"support_url": null,
index.js file
const stripe = require('stripe')('**SK_LIVE**');
exports.payWithStripe = functions.https.onRequest((request, response) => {
const connectAcc = stripe.accounts.create({
type: 'custom',
email: 'name#gmail.com',
country: 'GB',
business_type: 'individual',
business_profile: {
mcc: '5734',
url: 'site.com',
},
individual: {
first_name: 'First',
last_name: 'Last',
dob : {
day: 1,
month: 10,
year: 1990
},
email: 'name#gmail.com',
phone: '+44xxxxxxx',
address: {
city: 'city',
country: 'GB',
line1: '1',
line2: 'Street Rd',
postal_code: 'XXX XXX'
}
},
tos_acceptance: {
date: Math.floor(Date.now() / 1000),
ip: request.connection.remoteAddress,
},
capabilities: {
card_payments: {requested: true},
transfers: {requested: true},
},
external_account: {
object: 'bank_account',
country: 'GB',
currency: 'gbp',
account_number: 'xxxxx',
routing_number: 'xxxxx',
accounter_holder_name: 'First Last',
account_holder_type: 'individual',
}
})
stripe.paymentIntents.create({
amount: request.body.amount,
currency: request.body.currency,
payment_method_types: ['card'],
payment_method: request.body.payment_method.id,
application_fee_amount: 20,
on_behalf_of: connectAcc.id,
transfer_data: {
destination: connectAcc.id,
},
confirm: true,
description: 'UniHome'
}
).then((charge) => {
response.send(charge);
})
.catch(err =>{
console.log(err);
})
});
Thanks.
connectAcc is not an account object — it's a Promise. That's what Stripe's SDK returns.
You'd have to resolve the Promise first, like:
let connectAcc = await stripe.accounts.create(...); let id = connectAcc.id or stripe.accounts.create(...).then(function(acct){let id = acct.id;} )

paypal checkout.js popup opens and then closes immediately

<div id="paypal-button"></div>
<script src="https://www.paypalobjects.com/api/checkout.js"></script>
<script>
paypal.Button.render({
client: { sandbox: 'sandboxemailaddress',
production: 'dummyemailaddress'},
env: 'sandbox',
payment: function() {
var env = this.props.env;
var client = this.props.client;
return paypal.rest.payment.create(this.props.env, this.props.client, {
transactions: [
{
amount: {total: 20.00, currency: 'USD' },
locale: 'en_US',
enableShippingAddress: true,
shippingAddressEditable: false,
shippingAddressOverride: {
recipientName: 'John Public',
line1: '123 South East St',
line2: '',
city: 'Upland',
state: 'CA',
postalCode: '91711',
countryCode: 'US',
countryCode: 'US',
phone: '909-626-3777'
}
}
],
});
},
commit: true,
onAuthorize: function(data, actions) {
return actions.payment.execute().then(function() {
});
},
'#paypal-button');
</script>
Button displays w/o error being reported.
On clicking on the button the box opens up on the screen, the wait circle appears and then the box closs. Javascript console in Firefox reports:
window.paypal<["./node_modules/post-robot/src/drivers/receive/types.js"]/exports.RECEIVE_MESSAGE_TYPES< https://www.paypalobjects.com/api/checkout.js:3416:40
receiveMessage https://www.paypalobjects.com/api/checkout.js:1838:13
messageListener https://www.paypalobjects.com/api/checkout.js:1856:13
I had the same issue.
As soon as I added it, it worked:
paypal.Button.render({ <p>
client: { sandbox: 'AdZo0BCkNeg-xxxlongasssssString',
production: 'PRODUCTIONCLIENTIDSTRING'}, <p>
env: 'sandbox', // sandbox | production
change 'sandboxemailaddress' with Client ID.

Meteor aldeed/meteor-collection2 autoValue throwing error

I am trying to use autoValue in my schema
Posts.schema = new SimpleSchema({
title: { type: String },
description: { type: String },
posted: { type: Date,
autoValue: function (){
return new Date;
},
},
likes: { type: Number, defaultValue: 0, optional: true },
dislikes: { type: Number, defaultValue: 0, optional: true, },
author: { type: AuthorSchema },
votes: { type: [AuthorSchema], optional: true }
});
Posts.attachSchema(Posts.schema);
I am using this schema for validations here:
export const addPost = new ValidatedMethod({
name: 'Posts.addPost',
validate: Posts.schema.validator(),
run(post) {
if (!this.userId)
throw new Meteor.Error('403', 'You must be logged-in to reply');
Posts.simpleSchema().clean(post);
Posts.insert({
title: post.title,
description: post.description,
author: {
userId: this.userId,
vote: 0
}
});
}
});
It does not work. I get an error message
Posted is required [validation-error]
Am i doing something wrong? Do i need to make Posted field optional?
I tried to change the insert method by providing default value for posted: new Date(). Did not work either. Please help.
Fixed it by calling validator with { clean : true, filter : false }

meteor - How to add a subdocument as reference with SimpleSchema

I have the following SimpleSchema
Schema.Team = new SimpleSchema({
name:{
type:String
},
members: {
type: [Schema.User],
optional:true
}
});
I would like to insert (on the server) a new team document with the current user, as a reference (not as an embedded document).
I have tried:
Teams.insert({name:"theName",members:[Meteor.user()]}) // works but insert the user as an embedded doc.
Teams.insert({name:"theName",members:[Meteor.user()._id]}) // Error: 0 must be an object
I have also tried in two steps:
var id = Teams.insert({name:teamName});
Teams.update({ _id: id },{ $push: { 'users': Meteor.user()._id } });
Then I have another error I don't understand: Error: When the modifier option is true, validation object must have at least one operator
So how can I insert a document with a reference to another schema?
If you just want to store an array of userIds in your Team collection try:
Schema.Team = new SimpleSchema({
name:{
type:String
},
members: {
type: [String],
optional:true
}
});
Then
Teams.insert({ name: "theName", members: [Meteor.userId()] });
Should work. Later when you want to add an additional id you can just:
Teams.update({ _id: teamId },{ $addToSet: { members: Meteor.userId() }});
The following is probably the syntax you are after, assuming you are also using AutoForm.
If you are using collection2, you can also add an autovalue for when a team is created to automatically add the creator to that team for more convenience.
Schema.Team = new SimpleSchema({
name: {
type:String
},
members: {
type: [String],
defaultValue: [],
allowedValues: function () {
// only allow references to the user collection.
return Meteor.users.find().map(function (doc) {
return doc._id
});
},
autoform: {
// if using autoform, this will display their username as the option instead of their id.
options: function () {
return Meteor.users.find().map(function (doc) {
return {
value: doc._id,
label: doc.username // or something
}
})
}
},
autoValue: function () {
if (this.isInsert && !this.isFromTrustedCode) {
return [this.userId];
}
}
}
});

How can I trigger autocomplete with multiple rules.

I have an autocomplete on a text box which shows zipcode, City, State. Currently when I start typing zipcode [e.g. 55414] the autocomplete works and starts to show the relevant zip,city and State. But I can't figure out how to trigger autocomplete if I start typing a city name. I want both of these triggers on the textbox. I tried to add another rule in the rules array but it doesn't work. ZipCodes collection has _id, city, state fields. _id is zipcode.
Template.search.helpers({
settings : function () {
return {
position: "bottom",
limit: 20,
rules: [{
collection: ZipCodes,
field: "_id",
template: Template.userPill
}]
}
}
Thanks in advance
I think you are using meteor-autocomplete
In that case you can use selector option
Template.search.helpers({
settings : function () {
return {
position: "bottom",
limit: 20,
rules: [{
collection: ZipCodes,
field: "_id",
template: Template.userPill,
selector: function(match) {
var regex;
regex = new RegExp(match, 'i');
return {
$or: [
{
'_id': regex
}, {
'city': regex
}
]
};
},
}]
}
}
})
I know this answer is too late for you, but it can be helpful to somebody in the future. Just do this inside your server-side publish function.
Meteor.publish('ZipCodesPublication', function(selector, options) {
let limitTo = Math.abs(options.limit) > 50 ? 50 : options.limit,
defaultSelector = selector._id,
regEx = defaultSelector.$regex,
regExOptions = defaultSelector.$options,
customSeletor = {
$or: [
{
city: {
$regex: regEx,
$options: regExOptions
}
},
{
_id: {
$regex: regEx,
$options: regExOptions
}
}
]
};
Autocomplete.publishCursor(Clients.find(customSeletor), this);
this.ready();
});
And just do this on the client:
Template.search.helpers({
settings : function () {
return {
position: "bottom",
limit: 20,
rules: [{
collection: 'ZipCodes',
subscription: 'ZipCodesPublication',
field: "_id",
template: Template.userPill
}]
}
}

Resources