React 中的 PayPal 捐赠按钮:捐赠 SDK 或 Checkout SDK 集成?

发布于 2025-01-17 04:31:26 字数 1459 浏览 1 评论 0 原文

官方 NPM 包 @paypal/react-paypal-js: https:// www.npmjs.com/package/@paypal/react-paypal-js 仅支持需要 client_id 的按钮,我还没有找到任何可以简化“捐赠”按钮实现的内容。 PayPal 在“捐赠”按钮文档中仅提供以下 HTML 代码。如果有人有类似的经历,请告诉我,以及你是如何在 React/Gatsby 中正确实现它的。

<head>
 <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Ensures optimal rendering on mobile devices. -->
 <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <!-- Optimal Internet Explorer compatibility -->
</head>

<body>
 <script src="https://www.paypalobjects.com/donate/sdk/donate-sdk.js" charset="UTF-8"></script>
</body>

<body>
 <div id="paypal-donate-button-container"></div>

  <script>
   PayPal.Donation.Button({
       env: 'sandbox',
       hosted_button_id: 'YOUR_SANDBOX_HOSTED_BUTTON_ID',
       // business: 'YOUR_EMAIL_OR_PAYERID',
       image: {
           src: 'https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif',
           title: 'PayPal - The safer, easier way to pay online!',
           alt: 'Donate with PayPal button'
       },
       onComplete: function (params) {
           // Your onComplete handler
       },
   }).render('#paypal-donate-button-container');
</script>
</body>

The official NPM package @paypal/react-paypal-js: https://www.npmjs.com/package/@paypal/react-paypal-js only supports buttons that require client_id, I have not been able to find anything that simplifies the implementation of Donate button. PayPal provides only this HTML code below on the Donate button documentation. Please let me know if anyone has had a similar experience and how did you manage to implement it properly in React/Gatsby.

<head>
 <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Ensures optimal rendering on mobile devices. -->
 <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <!-- Optimal Internet Explorer compatibility -->
</head>

<body>
 <script src="https://www.paypalobjects.com/donate/sdk/donate-sdk.js" charset="UTF-8"></script>
</body>

<body>
 <div id="paypal-donate-button-container"></div>

  <script>
   PayPal.Donation.Button({
       env: 'sandbox',
       hosted_button_id: 'YOUR_SANDBOX_HOSTED_BUTTON_ID',
       // business: 'YOUR_EMAIL_OR_PAYERID',
       image: {
           src: 'https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif',
           title: 'PayPal - The safer, easier way to pay online!',
           alt: 'Donate with PayPal button'
       },
       onComplete: function (params) {
           // Your onComplete handler
       },
   }).render('#paypal-donate-button-container');
</script>
</body>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

吃不饱 2025-01-24 04:31:26

有两种方法可以使用 React 中的捐赠 SDK HTML/JS。

  1. 将应用配置为在页面加载时加载 SDK 脚本(通常作为页面 的一部分)。然后,渲染按钮的 JS 可以作为组件的一部分运行/输出,并使用 window.paypal 访问 SDK。

  2. 将脚本元素插入 DOM 页面加载后以及加载后带有回调函数的渲染按钮。这些都可以放在 React 组件的 useEffect 或类似组件中。使用 loadAsync 的链接示例适用于 Checkout SDK,但可以轻松替换为 Donate SDK 代码。


