paypal not redirecting to the paypal site but inks are getting in the response in Meteor - meteor

I am new to Meteor and integrating Paypal(Which i never had done).
from Client side in meteor -
I am calling method on button click.
<MDBBtn onClick={(e) => callPaypal(e)} color="primary" type="submit">
Add and Continue to PayPal
</MDBBtn>
And this callpaypal() method ->
import { Link as ReactRouterLink } from 'react-router-dom'
const callPaypal = (e) => {
e.preventDefault();
Meteor.call('createPayalPayment', (err, res) => {
console.log(res[1].href) **FIRST CONSOLE**
if (res) {
let link = res[1];
if (link.href) {
return <ReactRouterLink to={`${link.href}`} />
}
}
})
}
Calling createPayalPayment method from server ->
import { Config } from "./paypal_config";
createPayalPayment() {
var data = {
"intent": "sale",
"payer": {
"payment_method": "paypal"
},
"redirect_urls": {
// "return_url": `${Meteor.absoluteUrl('/execute'), { "replaceLocalhost": "true" }}`,
"return_url": "http://127.0.0.1:3000/execute",
"cancel_url": "http://172.20.10.5:3000/cancel"
},
"transactions": [{
"amount": {
"currency": "USD",
"total": "1.00"
},
"description": "This is the payment description."
}]
};
paypal.configure(Config);
var ppCreate = Meteor.wrapAsync(paypal.payment.create.bind(paypal.payment));
var ppExecute = Meteor.wrapAsync(paypal.payment.execute.bind(paypal.payment));
var response = ppCreate(data);
if (response.state !== 'created') {
console.log('not created!!!!!!!!!!!!!!!!')
}
else {
console.log(response); **SECOND CONSOLE**
return response.links;
}
}
And here is my Paypal config ->
export const Config = {
'mode': 'sandbox',
'client_id': 'client_Id',
'client_secret': 'secret'
};
FIRST CONSOLE --> 'https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=EC-1HR12649X9688931M'
SECOND CONSOLE -->>
{ id: 'PAYID-L2IJO4I8GE24787GF168351L',
intent: 'sale',
state: 'created',
payer: { payment_method: 'paypal' },
transactions:
[ { amount: [Object],
description: 'This is the payment description.',
related_resources: [] } ],
create_time: '2020-04-10T15:57:37Z',
links:
[ { href: 'https://api.sandbox.paypal.com/v1/payments/payment/PAYID-L2IJO4I8GE24787GF168351L',
rel: 'self',
method: 'GET' },
{ href: 'https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=EC-1HR12649X9688931M',
rel: 'approval_url',
method: 'REDIRECT' },
{ href: 'https://api.sandbox.paypal.com/v1/payments/payment/PAYID-L2IJO4I8GE24787GF168351L/execute',
rel: 'execute',
method: 'POST' } ],
httpStatusCode: 201
}
As the links[2].href is the URL, where the paypal should be redirect here and user can login to the account. But It is not redirecting. So I am manually redirecting to this link in callPaypal() method just below the First console.
But Still the router is unable to redirect to the link maybe Outer Domain Issue or whatever even it's not showing error.
Please Is there any way that the paypal redirect itself to paypal login? I have already wasted my 2 days on this and still have nothing.
Thanks.
I added the Redirect URL in my paypal developer account for this project.

It looks like you're using an old, redirect-based PayPal integration, so my recommendation is trying the new in-context experience: https://developer.paypal.com/demo/checkout/#/pattern/server
Notice the two fetch calls to '/demo/..' placeholders, which would need to be replaced with actual routes on your server. The first should return a PayID (or newer v2/orders ID), and the second should execute/capture that ID.
This integration is superior because your site stays loaded in the background, and the buyer is able to checkout and pay without 'leaving' it.
On the server side, it looks like you may be using the old deprecated v1 PayPal-node-SDK, which there is no reason to do for a new integration. Instead, use the v2 Checkout-NodeJS-SDK

