Skip to content

8. Bestimmte Lieferadressen ausschließen

tolja edited this page May 28, 2018 · 6 revisions

Für die folgenden Anweisungen dient die Datei payment_shippingAddress.html als Grundlage. Dazu den dortigen Code in die Datei payment_reject_shippingAddress.html kopieren.


Unterhalb der <h1>-Überschrift sollte wieder die Beschreibung der Seite ersetzt werden von

<p> Teil 2: Payment Request mit Lieferadresse </p>

auf:

<p> Teil 6: Payment Request mit abweichender Lieferadresse (USA)</p>

Wenn man beispielsweise ein bestimmtes Land als Lieferadresse ausschließen und nur an bestimmte Länder liefern will, nutzt man das shippingaddresschange-Event. Dies wird nachfolgend am Beispiel der USA demonstriert, indem nur noch in die Staaten geliefert wird.

Zunächst einmal muss die Variable paymentDetails wie folgt verändert werden:

var paymentDetails = {
        total: {
          label: 'Gesamtsumme',
          amount: {
            currency: 'EUR',
            value: '49.99'
          }
        },
        displayItems: [{
            label: 'Beispielprodukt',
            amount: {
              currency: 'EUR',
              value: '49.99'
            },
          },
          {
            label: 'Standardversand',
            amount: {
              currency: 'EUR',
              value: '0.00'
            },
          pending: true
          }

        ],
        shippingOptions: [{
            id: 'standard',
            label: 'Standardversand',
            amount: {
              currency: 'EUR',
              value: '0.00'
            }
          },
          {
            id: 'express',
            label: 'Expressversand',
            amount: {
              currency: 'EUR',
              value: '14.99'
            },
          },
        ],
      };

Eine Änderung ist das pending: true, welches dem Standardversand im Array displayItems hinzugefügt wurde. Eine weitere Änderung erfolgte im Array shippingOptions, wo ebenso beim Standardversand das selected: true entfernt wurde. Somit wird sichergestellt, dass beim Laden des PaymentRequest keine Adresse vorausgewählt wird, die z.B. nicht in den USA liegt.

Nun wird der EventListener für den Fall, dass sich die Lieferadresse ändert, definiert. Dieser ist quasi identisch mit dem EventListener für das shippingoptionchange-Event in Kapitel 3.

Dieser Code wird unter die Definition des PaymentRequest

var paymentRequest = new PaymentRequest(supportedPaymentMethods, paymentDetails, options);

gesetzt:

paymentRequest.addEventListener('shippingaddresschange', function(evt) {
        evt.updateWith(new Promise(function(resolve) {
          updateShippingDetails(paymentDetails, paymentRequest.shippingAddress, resolve);
        }));
      });

Wiederrum dadrunter folgt dann die Funktion updateShippingDetails().

Hier definieren wir zunächst die Variable shippingOption, da wir uns die Versandoption je nach Inhalt des Events (z.B. Adresse in den USA ausgewählt) zusammenbauen. Diese Versandoption wird vorausgewählt mit selected: true und ist nicht von weiteren Änderungen betroffen (pending: false).

Nun wird geschaut, ob bei der Lieferadresse die Vereinigten Staaten ausgewählt wurden. Wenn dem so ist, wird die Variable shippingOption mit den notwendigen Daten gefüllt und der neue Versandpreis berechnet. Danach werden alle bestehenden Versandoptionen im Array details.shippingOptions durch die gerade definierte Versandoption ersetzt und die Anzeige im PaymentRequest angepasst mit details.displayItems.splice(1, 1, shippingOption);.

Um nun Adressen außerhalb der USA auszuschließen, wird im else die Variable shippingOption auf pending: true gesetzt, außerdem ein Fehler angezeigt und alle Versandoptionen gelöscht. Dies sorgt dafür, dass der PaymentRequest nicht mehr durchführbar ist, da mindestens eine Versandoption immer gegeben sein muss.

function updateShippingDetails(details, shippingAddress, resolve) {

        let shippingOption = {
          id: '',
          label: '',
          amount: {
            currency: 'EUR',
            value: '0.00'
          },
          selected: true,
          pending: false,
        };
        if (shippingAddress.country === 'US') {
          shippingOption.id = 'unitedStatesStandardShipping';
          shippingOption.label = 'Versand in die USA';
          shippingOption.amount.value = '25.00';
          details.total.amount.value = '74.99';
          details.shippingOptions = [shippingOption];
          details.displayItems.splice(1, 1, shippingOption);
        } else {

          shippingOption.label = 'Versandoption';
          shippingOption.pending = true;
          details.total.amount.value = '49.99';
          details.error = 'Kein Versand an Adressen außerhalb der USA.';
          details.shippingOptions = undefined;

        }

        resolve(details);
      }

