You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ember 3.25集成Braintree Hosted Fields时client为undefined如何解决

Ember框架集成Braintree Hosted Fields报错解决方案

目前Ember与Braintree Hosted Fields的适配效果不佳,Braintree官方支持团队也暂未找到该问题的根因方案。页面表单渲染时会触发创建client的动作,但返回的client为undefined。
报错信息:
picture-this-44ac48bef9f8df633632a4d202da2379.js:57 Uncaught TypeError: Cannot read property 'client' of undefined


原配置与代码

组件hbs代码

<script src="https://js.braintreegateway.com/web/3.81.0/js/client.min.js"></script>
<script src="https://js.braintreegateway.com/web/3.81.0/js/hosted-fields.min.js"></script>
<div class="demo-frame" {{did-insert this.setupBraintreeHostedFields}}>
  <form action="/" method="post" id="cardForm" >
    <label class="hosted-fields--label" for="card-number">卡号</label>
    <div id="card-number" class="hosted-field"></div>
    <label class="hosted-fields--label" for="expiration-date">有效期</label>
    <div id="expiration-date" class="hosted-field"></div>
    <label class="hosted-fields--label" for="cvv">CVV</label>
    <div id="cvv" class="hosted-field"></div>
    <label class="hosted-fields--label" for="postal-code">邮政编码</label>
    <div id="postal-code" class="hosted-field"></div>
    <div class="button-container">
      <input type="submit" class="button button--small button--green" value="购买" id="submit"/>
    </div>
  </form>
</div>

组件类代码

import Component from '@glimmer/component';
import { action } from '@ember/object';
import { inject as service } from '@ember/service';
import { tracked } from '@glimmer/tracking';
import { braintree } from 'braintree-web';

export default class CardPaymentComponent extends Component {

  @action
  setupBraintreeHostedFields() {

    alert('booh');
    var form = document.querySelector('#cardForm');
    var authorization = 'sandbox_24nzd6x7_gyvpsk2myght4c2p';

    braintree.client.create({
      authorization: authorization
    }, function(err, clientInstance) {
      if (err) {
        console.error(err);
        return;
      }
      createHostedFields(clientInstance);
    });

    function createHostedFields(clientInstance) {
      braintree.hostedFields.create({
        client: clientInstance,
        styles: {
          'input': {
            'font-size': '16px',
            'font-family': 'courier, monospace',
            'font-weight': 'lighter',
            'color': '#ccc'
          },
          ':focus': {
            'color': 'black'
          },
          '.valid': {
            'color': '#8bdda8'
          }
        },
        fields: {
          number: {
            selector: '#card-number',
            placeholder: '4111 1111 1111 1111'
          },
          cvv: {
            selector: '#cvv',
            placeholder: '123'
          },
          expirationDate: {
            selector: '#expiration-date',
            placeholder: 'MM/YYYY'
          },
          postalCode: {
            selector: '#postal-code',
            placeholder: '11111'
          }
        }
      }, function (err, hostedFieldsInstance) {
        var tokenize = function (event) {
          event.preventDefault();

          hostedFieldsInstance.tokenize(function (err, payload) {
            if (err) {
              alert('操作出现问题,请检查您的卡信息后重试。');
              return;
            }

            alert('在此处将nonce (' + payload.nonce + ') 提交到您的服务器!');
          });
        };

        form.addEventListener('submit', tokenize, false);
      });
    }

  }

}

package.json配置

...
"ember-cli": "^3.25.2",
"braintree-web": "^3.81.0",
...

最终解决方案

无需安装NPM包braintree-web。问题根因是Ember组件类无法直接访问挂载在Window对象上的Braintree实例,按如下方案调整:

  1. 将Braintree的script标签移到app/index.html中
  2. 调整后的组件hbs代码如下:
<article class="rental">
  <form action="/" method="post" id="cardForm">
    <label class="hosted-fields--label" for="card-holder-name">持卡人姓名</label>
    <div id="card-holder-name" class="hosted-field payment"></div>
    <label class="hosted-fields--label" for="email">邮箱</label>
    <div id="email" class="hosted-field payment"></div>
    <label class="hosted-fields--label" for="card-number">卡号</label>
    <div id="card-number" class="hosted-field payment"></div>
    <label class="hosted-fields--label" for="expiration-date">有效期</label>
    <div id="expiration-date" class="hosted-field payment"></div>
    <label class="hosted-fields--label" for="cvv">CVV</label>
    <div id="cvv" class="hosted-field payment"></div>
    <label class="hosted-fields--label" for="postal-code">邮政编码</label>
    <div id="postal-code" class="hosted-field payment"></div>
    <div class="button-container">
      <input type="submit" class="button" value="购买" id="submit"/>
    </div>
  </form>
</article>

<script>
var form = document.querySelector('#cardForm');
var authorization = 'sandbox_24nzd6x7_gyvpsk2myght4c2p';

braintree.client.create({
  authorization: authorization
}, function(err, clientInstance) {
  if (err) {
    console.error(err);
    return;
  }
  createHostedFields(clientInstance);
});

function createHostedFields(clientInstance) {
  braintree.hostedFields.create({
    client: clientInstance,
    styles: {
      'input': {
        'font-size': '1.2em',
        'font-family': 'courier, monospace',
        'font-weight': 'lighter',
        'color': '#ccc'
      },
      ':focus': {
        'color': 'black'
      },
      '.valid': {
        'color': '#8bdda8'
      }
    },
    fields: {
      number: {
        selector: '#card-number',
        placeholder: '4111 1111 1111 1111'
      },
      cvv: {
        selector: '#cvv',
        placeholder: '123'
      },
      expirationDate: {
        selector: '#expiration-date',
        placeholder: 'MM/YYYY'
      },
      postalCode: {
        selector: '#postal-code',
        placeholder: '11111'
      }
    }
  }, function (err, hostedFieldsInstance) {
    var tokenize = function (event) {
      event.preventDefault();

      hostedFieldsInstance.tokenize(function (err, payload) {
        if (err) {
          alert('操作出现问题,请检查您的卡信息后重试。');
          return;
        }

        alert('在此处将nonce (' + payload.nonce + ') 提交到您的服务器!');
      });
    };

    form.addEventListener('submit', tokenize, false);
  });
}
</script>

内容的提问来源于stack exchange,提问作者Conor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 10:51:04