Related

Getting Cannot execute "delete" on "Article" in CASL JS

I'm learning CASL JS and trying to delete an article with a condition but getting this error Cannot execute "delete" on "Article". Here is the CodeSandBox Link.
Here is the sample code:
const { createMongoAbility, ForbiddenError } = require("#casl/ability");
const rules = [
{
action: "read",
subject: "Article"
},
{
inverted: true,
action: "delete",
subject: "Article",
conditions: { published: true },
reason: "You are not allowed to delete this article"
}
];
const ability = createMongoAbility(rules);
// this can be pulled from a database
class Article {
constructor(attrs) {
Object.assign(this, attrs);
}
}
const anotherArticle = new Article({
authorId: 2,
published: false,
content: "Lorem Ipsum"
});
try {
// checking ability before taking some action
ForbiddenError.from(ability).throwUnlessCan("delete", anotherArticle);
} catch (error) {
console.log(error.message); // throwing `Cannot execute "delete" on "Article"`
}
Please help me out. Thanks
The creator of CASL JS has answered this:
you declared that it's not possible to delete published articles but you have never said that it's possible to delete articles at all. That's why you get the error
So this means that I already declared inverted permission and it's not possible to delete articles.

How to implement push notification in KaiOS app

I am trying to implement push notification in KaiOS app. I simply follow below links.
W3C Push API
Push API introduction
Service Worker Cookbook - Web Push Payload
After follow all links the push is working in browser but not in KaiOS app.
If anybody have any sample code or documents please share.
Any help will be appriciated.
1) First, add this permission in manifest.webapp
"permissions": {
"serviceWorker":{
"description": "required for handle push."
},
"push":{
"description": "New update push."
},
"desktop-notification": {
"description": "New content update notification for the user."
}
}
2) service worker file sw.js code
self.addEventListener('push', function(event) {
event.waitUntil(
self.registration.showNotification('My Push', {
body: 'Push Activated',
})
);
});
self.addEventListener('activate', e => {
self.clients.claim();
});
3) Add service worker on app start
registerSW : function() {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('./sw.js').then(function(reg) {
console.log('Service Worker Registered!', reg);
reg.pushManager.getSubscription().then(function(sub) {
if (sub === null) {
} else {
console.log('Subscription object: ', sub);
}
});
}).catch(function(e) {
console.log('SW reg failed');
});
}
}
4) Call service worker by any dom element like button
registerServiceWorker: function() {
Notification.requestPermission().then(function(permission) {
if (permission === 'granted') {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready.then(function(reg) {
reg.pushManager.subscribe({
userVisibleOnly: true
}).then(function(sub) {
console.log('Endpoint URL: ', sub.endpoint);
}).catch(function(e) {
if (Notification.permission === 'denied') {
console.warn('Permission for notifications was denied');
} else {
console.error('Unable to subscribe to push', e);
}
});
})
}
}
});
}
That's it.
I had same problem as this, but I followed this simple web push notification method,
https://medium.com/#seladir/how-to-implement-web-push-notifications-in-your-node-react-app-9bed79b53f34
as well as I fixed that issue and now It work properly. please don't forget to add permissions like below into the manifest.webapp file.
"permissions": {
"serviceworker": {
"description": "Needed for assocating service worker"
},
"desktop-notification": {
"description": "Needed for creating system notifications."
},
"notifications": {},
"push": {
"description": "Required for being updated with new goals in soccer matches"
},
"geolocation": {
"description": "Marking out user location"
},
"alarms": {
"description": "Scheduling alarms"
}
},
and as well as please refer this kaios documention for run the applicaion on kaios device.
https://developer.kaiostech.com/getting-started/build-your-first-hosted-app/pwa-to-hosted-app

Meteor live update doesn't work as expected

