In-Context Checkout: Uncaught SecurityError: Blocked a frame with origin: checkout.js:4734 throws error - reactjs

I'm implementing PayPal's In-Context Checkout and am using Advanced In-Context JavaScript settings (https://developer.paypal.com/docs/classic/express-checkout/in-context/javascript_advanced_settings)
My app is a React app. So I can't use PP API as they suggest it, that is just throw a code between <script> ... </script> tags somewhere in the page under their buttons. My React components have state and data that I need to send to server within PP function calls. So I placed PP code in componentDidMount method. And for some reason PP throws this error:
checkout.js:4734 Uncaught SecurityError: Blocked a frame with origin "http://example.com:3000" from accessing a frame with origin "https://www.sandbox.paypal.com". The frame requesting access has a protocol of "http", the frame being accessed has a protocol of "https". Protocols must match.
(anonymous function) # checkout.js:4734
checkout.js:4515 GET http://www.paypalobjects.com/api/oneTouch.html net::ERR_EMPTY_RESPONSE
Here is the code:
componentDidMount() {
window.paypalCheckoutReady = function() {
paypal.checkout.setup(config[NODE_ENV].ppMerchantID, {
locale: 'en_US',
environment: 'sandbox',
buttons: [
{
container: 'checkoutBtnContainer',
type: 'checkout',
color: 'gold',
size: 'medium',
shape: 'pill',
click: (ev)=>{
paypal.checkout.initXO();
$.post('/checkout', {
checkoutData: this.props.checkoutData,
})
.done(res => {
paypal.checkout.startFlow(res.link);
})
.fail(err => {
paypal.checkout.closeFlow();
});
}
}
],
});
};
},
I know about cross-origin policy. I don't understand why it is the case here. Why the code works fine if I throw it on the page between <script> ... </script> tags, but PP throws an error if I use it in my React component. What is the cause of that? Is it React fault or PayPal's?

UPD: No, below is not a solution for the problem. Occasionally Paypal's checkout.js script throws the error.
However, it solves this issue
Apparently,
1) there was no this:
window.paypalCheckoutReady = function() {
// wrong this is here
}
I changed to:
window.paypalCheckoutReady = () => {
// correct this is here now
}
I don't like .bind(this).
2) I removed <form /> tag and set plain <div> instead:
// before
<form id="checkoutBtnContainer" method="post" action="/checkout"></form>
// after
<div id="checkoutBtnContainer"></div>
I don't know why and how, but all works fine now.

Related

Fetching a github repo in react gives a "Module "stream" has been externalized for browser compatibility and cannot be accessed in client code" error

I am currently stuck with a problem trying to fetch github repo data using the octokit npm package.
I use vite to run a dev server and when I try to make a request, the error that i get is:
Uncaught Error: Module "stream" has been externalized for browser compatibility and cannot be accessed in client code.
My React .tsx file looks like this:
import { Octokit, App } from 'octokit'
import React from 'react'
const key = import.meta.env.GITHUB_KEY
const octokit = new Octokit({
auth: key
})
await octokit.request('GET /repos/{owner}/{repo}', {
owner: 'OWNER',
repo: 'REPO'
})
export default function Repos() {
return (
<>
</>
)
}
I have redacted the information for privacy purposes.
If anyone knows how to resolve this issue with vite, please let me know!
Check first if this is similar to octokit/octokit.js issue 2126
I worked around this problem by aliasing node-fetch to isomorphic-fetch. No idea if it works for all usages within octokit, but works fine for my project.
You'll need to install the isomorphic-fetch dependency before making this config change.
// svelte.config.js
const config = { // ... kit: {
// ...
vite: {
resolve: {
alias: {
'node-fetch': 'isomorphic-fetch',
},
},
},
},
};
export default config;
Note: there are still questions about the support/development of octokit: issue 620.

Error with URL in NextJS and I can't find the problem