Um die zusätzlichen Versandkosten für die USA im UI abzubilden, muss in dem Div von produkt_bought das <p>-Element angepasst werden von

<p>Sie haben das Beispielprodukt erfolgreich für 49,99 € <span id="express_selected">(+ 14,99 € Expressversand)</span> gekauft.</p>

auf

<p>Sie haben das Beispielprodukt erfolgreich für 49,99 € (+ 25 € Versand in die USA)</span> gekauft.</p>

Um den PaymentRequest nun zu testen, muss als Land Vereinigte Staaten und dann ein Bundesstaat ausgewählt werden. Die restlichen Informationen können willkürlich eingegeben werden, da die Adresse nicht validiert wird.

Der komplette Code der payment_reject_shippingAddress.html:


<!doctype html>
<html>

<head>
  <meta charset="utf-8">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  <title>W3C Payment Request API Tutorial</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <style>
    * {
      margin: 0;
    }

    html {
      font-family: sans-serif;
      line-height: 1.4;
      padding: 2em;
    }

    body> :not(:first-child) {
      margin-top: 1.5em;
    }

    h1,
    h2 {
      line-height: 1.15;
    }

    #express_selected {
      display: none;
    }

    .produkt {
      max-width: 13em;
      padding: 1em;
      background: #fff;
    }

    .produkt> :not(:first-child) {
      margin-top: 0.85em;
    }

    .produkt_bought {
      padding: 1em;
      background: #fff;
    }

    .data_list {
      max-width: 100%;
    }

    .produkt_bought> :not(:first-child) {
      margin-top: 0.85em;
    }

    .produkt_bought {
      display: none;
    }

    .produkt_shadow {
      position: relative;
      -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
      box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
    }

    .produkt_shadow:after {
      content: "";
      position: absolute;
      z-index: -1;
      -webkit-box-shadow: 0 0 40px rgba(0, 0, 0, 0.8);
      box-shadow: 0 0 40px rgba(0, 0, 0, 0.8);
      bottom: 0px;
      left: 10%;
      right: 10%;
      width: 80%;
      height: 50%;
      -moz-border-radius: 100%;
      border-radius: 100%;
    }

    .produkt_meta {
      display: flex;
      align-items: center;
      justify-content: space-between;
    }

    .produkt_button {
      background-color: #008CBA;
      color: #fff;
      padding: 0.25em 1em;
      text-decoration: none;
    }

    ul.nav {
    margin:0;
    padding:0;
    list-style:none;
    height:36px;
    margin-top:20px;

    font-family:Arial, Helvetica, sans-serif;
    font-size:13px;
    }

    ul.nav li {
    float:left;
    }

    ul.nav a {
    display:block;
    padding:0 28px;
    color:#000;
    text-decoration:none;
    }
  </style>
</head>

