generateCreditCardFormHTML static method

String generateCreditCardFormHTML(
  1. String vaultId,
  2. String environment, {
  3. List<PayEngineField>? additionalFields,
  4. String source = 'native ',
})

Implementation

static String generateCreditCardFormHTML(String vaultId, String environment,
    {List<PayEngineField>? additionalFields, String source = 'native '}) {
  return '''
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
  <title>Credit Card Form</title>
  <script type="text/javascript" src="https://js.verygoodvault.com/vgs-collect/2.16.0/vgs-collect.js"></script>

  <style>
    html, body {
      margin: 0;
      padding: 0;
      background: transparent;
    }
    .row {
      display: flex;
      gap: 10px;
    }
    .col {
      flex: 1;
    }
    .form-group {
      margin-bottom: 10px;
    }
    .form-field {
      display: block;
      width: 100%;
      height: 50px;
    }

    .form-field iframe {
      border: 0 none transparent;
      height: 100%;
      vertical-align: middle;
      width: 100%;
    }
  </style>
</head>
<body>
  <form id="cc-form">
    <div class="form-group">
      <span id="card_holder" class="form-field">
      </span>
    </div>
    <div class="form-group">
      <span id="card_number" class="form-field"></span>
    </div>
    <div class="row">
      <div class="form-group col">
        <span id="card_exp" class="form-field"></span>
      </div>
      <div class="form-group col">
        <span id="card_cvc" class="form-field"></span>
      </div>
    </div>
    ${additionalFields?.map((field) => '<div class="form-group"><span id="${field.name}" class="form-field"></span></div>').join('') ?? ''}
  </form>

  <script>
    const css = {
      color: '#000',
      border: '#CCC 1px solid',
      'border-radius': '5px',
      'text-transform': 'uppercase',
      padding: '5px 10px',
      'box-sizing': 'border-box',
      'font-size': '1em',
      'caret-color': 'transparent',
      '&:focus': {
        'border-color': '#999',
      },
      '&.invalid.touched': {
        'border-color': 'red',
      },
      '&.valid': {
        'border-color': '#CCC',
      },
    }
    const form = VGSCollect.create('$vaultId', '$environment', function(state) {});

    form.field('#card_holder', {
      type: 'text',
      name: 'card_holder',
      placeholder: 'Card holder name',
      validations: ['required'],
      css
    });

    const cardElement = form.field('#card_number', {
      type: 'card-number',
      name: 'card_number',
      placeholder: 'Card number',
      validations: ['required', 'validCardNumber'],
      showCardIcon: true,
      css
    });

    const cvcElement = form.field('#card_cvc', {
      type: 'card-security-code',
      name: 'card_cvc',
      placeholder: 'CVC',
      validations: ['required', 'validCardSecurityCode'],
      showCardIcon: true,
      css
    });

    cardElement.setCVCDependency(cvcElement);

    form.field('#card_exp', {
      type: 'card-expiration-date',
      name: 'card_exp',
      placeholder: 'Exp date',
      validations: ['required', 'validCardExpirationDate'],
      css
    });

    ${additionalFields?.map((field) => '''
    form.field('#${field.name}', {
      type: 'text',
      name: '${field.name}',
      placeholder: '${field.placeholder}',

      validations: [${field.isRequired ? "'required', " : ""}${field.pattern != null ? "'/${field.pattern!.replaceAll('\\', r'\\')}/'" : ""}],
      css
    });
''').join('') ?? ''}

    const sendNative = (data, isError) => {
      ${source == 'native' ? 'PE' : 'window.parent'}.postMessage(JSON.stringify({
        type: 'PayEngineResponse',
        data: {
          STATUS: isError ? 'FAILED' : 'SUCCESS',
          DATA: data
        }
      }))
    }

    function submit(merchantId, authHeader) {
      form.submit('/api/cards', {
        method: 'POST',
        data: {
          brand: form.state.card_number.cardType,
          last_4: form.state.card_number.last4,
          bin: form.state.card_number.bin,
          pci_vault_provider: 'vgs',
          merchant_id: merchantId,
        },
        headers: {
          Authorization: authHeader
        }
      }, (status, data) => {
        if (status === 200) {
          sendNative(data, false)
        } else {
          sendNative({ data, status }, true)
        }
      }, error => {
        sendNative(error, true)
      })
      return true
    }

    window.addEventListener('message', message => {
      try {
        const json = JSON.parse(message.data);
        if (json.source === 'PEFlutter') {
          console.log({ json });
          if (json.action === 'submit') {
            submit(json.data.merchantId, json.data.authHeader);
          }
        }
      } catch {}
    })
  </script>
</body>
</html>
''';
}