I have an error that appear in both development and production mode, however, this error only crash the website in production.
I have this error returned:
unhandledRejection: TypeError: Only absolute URLs are supported
at getNodeRequestOptions (D:\FIV\nextjs-fiv-4\node_modules\node-fetch\lib\index.js:1305:9)
at D:\FIV\nextjs-fiv-4\node_modules\node-fetch\lib\index.js:1410:19
at new Promise (<anonymous>)
at Function.fetch [as default] (D:\FIV\nextjs-fiv-4\node_modules\node-fetch\lib\index.js:1407:9)
at fetchWithAgent (D:\FIV\nextjs-fiv-4\node_modules\next\dist\server\node-polyfill-fetch.js:38:39)
at _callee$ (D:\FIV\nextjs-fiv-4\node_modules\swell-js\dist\api.js:191:20)
at tryCatch (D:\FIV\nextjs-fiv-4\node_modules\regenerator-runtime\runtime.js:63:40)
at Generator.invoke [as _invoke] (D:\FIV\nextjs-fiv-4\node_modules\regenerator-runtime\runtime.js:294:22)
at Generator.next (D:\FIV\nextjs-fiv-4\node_modules\regenerator-runtime\runtime.js:119:21)
at asyncGeneratorStep (D:\FIV\nextjs-fiv-4\node_modules\swell-js\node_modules\#babel\runtime\helpers\asyncToGenerator.js:3:24)
And I know that this is the element below causing this error, when I remove it, the error disappears. But I do not understand how to correct it, or what's wrong when checking the network tab. In the network tab I see that this is calling http://localhost:3000/null/api/cart instead of https://my-store.swell.store/api/cart which is weird because on other page this URL is called correctly and I use an .env file to set my environment variables.
//Render Stripe Card Element
var customCardElement = swell.payment.createElements({
card: {
elementId: '#card-element', // default: #card-element
options: {
style: {
base: {
fontWeight: 500,
fontSize: "16px"
},
},
},
onChange: event => {
//setDisabled(event.empty);
if(event.error){
//setError(event.error.message);
}
}
}
});
Client side NextJS variables are only available if prefixed with NEXT_PUBLIC_ because well... they're public

webview_flutter javascript channel can't communicate in release mode

I am using webview_flutter with version 3.0.0 in my app. I have heavy usage of two-way communication between flutter and javascript. Everything works on debug mode nicely. But, after I build the APK started to get some errors in the javascript channel. I tried with flutter run --release and got the same error.
In my web application (ReactJs), I am using channels in this way:
index.html
<div id="root">
<script>
function sendToFlutter(message) {
if (flutterChannel) {
flutterChannel.postMessage(message);
}
}
</script>
</div>
calling is from React component like this:
window.sendToFlutter("hello-world");
My Webview setup from Flutter end:
Completer<WebViewController> webViewCompleter = Completer<WebViewController>();
WebView(
debuggingEnabled: false,
initialUrl: "https://example.com",
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
webViewCompleter.complete(webViewController);
},
javascriptChannels: <JavascriptChannel>{
JavascriptChannel(
name: "flutterChannel",
onMessageReceived: (JavascriptMessage message) {
if (message.message == "hello-world") {
// Do something
}
})
},
navigationDelegate: (NavigationRequest request) {
if (request.url.startsWith('https://www.youtube.com/')) {
return NavigationDecision.prevent;
}
return NavigationDecision.navigate;
},
gestureNavigationEnabled: true,
zoomEnabled: false,
userAgent: Platform.isAndroid ? kAndroidUserAgent : kIosUserAgent,
);
When I call the channel from ReactJs, then I am getting this error:
TypeError: flutterChannel.postMessage is not a function
According to alexbatalov's research in https://github.com/flutter/flutter/issues/92548, the current workaround is to do the following:
Create android/app/proguard-rules.pro. At minimum you need to have a
rule for JavascriptInterface, but I recommend to copy entire
proguard-android.txt, given the fact that you don’t have these rules.
# Preserve annotated Javascript interface methods.
-keepclassmembers class * {
#android.webkit.JavascriptInterface <methods>;
}

Window.OneSignal showing 404 error when i am trying to use it with next.js

