Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Building Hosted Fields

jeffcarp
October 08, 2015

Building Hosted Fields

A lightning talk given at Node学園18 in Tokyo on October 8, 2015.

This talk is about what the JS SDK team at Braintree learned when building the new Hosted Fields integration.

jeffcarp

October 08, 2015
Tweet

More Decks by jeffcarp

Other Decks in Programming

Transcript

  1. Braintree helps companies like Uber, Airbnb, GitHub, and Dropbox accept

    credit cards, PayPal, Venmo, Bitcoin, Apple Pay, and Android Pay
  2. 2015 - PCI DSS VERSION 3 Credit card information must

    now be entered on the domain of your payment provider
  3. HOSTED FIELDS: A NEW INTEGRATION FOR MATCHING THE STYLE OF

    YOUR CHECKOUT FORM AND BEING PCI COMPLIANT
  4. We decided that the only way to give merchants the

    most customizability was to make each input an iframe
  5. STYLING CONSIDERATIONS > Guard against XSS > Minimal change to

    existing CSS workflow > Easy and intuitive
  6. INFER STYLES FROM CONATINER > ! No extra work for

    the merchant > " Requires watching for updates > " Black box to the merchant
  7. applyIf styles: [ { // base styles color: 'green', fontFamily:

    'Helvetica' }, { // setting styles for focused elements applyIf: function(inputElement) { return inputElement.isFocused; }, color: 'limegreen' }, { // media queries applyIf: function() { return window.innerWidth > 600; }, fontSize: '16pt' } ]
  8. applyIf > ! Not constrained to CSS rules > !

    Anything you can write in JS works > ! Supports media queries > " Not intuitive > " Requires inter-frame communication for every CSS change
  9. CSS IN A SCRIPT TAG <script type="braintree/css"> input { font-size:

    16pt; color: #ccc; } </script> > ! Intuitive > " Requires parsing CSS in JS
  10. stylesheet.insertRule > ! Close to CSS syntax > ! Supports

    media queries > ! Makes XSS more difficult { 'input': { 'font-size': '16pt' } }
  11. INNER STYLES: FOR THE TEXT braintree.setup('client-token', 'custom', { hostedFields: {

    styles: { 'input': { 'font-size': '16pt' }, ':focus': { 'color': '#ddd' } } } });
  12. WE EVALUATED USING TYPESCRIPT function sum(a: number, b: number): number

    { return a + b; } > Easy if your entire project is TypeScript > Must write type declarations for all plain JS
  13. WE ALSO EVALUATED USING BABEL FOR ES6 > Vanilla JS™

    on the merchant page > Babel/ES6 inside iframes
  14. WE ALSO EVALUATED JEST > Front-end testing framework from Facebook

    > Based on jsdom (JS implementation of the DOM) > Auto-mocks everything by default const API = require('api'); console.log(API); // => {}
  15. EVENT LIFECYCLE hostedFields: { onFieldEvent: function (event) { if (event.type

    === "focus") { // Handle focus } else if (event.type === "blur") { // Handle blur } else if (event.type === "fieldStateChange") { // Handle a change in validation or card type console.log(event.isValid); // true|false if (event.card) { console.log(event.card.type); // visa|master-card|american-express|diners-club|discover|jcb|unionpay|maestro } } } }
  16. VALIDATING AS YOU TYPE 3 => {isValid: false, isPotentiallyValid: true,

    type: null} 37 => {isValid: false, isPotentiallyValid: true, type: 'Amex'} 373 => {isValid: false, isPotentiallyValid: true, type: 'Amex'} 3736 => {isValid: false, isPotentiallyValid: false, type: null} 4111111111111111 => {isValid: true, isPotentiallyValid: true, type: 'Visa'}
  17. FRAMEBUS <iframe> <script> bus.on('message', function (data) { console.log(data); // =>

    '͜Μʹͪ͸'; }); </script> </iframe> <iframe> <script> bus.emit('message', '͜Μʹͪ͸'); </script> </iframe>
  18. TEAM DYNAMICS > 4 programmers (2 pairs) > Pair programming

    100% of the time > Rotate pairs every few days