前篇:Braintree-国外支付对接(二) 中的支付按钮的生成是braintree自带的样式和事件控制的,即drop-in,生成的界面我们不能过多的更改和控制。所以假如我们想要自己编写控件,自己控制样式,但又能正常点击触发支付等事件。那么就使用Customer UI.
使用Customer UI需要映入的官方JS有很大不同,但是我们的后端是不需要变的,因为提交的参数和返回的参数是一样的。下面给出的例子,没有过多的写的样式很漂亮华丽,简单点:
<div class="wrapper"><div class="checkout container"><header><h1>Hi,<br>Let's test a transaction</h1><p>Make a test payment with Braintree using PayPal or a card</p></header><form id="payment-form" method="post" action="/checkouts/Create"><section><label for="amount"><span class="input-label">Amount</span><div class="input-wrapper amount-wrapper"><input id="amount" name="amount" type="tel" min="0.01" placeholder="Amount" value="0.01"></div></label><fieldset><legend>Card</legend><div class="cardinfo-card-number"><label class="cardinfo-label" for="cc-number">Card Number</label><div class='input-wrapper' id="cc-number"></div><div id="card-image"></div></div><div class="cardinfo-card-number"><label class="cardinfo-label" for="cc-number">CVV</label><div class='input-wrapper' id="cc-cvv"></div></div><div class="cardinfo-card-number"><label class="cardinfo-label" for="cc-expiration-date">Expiration-Date</label><div class='input-wrapper' id="cc-expiration-date"></div></div> <button style="margin-top: 10px; background-color: pink;" class="button" id="card-button" type="button"><span style="padding: 0.7em 1em">Done</span></button></fieldset><fieldset><legend>Paypal</legend><button style="margin-top: 10px; background-color: pink;" class="button" disabled id="paypal-button" type="button"><span>Paypal</span></button><span id="payer"></span></fieldset></section><input id="nonce" name="payment_method_nonce" type="hidden" /><button class="button" type="submit"><span>Test Transaction</span></button></form></div>
</div><style>.cardinfo-card-number {position: relative;}.cardinfo-label {display: block;font-size: 11px;margin-bottom: 0.5em;text-transform: uppercase;
}.input-wrapper {border-radius: 2px;background: rgba(255, 255, 255, 0.86);height: 2.75em;border: 1px solid #eee;-webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.06);box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.06);padding: 5px 10px;margin-bottom: 1em;
}#card-image{position: absolute;top: 36px;right: 0px;width: 44px;height: 28px;background-image: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/346994/card_sprite.png);background-size: 86px 458px;border-radius: 4px;background-position: -100px 0;background-repeat: no-repeat;margin-bottom: 1em;}#card-image.visa{background-position: 0 -398px;}#card-image.master-card{background-position: 0 -281px;}#card-image.american-express{background-position: 0 -370px;}#card-image.discover{background-position: 0 -163px;}#card-image.maestro{background-position: 0 -251px;}#card-image.jcb{background-position: 0 -221px;}#card-image.diners-club{background-position: 0 -133px;}
</style>
<script src="\App_Themes\javascript\vendor\jquery-2.1.4.min.js"></script><script src="https://js.braintreegateway.com/web/3.29.0/js/client.min.js"></script>
<script src="https://js.braintreegateway.com/web/3.29.0/js/hosted-fields.min.js"></script>
<script src="https://js.braintreegateway.com/web/3.29.0/js/paypal.js"></script>
<script src="https://js.braintreegateway.com/web/3.29.0/js/paypal-checkout.js"></script>
<script src="https://js.braintreegateway.com/web/3.29.0/js/three-d-secure.js"></script><script>$(function () {var client_token = '@ViewBag.ClientToken';var paypalButton = document.querySelector('#paypal-button');var cardButton = document.querySelector('#card-button');braintree.client.create({authorization: client_token }, function (clientErr, clientInstance) { //****if (clientErr) {//console.error('Error creating client:', clientErr);return;}//paypal支付braintree.paypal.create({client: clientInstance //****}, function (paypalErr, paypalInstance) {if (paypalErr) {console.error('Error creating PayPal:', paypalErr);return;}paypalButton.removeAttribute('disabled');paypalButton.addEventListener('click', function (event) {// Because tokenization opens a popup, this has to be called as a result of// customer action, like clicking a button. You cannot call this at any time.paypalInstance.tokenize({flow: 'checkout',amount: document.querySelector('#amount').value,currency: 'USD'// For more tokenization options, see the full PayPal tokenization documentation// http://braintree.github.io/braintree-web/current/PayPal.html#tokenize}, function (tokenizeErr, payload) {if (tokenizeErr) {if (tokenizeErr.type !== 'CUSTOMER') {console.log('Error tokenizing:', tokenizeErr);}return;}// Tokenization succeededdocument.querySelector('#nonce').value = payload.nonce;$("#payer").html(payload.details.email);paypalButton.firstChild.innerHTML = "switch account";console.log('Paypal Got nonce:', payload.nonce);});}, false);});///信用卡支付// Create input fields and add text styles braintree.hostedFields.create({client: clientInstance, //****// Add information for individual fieldsfields: {number: {selector: '#cc-number',placeholder: '1111 1111 1111 1111'},cvv: {selector: '#cc-cvv',placeholder: '123'},expirationDate: {selector: '#cc-expiration-date',placeholder: '10 / 2019'}}}, function (err, hostedFieldsInstance) {if (err) {console.log(err);return;}hostedFieldsInstance.on('cardTypeChange', function (event) {// Change card bg depending on card typeif (event.cards.length === 1) {//$(form).removeClass().addClass(event.cards[0].type);$('#card-image').removeClass().addClass(event.cards[0].type);//$('header').addClass('header-slide');// Change the CVV length for AmericanExpress cardsif (event.cards[0].code.size === 4) {hostedFieldsInstance.setAttribute({field: 'cvv',attribute: 'placeholder',value: '1234'});}} else {hostedFieldsInstance.setAttribute({field: 'cvv',attribute: 'placeholder',value: '123'});}});cardButton.addEventListener('click', function (event) {event.preventDefault();hostedFieldsInstance.tokenize(function (err, payload) {if (err) {console.log(err);return;}var a = payload.details.cardType;var b = payload.details.lastFour;//document.querySelector('#nonce').value = payload.nonce;// This is where you would submit payload.nonce to your servervar my3DSContainer;braintree.threeDSecure.create({client: clientInstance}, function (threeDSecureErr, threeDSecure) {if (threeDSecureErr) {console.log("Error creating 3DSecure" + threeDSecureErr);return;}else{threeDSecure.verifyCard({nonce: payload.nonce,amount: document.querySelector('#amount').value,addFrame: function (err, iframe) {// Set up your UI and add the iframe.my3DSContainer = document.createElement('div');my3DSContainer.appendChild(iframe);document.body.appendChild(my3DSContainer);},removeFrame: function () {//Remove UI that you added in addFrame.document.body.removeChild(my3DSContainer);}}, function (err, thpayload) {if (err) {console.log(err);return;}//hostedFieldsInstance.clear('number');//hostedFieldsInstance.clear('cvv');//hostedFieldsInstance.clear('expirationDate');debugger;if (thpayload.liabilityShiftPossible) {if (thpayload.liabilityShifted) {//Liablity has shifted//submitNonceToServer(payload.nonce);document.querySelector('#nonce').value = thpayload.nonce;console.log('Card Got nonce:', thpayload.nonce);} else {console.log("Invalid Card!");}} else {document.querySelector('#nonce').value = thpayload.nonce;console.log('No3D nonce:', thpayload.nonce);}});}});});}, false);});});});
</script>
界面效果:
paypal和信用卡的初始化方法是不一样的,信用卡的稍微复杂点。它们所依赖的js也是不一样的。
这里要注意,所有引入的braintree官方的js的版本必须要一致,原因嘛,你去改下版本试下就知道了。版本不一致的话,paypal支付或者信用卡支付的时候官方会返回错误给我们,提示就是必须引入的client.min.js版本和paypal-checkout.js或者其他的js要一致。你用到哪种支付的时候,就会提示你要与哪种支付所依赖的js版本要一致。
- client.min.js
这是第一个要引入的,客户端支付控件初始化,其他支付方式的初始化都是依赖于braintree.client.create()返回的clientInstance作为参数去初始化的。代码中注释了*的地方。
2. hosted-fields.min.js
这是将信用卡支付中的输入框控件(卡号,CVV等)标记为信用卡支付时校验的字段,标记了之后我们就拿不到其客户真正输入的值,且一切相应的判断(比如卡号,CVV的正确性,必填性)这些就都不需要我们自己来控制。其外最重要的,不可让商城拿到客户的卡信息这是为了保护客户的财产泄露,引发商家的承担不必要的责任。入正式的时候需要进行PCI安全验证,这点上就很能让你通过了。
3. paypal-checkout.js
这是paypal支付需要的,braintree.paypal.create()。这个很简单的。
4.three-d-secure.js
3D安全校验需要的,这个东西启用的主要原因就是 为支付减少风险。也为商家转移责任。
参考资料:
https://developers.braintreepayments.com/guides/hosted-fields/examples/javascript/v3