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实例,按如下方案调整:
- 将Braintree的script标签移到
app/index.html中 - 调整后的组件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
相关产品推荐
相关产品推荐