When I make changes to the database that affect UserProfiles, the client side is updated. For instance, if I change a weekday from true to false the UserProfile will appear or disappear on my computer screen. However, when I make a change to Attendances, for instance, create a new attendance record which should make a UserProfile appear nothing happens unless I reload the page. I assume it's to do with studnentUserIds not being rerun.
How do I make Meteor notice these changes?
This is being built using Meteor, React and mongoDB.
Meteor.publish('teacher.AdminDashboardContainer.userProfiles', function getStudentUserProfiles(rollCallDate) {
if (this.userId) {
const start = new Date(moment(rollCallDate).startOf('day').toISOString());
const end = new Date(moment(rollCallDate).endOf('day').toISOString());
const weekday = `student.days.${moment(rollCallDate).format('dddd').toLowerCase()}`;
const studentUserIds = Attendances.find({
$and: [
{ createdAt: { $gte: start, $lt: end } },
],
}).map(attendance => attendance.studentUserProfileId);
return UserProfiles.find({
$or: [
{ _id: { $in: studentUserIds } },
{
$and: [
{ [weekday]: true },
],
},
],
}),
}
// user not authorized. do not publish secrets
this.stop();
return false;
});
How about using publish-composite? It handles the "reactivity" part on its own.
https://github.com/englue/meteor-publish-composite

Google Analytics Reporting API v4 missing required authentication credential

I'm new to using this API, and I am struggling with retrieving my data using Google Analytics Reporting API v4. I am only attempting to retrieve the analytics for a website so I can build a dashboard. I am following the example here: Hello Analytics Reporting API v4; JavaScript quick start for web applications
I am able to make a request, however, I keep getting a 400 error that is might be this: 400: Invalid Credentials
`Invalid JSON payload received. Unknown name "express" at 'report_requests[0].metrics[0]': Cannot find field.
handleError # Test.js:64
h.o0 # cb=gapi.loaded_0:53
xs # cb=gapi.loaded_0:56
Wq # cb=gapi.loaded_0:56
_.C.uea # cb=gapi.loaded_0:55
Ap # cb=gapi.loaded_0:49`
I have no idea what I am doing wrong, and I am hoping someone can point me in the right direction.
This is a react application. I am making the request after the component mounts.
import React, { Component } from 'react';
import GoogleLogin from 'react-google-login';
import $ from 'jquery';
const VIEW_ID = '17414592';
const CLIENT_ID = "936270024581-stgn130l17v21s6vjch9p751hiqbovac.apps.googleusercontent.com";
const DISC_DOCS = 'https://analyticsreporting.googleapis.com/$discovery/rest?version=v4';
export default class Test extends Component {
constructor(props) {
super(props)
this.printResults = this.printResults.bind(this);
this.handleRequest = this.handleRequest.bind(this);
this.handleError = this.handleError.bind(this);
}
//when component mounts, create a google sign in button.
componentDidMount() {
//load gapi
$.getScript("https://apis.google.com/js/client:platform.js")
.done(() => {
window.gapi.signin2.render('my-signin2', {
'scope': 'profile email',
'width': 240,
'height': 50,
'longtitle': true,
'theme': 'dark',
'onsuccess': this.handleRequest,
'onfailure': this.handleError
});
})
}
//on success, make a request to get google analytics data
handleRequest() {
window.gapi.client.request({
path: '/v4/reports:batchGet',
root: 'https://analyticsreporting.googleapis.com',
method: 'POST',
body: {
reportRequests: [
{
viewId: VIEW_ID,
dateRanges: [{
startDate: '7daysAgo',
endDate: 'today'
}],
metrics: [{ express: 'ga:sessions' }]
}
]
}
}).then(this.printResults, this.handleError)
}
//log the data
printResults(response) {
console.log(response)
}
//or the error if there is one
handleError(reason) {
console.error(reason)
console.error(reason.result.error.message);
}
//render it all
render() {
return (
<div>
<div id="my-signin2"></div>
</div>
)
}
}
What am I doing wrong? How can I properly do a batchRequest to retrieve all data from 7 days using Google Analytics Reporting APIv4? I feel as though I am using all required fields, however, I do not know what I am missing. Can you point me in the right direction?
I'm answering my own question in case anyone else needs help using google analytics reporting api v4 with react. This is what I needed to do in order to construct a gapi button that would then make a basic request. The error I was creating was from a typo. Instead of metrics:[{expression: 'ga:sessions'}] I was using metrics:[{express: 'ga:sessions'}].
Here is a component that will create a simple request. Please note you have to change the VIEW_ID to your value.
import React, { Component } from 'react';
import $ from 'jquery';
const VIEW_ID = '17414592';
export default class Test extends Component {
constructor(props) {
super(props)
this.printResults = this.printResults.bind(this);
this.handleRequest = this.handleRequest.bind(this);
this.handleError = this.handleError.bind(this);
}
//when component mounts, create a google sign in button.
componentDidMount() {
//load gapi
$.getScript("https://apis.google.com/js/client:platform.js")
.done(() => {
window.gapi.signin2.render('my-signin2', {
'scope': 'profile email',
'width': 240,
'height': 50,
'longtitle': true,
'theme': 'dark',
'onsuccess': this.handleRequest,
'onfailure': this.handleError
});
})
}
//on success, make a request to get google analytics data
handleRequest() {
window.gapi.client.request({
path: '/v4/reports:batchGet',
root: 'https://analyticsreporting.googleapis.com',
method: 'POST',
body: {
reportRequests: [
{
viewId: VIEW_ID,
dateRanges: [{
startDate: '7daysAgo',
endDate: 'today'
}],
metrics: [{ expression: 'ga:sessions' }]
}
]
}
}).then(this.printResults, this.handleError)
}
//log the data
printResults(response) {
console.log(response)
}
//or the error if there is one
handleError(reason) {
console.error(reason)
console.error(reason.result.error.message);
}
//render it all
render() {
return (
<div>
<div id="my-signin2"></div>
</div>
)
}
}
401: Invalid Credentials Invalid authorization header. The access
token you're using is either expired or invalid.
This basically means that you need to sign in again.
Click the Sign in button, and authorize access to Google Analytics.
Remember access tokens are only valid for an hour your going to have to sign it in again when ever it expires.

