UNPKG

@rebilly/framepay-react

Version:

A React wrapper for Rebilly's FramePay offering out-of-the-box support for Redux and other common React features

488 lines (472 loc) 21.9 kB
import React, { Component } from 'react'; import { FramePayProvider, withFramePay } from '../../../build'; import { deepMerge, prettyDebugRender, ReactVersion, renderFixture, } from './util'; import './style.css'; const params = { publishableKey: 'pk_sandbox_S95ATjj4hXZs-T9QpZq1ENl2tDSrUkCGv98utc9', organizationId: '5977150c-1c97-4dd4-9860-6bb2bab070b4', websiteId: 'demo.com', transactionData: { amount: 10, currency: 'USD', label: 'Purchase label 1', }, }; const defaultEvents = () => ({ card: { onReady: false, onChange: false, onFocus: false, onBlur: false, }, bankAccountType: { onReady: false, onChange: false, onFocus: false, onBlur: false, }, bankAccountNumber: { onReady: false, onChange: false, onFocus: false, onBlur: false, }, bankRoutingNumber: { onReady: false, onChange: false, onFocus: false, onBlur: false, }, iban: { onReady: false, onChange: false, onFocus: false, onBlur: false, }, }); class PaymentFormComponent extends Component { constructor(props) { super(props); this.state = { paymentElements: { // {element: method} card: 'payment-card', bank: 'ach', iban: 'ach', googlepay: 'googlepay', applepay: 'applepay', samsungpay: 'samsungpay', }, paymentElement: 'card', billingAddress: { firstName: 'first-name-value', lastName: 'last-name-value', country: 'GB', }, }; this.handleSubmit = this.handleSubmit.bind(this); } handleSubmit(e) { e.preventDefault(); /** * * @see https://www.rebilly.com/docs/dev-docs/framepay-global-reference/#framepay.createtoken * */ const billingAddress = { ...this.state.billingAddress, }; this.props.Framepay.createToken(this.formNode, { // method: this.state.paymentElements[this.state.paymentElement], billingAddress, }) .then((data) => { this.props.onEvent({ token: { error: false, data: { ...data, method: data.method }, }, }); }) .catch((err) => { this.props.onEvent({ token: { error: true, data: err } }); }); } render() { const elements = Object.keys(this.state.paymentElements); const changeElement = (element) => { this.setState({ paymentElement: element, }); // Clear events this.props.onEvent({ events: { ...defaultEvents(), }, }); }; return ( <div className="example-2"> <ul> {elements.map((element) => ( <li key={`payment-method-${element}`}> <button id={`set-active-element-${element}`} onClick={() => changeElement(element)} > {element} - isActive: {String(element === this.state.paymentElement)} </button> </li> ))} </ul> <form id="form" ref={(node) => (this.formNode = node)} method="post" onSubmit={this.handleSubmit} > <fieldset> <div className="field"> <input type="text" name="firstName" placeholder="First Name" defaultValue={ this.state.billingAddress.firstName } onChange={(e) => { this.props.onEvent({ billingAddress: { firstName: e.target.value, }, }); }} /> </div> <div className="field"> <input type="text" name="lastName" placeholder="Last Name" defaultValue={ this.state.billingAddress.lastName } onChange={(e) => { this.props.onEvent({ billingAddress: { lastName: e.target.value, }, }); }} /> </div> <hr /> <div className="field" id="field-CardElement"> {this.state.paymentElement === 'card' && ( <this.props.CardElement onReady={() => this.props.onEvent({ events: { card: { onReady: true }, }, }) } onChange={(data) => this.props.onEvent({ events: { card: { onChange: { ...data, error: data.error || '', }, }, }, }) } onFocus={() => this.props.onEvent({ events: { card: { onFocus: true }, }, }) } onBlur={() => this.props.onEvent({ events: { card: { onBlur: true }, }, }) } /> )} {this.state.paymentElement === 'googlepay' && ( <this.props.GooglePayElement /> )} {this.state.paymentElement === 'samsungpay' && ( <this.props.SamsungPayElement /> )} {this.state.paymentElement === 'applepay' && ( <this.props.ApplePayElement /> )} {this.state.paymentElement === 'bank' && ( <div> <div className="field" id="field-BankAccountTypeElement" > <label>Account Type</label> <this.props.BankAccountTypeElement onReady={() => this.props.onEvent({ events: { bankAccountType: { onReady: true, }, }, }) } onChange={(data) => this.props.onEvent({ events: { bankAccountType: { onChange: { ...data, error: data.error || '', }, }, }, }) } onFocus={() => this.props.onEvent({ events: { bankAccountType: { onFocus: true, }, }, }) } onBlur={() => this.props.onEvent({ events: { bankAccountType: { onBlur: true, }, }, }) } /> </div> <div className="field" id="field-BankRoutingNumberElement" > <label>Routing Number</label> <this.props.BankRoutingNumberElement onReady={() => this.props.onEvent({ events: { bankRoutingNumber: { onReady: true, }, }, }) } onChange={(data) => this.props.onEvent({ events: { bankRoutingNumber: { onChange: { ...data, error: data.error || '', }, }, }, }) } onFocus={() => this.props.onEvent({ events: { bankRoutingNumber: { onFocus: true, }, }, }) } onBlur={() => this.props.onEvent({ events: { bankRoutingNumber: { onBlur: true, }, }, }) } /> </div> <div className="field" id="field-BankAccountNumberElement" > <label>Account Number</label> <this.props.BankAccountNumberElement onReady={() => this.props.onEvent({ events: { bankAccountNumber: { onReady: true, }, }, }) } onChange={(data) => this.props.onEvent({ events: { bankAccountNumber: { onChange: { ...data, error: data.error || '', }, }, }, }) } onFocus={() => this.props.onEvent({ events: { bankAccountNumber: { onFocus: true, }, }, }) } onBlur={() => this.props.onEvent({ events: { bankAccountNumber: { onBlur: true, }, }, }) } /> </div> </div> )} {this.state.paymentElement === 'iban' && ( <div> <div className="field" id="field-IBANElement" > <label>IBAN NUmber</label> <this.props.IBANElement onReady={() => this.props.onEvent({ events: { iban: { onReady: true, }, }, }) } onChange={(data) => this.props.onEvent({ events: { iban: { onChange: { ...data, error: data.error || '', }, }, }, }) } onFocus={() => this.props.onEvent({ events: { iban: { onFocus: true, }, }, }) } onBlur={() => this.props.onEvent({ events: { iban: { onBlur: true, }, }, }) } /> </div> </div> )} </div> </fieldset> <hr /> <button id="submit">Make Payment</button> </form> </div> ); } } const PaymentForm = withFramePay(PaymentFormComponent); class App extends Component { constructor(props) { super(props); this.state = { events: { ...defaultEvents(), }, token: { error: null, data: null, }, }; } deepUpdateState(data) { this.setState((prevState) => { return deepMerge(prevState, data); }); } render() { return ( <FramePayProvider {...params} onTokenReady={(token) => this.deepUpdateState({ error: false, data: token }) } > <div> {ReactVersion()} <div> <div className="flex-wrapper"> {prettyDebugRender(this.state)} <PaymentForm onEvent={(data) => this.deepUpdateState(data)} /> </div> </div> </div> </FramePayProvider> ); } } renderFixture(<App />);