如何使用 Vue.js 类组件设置 PayPal 智能按钮

Posted

技术标签:

【中文标题】如何使用 Vue.js 类组件设置 PayPal 智能按钮【英文标题】:How to set up PayPal Smart Buttons with Vue.js class components 【发布时间】:2021-09-30 04:38:13 【问题描述】:

我正在尝试将 PayPal 按钮添加到现有的结帐页面。但是,我遇到了很多麻烦,因为我们的项目使用了 Vue.js 类组件,而我遇到的示例却没有(PayPal 官方文档不使用类组件:https://developer.paypal.com/docs/business/checkout/configure-payments/single-page-app/)。

我遇到了使用mounted()钩子将PayPal SDK脚本注入DOM的解决方法,并且我已经成功地使按钮出现,但是我无法付款的问题动态细节(总金额、商品描述等订单信息存储在 Vue 组件的状态中,我还没有找到将状态传递给 DOM 中的静态 JS 脚本的方法)。

我目前正在尝试调整 PayPal 官方文档以使用类组件,我的代码如下(去掉了与 PayPal 无关的部分):

索引.html

<!DOCTYPE html>
<html class="no-js" lang="en" dir="ltr">
    <head>
        <script defer src="https://www.paypal.com/sdk/js?client-id=abc123&disable-funding=credit,card"></script>
    </head>
    <body>
        <div id="app">
        <!-- The shop component is put inside here -->
        </div>
    </body>
</html>

shop.vue:

<template>
    <paypal-buttons :on-approve="onApprove" :create-order="createOrder" />
</template>
<script lang="ts" src="./shop.component.ts"></script>

shop.component.ts:

const PayPalButton = paypal.Buttons.driver("vue", window.Vue);

@Component(
  components: 
    PayPalButton,
  ,
)
export default class Shop extends Vue 

  public total = '10.0'; // Will be dynamic

  public mounted(): void 
    ...
  

  public createOrder(data, actions) 
    return actions.order.create(
        purchase_units : [
            amount: 
              value: total
            
        ]
    );
  
  public onApprove(data, actions) 
    return actions.order.capture().then(function (details) 
        console.log(details)
    )
  

此代码将成功构建,但由于出现错误,我无法实际打开页面。在浏览器控制台中,我看到以下错误:

TypeError: 无法读取未定义的属性“组件”

经过进一步调试,我发现paypal.Buttons.driver("vue", window.Vue); 行导致错误,这是因为paypal 未定义。我相当确定 index.html 中的 PayPal 脚本已正确加载,而且我也不认为这是由于缺少 npm 包或导入。我在网上找到的少数资源之一是:Vue PayPal implementation with vue-head, paypal not defined

不幸的是,这个链接的解决方案使用了mounted() 钩子,这是我之前尝试过的,它不能解决提供我想要的动态总数的问题。

有人有使用 PayPal SDK 和 Vue.js 类组件的经验吗?任何帮助将不胜感激!

【问题讨论】:

【参考方案1】:

经过更多测试,我得出了这个结论:显然,即使您使用mounted() 钩子将 SDK 脚本注入DOM。事实证明,当我第一次尝试这样做时,我对 Vue 类组件的理解存在缺陷,因此错误地引用了组件状态。

在我的最终代码中,我从 index.html 中取出了 PayPal SDK &lt;script&gt; 标签。我的其他 2 个文件中的代码修改如下:

shop.vue:

<template>
    <div id="paypal-button"></div>
</template>
<script lang="ts" src="./shop.component.ts"></script>

shop.component.ts:

export default class Shop extends Vue 

  public total = '10.0'; // Will be dynamic

  public mounted(): void 
    const script = document.createElement('script');
    const clientId = 'abc123';
    script.src = `https://www.paypal.com/sdk/js?client-id=$clientId&disable-funding=credit,card`;
    script.addEventListener('load', this.paypalSetLoaded);
    document.body.appendChild(script);
  

  public paypalSetLoaded() 
    window.paypal
      .Buttons(
        style: 
          color: 'blue',
          shape: 'pill',
        ,
        createOrder: this.paypalCreateOrder,
        onApprove: this.paypalOnApprove,
      )
      .render('#paypal-button');
  

  public paypalCreateOrder(data, actions) 
    return actions.order.create(
      purchase_units: [
        amount: 
          currency_code: 'USD',
          value: this.total,
        
      ],
    );
  

  public paypalOnApprove(data, actions) 
    return actions.order.capture().then(details => 
      console.log(details);
    );
  

即使total 的值在程序执行期间发生变化(由于用户交互),正确金额的订单将始终发送到 PayPal。

我不确定这是否是最佳实践,但代码有效,并且根据我的预见,既高效又可扩展。希望这可以帮助遇到类似问题的其他人?

【讨论】:

以上是关于如何使用 Vue.js 类组件设置 PayPal 智能按钮的主要内容,如果未能解决你的问题,请参考以下文章

如何将 vue.js 中的子组件设置为“默认”

如何使用 Vue.js 类设置计时器

如何使用 Vue js 中的 paypal/stripe 等付款方式收费?我需要像express这样的服务器吗?

Vue.js 过渡类在动画完成之前消失

如何将 TypeScript 与 Vue.js 和单文件组件一起使用?

如何使用 vue js 制作固定导航栏?