<body>
  <h1>W3C Payment Request API Tutorial</h1>

  <ul class="nav">
  <li><a href="/">1. Basic</a></li>
  <li><a href="/2">2. shippingAddress</a></li>
  <li><a href="/3">3. Sale</a></li>
  <li><a href="/4">4. reject Creditcards</a></li>
  <li><a href="/5">5. Tax</a></li>
  <li><a href="/6">6. reject shippingAddress</a></li>
  </ul>

  <p> Teil 6: Payment Request mit abweichender Lieferadresse (USA)</p>
  <div class="produkt produkt_shadow" id="produkt">
    <h2>Beispielprodukt</h2>
    <p>Ich bin ein ganz tolles Produkt! Kauf mich!</p>
    <div class="produkt_meta">
      <strong class="produkt_preis">nur 49.99 €</strong>
      <a href="#" id="produkt_button" class="produkt_button">Kaufen</a>
    </div>
  </div>

  <div class="produkt_bought" id="produkt_bought">
    <h2>Beispielprodukt gekauft!</h2>
      <p>Sie haben das Beispielprodukt erfolgreich für 49,99 € (+ 25 € Versand in die USA)</span> gekauft.</p>
    <p>Ihre Daten:</p>
    <div id="data_list"></div>

  </div>

  <script>
    function handleProduktClick(e) {
      e.preventDefault();

      var creditCardPaymentMethod = {
        supportedMethods: 'basic-card',
      };

      var supportedPaymentMethods = [creditCardPaymentMethod];

      var paymentDetails = {
        total: {
          label: 'Gesamtsumme',
          amount: {
            currency: 'EUR',
            value: '49.99'
          }
        },
        displayItems: [{
            label: 'Beispielprodukt',
            amount: {
              currency: 'EUR',
              value: '49.99'
            },
          },
          {
            label: 'Standardversand',
            amount: {
              currency: 'EUR',
              value: '0.00'
            },
            pending: true
          }

        ],
        shippingOptions: [{
            id: 'standard',
            label: 'Standardversand',
            amount: {
              currency: 'EUR',
              value: '0.00'
            }
          },
          {
            id: 'express',
            label: 'Expressversand',
            amount: {
              currency: 'EUR',
              value: '14.99'
            },
          },
        ],
      };

      var options = {
        requestShipping: true
      };

      var paymentRequest = new PaymentRequest(supportedPaymentMethods, paymentDetails, options);

      paymentRequest.addEventListener('shippingaddresschange', function(evt) {
        evt.updateWith(new Promise(function(resolve) {
          updateShippingDetails(paymentDetails, paymentRequest.shippingAddress, resolve);
        }));
      });

      paymentRequest.addEventListener('shippingoptionchange', function(evt) {
        evt.updateWith(new Promise(function(resolve, reject) {
          updateDetails(paymentDetails, paymentRequest.shippingOption, resolve, reject);
        }));
      });

      function updateShippingDetails(details, shippingAddress, resolve) {

        let shippingOption = {
          id: '',
          label: '',
          amount: {
            currency: 'EUR',
            value: '0.00'
          },
          selected: true,
          pending: false,
        };
        if (shippingAddress.country === 'US') {
          shippingOption.id = 'unitedStatesStandardShipping';
          shippingOption.label = 'Versand in die USA';
          shippingOption.amount.value = '25.00';
          details.total.amount.value = '74.99';
          details.shippingOptions = [shippingOption];
          details.displayItems.splice(1, 1, shippingOption);

        } else {

          shippingOption.label = 'Versandoption';
          shippingOption.pending = true;
          details.total.amount.value = '49.99';
          details.error = 'Kein Versand an Adressen außerhalb der USA.';
          details.shippingOptions = undefined;

        }
        resolve(details);
      }

      function updateDetails(details, shippingOption, resolve, reject) {
        if (shippingOption === 'standard') {
          selectedShippingOption = details.shippingOptions[0];
          otherShippingOption = details.shippingOptions[1];
          details.total.amount.value = '49.99';
        } else if (shippingOption === 'express') {
          selectedShippingOption = details.shippingOptions[1];
          otherShippingOption = details.shippingOptions[0];
          details.total.amount.value = '64.98';

        } else {
          reject('Unbekannte Versandart \'' + shippingOption + '\'');
          return;
        }
        selectedShippingOption.selected = true;
        otherShippingOption.selected = false;
        details.displayItems.splice(1, 2, selectedShippingOption);
        resolve(details);
      }

      paymentRequest
        .show()
        .then(paymentResponse => {
          console.log(paymentDetails.displayItems);
          return verifyPaymentWithBackend(paymentResponse).then((success) => {
            if (success) {

              showPaymentResponse(JSON.parse(success));
              return paymentResponse.complete('success');

            } else {
              return paymentResponse.complete('fail');
            }
          });
        })
        .catch(err => {
          console.log('Error:', err);
        });

    };

    function showPaymentResponse(data) {

      document.getElementById("produkt_button").innerHTML = 'Gekauft';
      document.getElementById("produkt_button").style.backgroundColor = "#4CAF50";

      document.getElementById("produkt_button").removeEventListener('click', handleProduktClick);

      document.getElementById("produkt_bought").style.display = "block";

      if (data.shippingOption == "express") {
        document.getElementById("express_selected").style.display = "inline-block";
      }

      document.getElementById("data_list").innerHTML = JSON.stringify(data);

    }

    function verifyPaymentWithBackend(data) {
      return new Promise((resolve, reject) => {

        var xmlhttp = new XMLHttpRequest();

        xmlhttp.onload = function() {

          if (xmlhttp.status == 201) {

            resolve(xmlhttp.responseText);
          } else {
            resolve(false)
          }
        };


        xmlhttp.open("POST", "/payment");
        xmlhttp.setRequestHeader("Content-Type", "application/json");

        xmlhttp.send(JSON.stringify(data));

      });
    }

    document.getElementById("produkt_button").addEventListener('click', handleProduktClick)
  </script>
</body>

</html>

Clone this wiki locally