I am trying to implement OneSignal web push notifications with the next.js web app. I followed this article
to implement it. But it is not implementing properly as it shows an error. I have doubt that where should I place the window.OnseSignal code shown in step 7.
What I did?
I built a component name NewOneSignal instead of pasting it in App.js (because there is no App.js file in next.js) whose code is given below:
import React, { useEffect } from "react";
const NewOneSignal=()=>{
useEffect(()=>{
window.OneSignal = window.OneSignal || [];
const OneSignal = window.OneSignal;
},[]);
return (
OneSignal.push(()=> {
OneSignal.init(
{
appId: "i pasted my app id here", //STEP 9
promptOptions: {
slidedown: {
enabled: true,
actionMessage: "We'd like to show you notifications for the latest Jobs and updates about the following categories.",
acceptButtonText: "OMG YEEEEESS!",
cancelButtonText: "NAHHH",
categories: {
tags: [
{
tag: "governmentJobs",
label: "Government Jobs",
},
{
tag: "PrivateJobs",
label: "Private Jobs",
}
]
}
}
},
welcomeNotification: {
"title": "The website",
"message": "Thanks for subscribing!",
}
},
//Automatically subscribe to the new_app_version tag
OneSignal.sendTag("new_app_version", "new_app_version", tagsSent => {
// Callback called when tag has finished sending
console.log('new_app_version TAG SENT', tagsSent);
})
);
})
)
}
export default NewOneSignal;
And imported this component in the document.js file. According to this article, I have to put step 8 code in the useEffect but didn't work also, I have tried that also
I am very much sure that the problem is in this file. I paste the OneSignalsdk script in head section of the _document.js file.Also, i moved the two service worker files in a public folder as shown in the article. Please help me to make this code work

I get "Invalid Plugin Options" Error with Prismic Plugin in Gatsby

I'm using CodeSandbox to make a Gatsby app and I'm trying to use Prismic for the backend. I set it up nicely, I'm sure, and I installed gatsby-source-prismic to my project. However, when I add it to my config file and restart the project, it throws an error saying "Invalid Plugin Options". This is what's in my plugin file:
{
resolve: `gatsby-source-prismic`,
options: {
repositoryName: `firstprism`,
accessToken: `XXX`
},
},
Here's the stack:
ERROR
gatsby-source-prismic - invalid plugin options
ERROR
Expected a value of type record<string,object> forschemas but received undefined.
Error:
index.cjs:650 new StructError
[sandbox]/[superstruct]/lib/index.cjs:650:19
index.cjs:707 Function.Struct.assert
[sandbox]/[superstruct]/lib/index.cjs:707:13
index.cjs:679 Struct
[sandbox]/[superstruct]/lib/index.cjs:679:19
gatsby-node.js:74 validatePluginOptions
[sandbox]/[gatsby-source-prismic]/dist/gatsby-node.js:74:50
gatsby-node.js:1042
[sandbox]/[gatsby-source-prismic]/dist/gatsby-node.js:1042:25
Generator.next
gatsby-node.js:52
[sandbox]/[gatsby-source-prismic]/dist/gatsby-node.js:52:71
new Promise
gatsby-node.js:48 __awaiter
[sandbox]/[gatsby-source-prismic]/dist/gatsby-node.js:48:12
gatsby-node.js:1029 Object.sourceNodes
[sandbox]/[gatsby-source-prismic]/dist/gatsby-node.js:1029:55
api-runner-node.js:256 runAPI
[sandbox]/[gatsby]/dist/utils/api-runner-node.js:256:37
api-runner-node.js:375 resolve
[sandbox]/[gatsby]/dist/utils/api-runner-node.js:375:15
debuggability.js:384 Promise._execute
[sandbox]/[bluebird]/js/release/debuggability.js:384:9
promise.js:518 Promise._resolveFromExecutor
[sandbox]/[bluebird]/js/release/promise.js:518:18
promise.js:103 new Promise
[sandbox]/[bluebird]/js/release/promise.js:103:10
api-runner-node.js:374 Promise.mapSeries.plugin
[sandbox]/[gatsby]/dist/utils/api-runner-node.js:374:12
I just ran into this issue. It appears it is now required to provide JSON schemas, as described here in the docs : https://github.com/angeloashmore/gatsby-source-prismic#providing-json-schemas
edit: please also refer to https://github.com/angeloashmore/gatsby-source-prismic/blob/master/docs/migrating-from-v2-to-v3.md
It's like this
options: {
repositoryName: 'your-repository-name',
accessToken: `${process.env.API_KEY}`,
linkResolver: ({ node, key, value }) => post => `/${post.uid}`,
schemas: {
page: require("./src/schemas/page.json"),
},
},
instead of this now
options: {
repositoryName: `your-repository-name`,
accessToken: `${process.env.API_KEY}`,
linkResolver: ({ node, key, value }) => post => `/${post.uid}`,
page: require("./src/schemas/page.json"),
},

Resources