您可以将捐赠 SDK 与您提到的 hosted_button_id 结合使用(在 https:// www.paypal.com/buttons(实时)或www.sandbox.paypal.com/buttons) - 或者,也可以不使用托管按钮 ID,只需传递 business 参数以及接收帐户的 PayPal 电子邮件地址或 (理想情况下)其PayPal Merchant ID(因为它永远不会改变,而电子邮件可以被删除)从帐户中,不再指向它)


稍后编辑:请注意,捐赠 SDK 与简单地使用文本“捐赠”重新标记普通 PayPal Checkout SDK 按钮是分开的,这可以完成 根据react-paypal-js故事书示例,正如提到的另一个答案。这种方法的问题是,点击按钮后,它看起来像一个标准的 PayPal 结帐,而不是特定于捐赠的流程...

使用实际的 Donate SDK 会产生更定制的捐赠流程,他们可以在其中选择大笔金额中的任何金额输入,甚至检查一个选项以使其经常捐款:

There are two ways to use the Donate SDK HTML/JS from react.

  1. Configure the app to load the SDK script at page load time (typically as part of the page's <head>). The JS to render the button can then be run/outputted whenever as part of a component and access the SDK using window.paypal.

  2. Insert the script element into the DOM after page load and once loaded render buttons with a callback function. This can all be placed in a React component's useEffect or similar. The linked example using loadAsync is for the Checkout SDK, but that's easily swapped out for Donate SDK code.


You can use the Donate SDK with a hosted_button_id as you mentioned (created at https://www.paypal.com/buttons (live) or www.sandbox.paypal.com/buttons) -- or alternatively, instead of a hosted button id just pass a business parameter with either the receiving account's PayPal email address or (ideally) its PayPal Merchant ID (since that will never change whereas an email can be removed from the account and no longer point to it)


Later edit: Note that the Donate SDK is separate from simply relabeling a normal PayPal Checkout SDK button with the text "Donate", which can be done per the react-paypal-js storybook example, as another answer mentioned. The issue with this approach is after clicking the button it will look like a standard PayPal checkout, not a donation-specific flow...

Using the actual Donate SDK instead results in a more tailored donor flow where they can select any amount in the large input, and even check an option to make their donation recurring:

空城旧梦 2025-01-24 04:31:26

我联系了 React SDK 团队,他们说它实际上支持开箱即用的捐赠,并且 他们的故事书。这是相关代码。如果您使用此方法,则不需要 hosted_button_id

<PayPalButtons
  fundingSource="paypal"
  style={{
    layout: "vertical",
    label: "donate"
  }}
  createOrder={(data, actions) => {
    return actions.order
      .create({
        purchase_units: [{
            amount: {
              value: "2",
              currency_code: "USD",
            },
            items: [{
                name: "donation-example",
                quantity: "1",
                unit_amount: {
                  currency_code: "USD",
                  value: "2",
                },
                category: "DONATION",
            }],
        }],
      })
  }}
/>;

I reached out to the React SDK team and they said it actually comes with support for donate out of the box and there is an example in their storybook. Here's the relevant code. If you use this approach you shouldn't need hosted_button_id:

<PayPalButtons
  fundingSource="paypal"
  style={{
    layout: "vertical",
    label: "donate"
  }}
  createOrder={(data, actions) => {
    return actions.order
      .create({
        purchase_units: [{
            amount: {
              value: "2",
              currency_code: "USD",
            },
            items: [{
                name: "donation-example",
                quantity: "1",
                unit_amount: {
                  currency_code: "USD",
                  value: "2",
                },
                category: "DONATION",
            }],
        }],
      })
  }}
/>;
柠檬色的秋千 2025-01-24 04:31:26

我遇到了同样的问题,并且由于参考错误,我没有看到此处接受的答案如何与React一起使用:< code>PayPal.Donation.Button 未定义,如果我尝试将其用作函数,代码将无法编译。

我研究了将整个脚本标记作为字符串附加(dangerouslySetInnerHTML),并发现这篇博客文章是一个很好的解释:使用 React 渲染危险内容。 作者非常酷地使用了 document.Range API 以解决里面执行脚本的问题html。他还将他的解决方案作为一个小包发布: dangerously-set-html-content .

我在我的 Gatsby 项目中尝试过。首先,我在 gatsby-srr.js 的主体上添加 Donate SDK 脚本标记,以便在页面加载时获取 JapaScript:(

exports.onRenderBody = ({setPreBodyComponents}) => {
    setPreBodyComponents(
        <script key={0} src="https://www.paypalobjects.com/donate/sdk/donate-sdk.js" charSet="UTF-8"/>
    )
}

我需要看起来怪异的 key 属性以避免在合并 html.js 时出现错误,该属性将被删除)

然后在组件中我将脚本设置为字符串:

import React from 'react'
import InnerHTML from 'dangerously-set-html-content'
const html = `
    <div id="donate-button-container">
        <div id="donate-button">
            <script>
                PayPal.Donation.Button({
                    ...
                }}).render('#donate-button')
            </script>
        </div>
    </div>
`
function MyComponent() {
    return (
       <InnerHTML html={html} />
    )
}

您可以查看 GitHub 存储库,用于解释如何使用 useEffectuseRef 挂钩,以及一些使用示例。

I had the same problem and I didn't see how exactly the accepted answer here could work with React because of the reference error: PayPal.Donation.Button is undefined, and the code wouldn't compile if I tried using it as a function.

I looked into appending the whole script tag as a string (dangerouslySetInnerHTML) and found this blog post to be a great explanation: Render dangerous content with React. The author makes a pretty cool use of document.Range API in order to solve the problem of executing scripts inside html. He has also published his solution as a small package: dangerously-set-html-content.

I gave it a try in my Gatsby project. First thing I'm adding the Donate SDK script tag on the body in gatsby-srr.js in order to fetch the JapaScript on page load:

exports.onRenderBody = ({setPreBodyComponents}) => {
    setPreBodyComponents(
        <script key={0} src="https://www.paypalobjects.com/donate/sdk/donate-sdk.js" charSet="UTF-8"/>
    )
}

(I need the bizarre-looking key attribute to avoid errors when html.js is compiled. Once it's merged, the attribute is removed)

And then in the component I'm setting the script as a string:

import React from 'react'
import InnerHTML from 'dangerously-set-html-content'
const html = `
    <div id="donate-button-container">
        <div id="donate-button">
            <script>
                PayPal.Donation.Button({
                    ...
                }}).render('#donate-button')
            </script>
        </div>
    </div>
`
function MyComponent() {
    return (
       <InnerHTML html={html} />
    )
}

You can have a look at the GitHub repo of the package for the explanation of how useEffect and useRef hooks are used, and for some usage examples.

薄暮涼年 2025-01-24 04:31:26

在 NextJS 中,我在 _document.js 中执行了此操作(删除了不相关的行)

export default function Document() {
  return (
    <Html lang="en">
      <Head>
        <script src="https://www.paypalobjects.com/donate/sdk/donate-sdk.js" defer/>
      </Head>
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  );
}
  1. 我想要按钮的组件:
import { useEffect, useState } from "react";
export default function Donate() {
  const [doPaypal, setDoPaypal] = useState(false);
  useEffect(() => {
    setDoPaypal(true);
  }, []);
  return (
    <>
      {
        doPaypal && 
        <div id="donate-button-container">
        <div id="donate-button"></div>
          <Script id="donate-button-script">
            {`
            PayPal.Donation.Button({
              env:'production',
              hosted_button_id:'${process.env.NEXT_PUBLIC_PAYPAL_HOSTED_BUTTON_ID}',
              image: {
                src:'https://whatever/paypal-donate.png',
                alt:'Donate with PayPal button', 
                title:'PayPal - The safer, easier way to pay online!',
              }
            }).render('#donate-button');
          `}
        </Script>
        </div>
      }
    </>
  );
}

类似的方法将在 vanilla React 中工作,但这里的问题是 NextJS 提供了

In NextJS I did this (irrelevant lines removed)

  1. in _document.js:
export default function Document() {
  return (
    <Html lang="en">
      <Head>
        <script src="https://www.paypalobjects.com/donate/sdk/donate-sdk.js" defer/>
      </Head>
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  );
}
  1. component where I wanted the button:
import { useEffect, useState } from "react";
export default function Donate() {
  const [doPaypal, setDoPaypal] = useState(false);
  useEffect(() => {
    setDoPaypal(true);
  }, []);
  return (
    <>
      {
        doPaypal && 
        <div id="donate-button-container">
        <div id="donate-button"></div>
          <Script id="donate-button-script">
            {`
            PayPal.Donation.Button({
              env:'production',
              hosted_button_id:'${process.env.NEXT_PUBLIC_PAYPAL_HOSTED_BUTTON_ID}',
              image: {
                src:'https://whatever/paypal-donate.png',
                alt:'Donate with PayPal button', 
                title:'PayPal - The safer, easier way to pay online!',
              }
            }).render('#donate-button');
          `}
        </Script>
        </div>
      }
    </>
  );
}

A similar approach will work in vanilla React, but the thing here is that NextJS provides the <Script> component which is ideal rather than using dangerouslySetInnerHTML(). Also note the use of the environment to store your PayPal button ID; this must be a visible on the client-side hence using the NEXT_PUBLIC_ prefix.

瘫痪情歌 2025-01-24 04:31:26

同样在这里!因此,我在不通过 SDK 的情况下复制了按钮的代码,调整了按钮外观,并添加了 target="_blank" 以使 paypal 表单出现在新窗口中:

import "./paypalDonate.css";

const PaypalDonate = () => {
  return (
    <form action="https://www.paypal.com/donate" method="post" target="_blank">
      <input type="hidden" name="business" value="BUTTON-KEY" />
      <input type="hidden" name="no_recurring" value="0" />
      <input
        type="hidden"
        name="item_name"
        value="The organization cause should be written here."
      />
      <input type="hidden" name="currency_code" value="USD" />
      <input
        type="submit"
        border="0"
        name="submit"
        title="PayPal - The safer, easier way to pay online!"
        className="paypal-donate-btn"
        value="Donate"
      />
      <img
        alt=""
        border="0"
        src="https://www.paypal.com/en_US/i/scr/pixel.gif"
        width="1"
        height="1"
      />
    </form>
  );
};

export default PaypalDonate;

Same here! So, I copied the code for the button without going through the SDK, tweaked the button appearance, and added target="_blank" to make the paypal form appear in a new window:

import "./paypalDonate.css";

const PaypalDonate = () => {
  return (
    <form action="https://www.paypal.com/donate" method="post" target="_blank">
      <input type="hidden" name="business" value="BUTTON-KEY" />
      <input type="hidden" name="no_recurring" value="0" />
      <input
        type="hidden"
        name="item_name"
        value="The organization cause should be written here."
      />
      <input type="hidden" name="currency_code" value="USD" />
      <input
        type="submit"
        border="0"
        name="submit"
        title="PayPal - The safer, easier way to pay online!"
        className="paypal-donate-btn"
        value="Donate"
      />
      <img
        alt=""
        border="0"
        src="https://www.paypal.com/en_US/i/scr/pixel.gif"
        width="1"
        height="1"
      />
    </form>
  );
};

export default PaypalDonate;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文