In Meteor when trying to access an attribute, I get TypeError: Cannot read property in the console. But the site is working

When trying to read an attribute, meteor gives me a TypeError: Cannot read property 'featuredImage' of undefined error in the browser console. But it reads featuredImage and the site is working fine. How can I get rid of this error? Is it happening because my subscriptions are not yet ready? Is that's the case, how to fix it? (PS : Im using the flow router so I can't wait for subscriptions in the router)
My template code :
Template.About.helpers({
page: () => {
return findPage();
},
featuredImage: () => {
var thisPage = findPage();
return Images.findOne({
"_id": thisPage.featuredImage
});
}
});
function findPage() {
return Pages.findOne({
slug: 'about'
});
}
The router code :
FlowRouter.route('/about', {
name: 'about',
subscriptions: function() {
this.register('page', Meteor.subscribe('pages', 'about'));
this.register('image', Meteor.subscribe('images'));
},
action() {
BlazeLayout.render('MainLayout', {
content: 'About'
});
setTitle('About Us');
},
fastRender: true
});
The subscription is probably not ready yet. FlowRouter provides a utility for dealing with this, your helpers should look like this:
Template.About.helpers({
page: () => {
// If you only need a specific subscription to be ready
return FlowRouter.subsReady('page') && findPage() || null;
},
featuredImage: () => {
// Ensure ALL subscriptions are ready
if ( FlowRouter.subsReady() ) {
var thisPage = findPage();
return Images.findOne({
"_id": thisPage.featuredImage // Probably should be thisPage.featuredImage._id
});
}
return null;
}
});
However, for maximum performance, you should use if (FlowRouter.subsReady('page') && Flowrouter.subsReady('image')) rather than FlowRouter.subsReady() since if you have other pending subscriptions which are large, it will wait for those even though you don't need them.

Resources