AMP
  • 網站

結帳流程

簡介

此範例示範如何在 AMP 中實作簡單的結帳頁面。此範例假設所有付款處理都在伺服器端完成。涵蓋的使用案例包括

  • 如何動態呈現購物車資料。
  • 如何支援使用者使用已儲存的地址和信用卡登入。
  • 如何讓使用者自動填寫聯絡方式、地址和信用卡詳細資訊。
  • 如何處理促銷/折扣代碼。

設定

我們使用了相當多的元件

amp-form 用於收集和提交使用者輸入。

<script async custom-element="amp-form" src="https://cdn.ampproject.org/v0/amp-form-0.1.js"></script>

amp-access 用於使用者登入。

<script async custom-element="amp-access" src="https://cdn.ampproject.org/v0/amp-access-0.1.js"></script>

amp-analyticsamp-access 擴充功能所必需的。

<script async custom-element="amp-analytics" src="https://cdn.ampproject.org/v0/amp-analytics-0.1.js"></script>

amp-list 用於呈現個人化內容,例如購物車。

<script async custom-element="amp-list" src="https://cdn.ampproject.org/v0/amp-list-0.1.js"></script>

amp-mustache 用於結合 amp-list 呈現範本。

<script async custom-template="amp-mustache" src="https://cdn.ampproject.org/v0/amp-mustache-0.2.js"></script>

amp-bind 用於根據使用者輸入動態更新頁面。

<script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>

登入支援

我們使用 amp-access 整合登入功能,並根據使用者是否已登入來顯示和隱藏登入按鈕。amp-access 需要定義 3 個端點,如此處所述。

此範例允許使用者使用電子郵件/密碼或 Google 登入來登入和登出。登出是透過在登入屬性 sign-out 中設定第二個端點來實作,請在此處找到更多資訊。

<script id="amp-access" type="application/json">
  {
      "authorization": "/documentation/examples/api/amp-access/authorization?rid=READER_ID&url=CANONICAL_URL&ref=DOCUMENT_REFERRER&_=RANDOM",
      "noPingback": "true",
      "login": {
        "sign-in": "/documentation/examples/api/amp-access/login?rid=READER_ID",
        "sign-out": "/documentation/examples/api/amp-access/logout?rid=READER_ID"
      },
      "authorizationFallbackResponse": {
          "error": true,
          "loggedIn": false
      }
  }
</script>

amp-access 讓我們可以根據使用者是否已登入來顯示登入或登出按鈕,例如,標記為 amp-access="NOT loggedIn" 的元素只會針對未登入的使用者顯示。按鈕的點擊時動作 (例如 on="tap:amp-access.login-sign-in") 指定點擊按鈕時應採取的動作:login 定義 amp-access json 設定內的屬性,而 sign-in 定義端點。

...或以訪客身分繼續
<div [hidden]="checkoutSuccess">
  <button amp-access="NOT loggedIn" on="tap:amp-access.login-sign-in">Login</button>
  <button amp-access="loggedIn" tabindex="0" on="tap:amp-access.login-sign-out" amp-access-hide>Logout</button>
  <span amp-access="NOT loggedIn">...or continue as guest</span>
</div>

檢視訂單 (購物車)

檢視訂單區段顯示目前的購物車內容和總價。我們從 JSON 端點提取購物車內容,並將其呈現在 amp-list 內。使用者是根據 AMP CLIENT_ID 識別的,該 ID 作為

請求參數傳遞。另一種可能性是使用 Cookie,如果設定了屬性 credentials="include",則 Cookie 會包含在 amp-list 的來源請求中。此外,我們將 amp-list 的 src 屬性繫結到隱含狀態物件 [src]="shoppingCart.src",我們使用它來使用 amp-bind 重新整理內容。

檢視訂單

<section [hidden]="checkoutSuccess" class="checkout-section">
  <h3>Review Order</h3>
  <amp-list width="auto" height="180" items="." single-item layout="fixed-height" credentials="include" src="https://amp.dev.org.tw/documentation/examples/e-commerce/checkout_flow/shoppingcart?clientId=CLIENT_ID(cart)" [src]="shoppingCart.src" binding="no">
    <template type="amp-mustache">
      <div class="shopping-cart">
        <div class="item header">
          <div class="name"></div>
          <div class="price"><strong>Price</strong></div>
          <div class="quantity"><strong>Quantity</strong></div>
        </div>
        {{#items}}
        <div class="item">
          <div class="name">{{name}}</div>
          <div class="price">${{price}}</div>
          <div class="quantity">{{quantity}}x</div>
        </div>
        {{/items}}
        {{#discount}}
        <div class="item summary">
          <div class="name"></div>
          <div class="price"><strong>Discount:</strong></div>
          <div class="quantity"><strong>{{.}}</strong></div>
        </div>
        {{/discount}}
        <div class="item summary">
          <div class="name"></div>
          <div class="price"><strong>Sum:</strong></div>
          <div class="quantity"><strong>${{total}}</strong></div>
        </div>
      </div>
    </template>
  </amp-list>
</section>

促銷/折扣代碼

此區段可以輸入促銷或折扣代碼。這是一個簡單的 amp-form,會將

代碼張貼到 XHR 端點。如果表單已成功提交,我們會重新整理購物車

內容,方法是使用更新的 src URL 更新 shoppingCart 物件。我們附加一個隨機值以使任何快取失效並強制

重新整理。

新增促銷代碼

<section [class]="checkoutSuccess ? 'hide' : 'checkout-section'" class="checkout-section">
  <h3> Add a promotional code </h3>
  <form method="post" action-xhr="https://amp.dev.org.tw/documentation/examples/e-commerce/checkout_flow/apply-code" on="submit-success:AMP.setState({
                shoppingCart: {
                  src: 'https://amp.dev.org.tw/documentation/examples/e-commerce/checkout_flow/shoppingcart?clientId=CLIENT_ID(cart)&' + random()
                }
             })" target="_top">
    <input name="clientId" type="hidden" value="CLIENT_ID(cart)" data-amp-replace="CLIENT_ID">
    <input name="code" placeholder="Code" aria-label="code" value="abc123">
    <button value="Apply">Apply</button>
  </form>
</section>

結帳表單

這是實際的結帳表單。表單提交透過 XHR 進行。表單成功提交後,我們會將

checkoutSuccess 變數設定為 true。這讓我們可以在結帳完成後隱藏表單。另一種選擇是在成功結帳後重新導向到新頁面。

<form id="checkout-form" method="post" [hidden]="checkoutSuccess" action-xhr="https://amp.dev.org.tw/documentation/examples/e-commerce/checkout_flow/apply-code" on="submit-success:AMP.setState({checkoutSuccess: true})" target="_top">

聯絡方式

未登入的使用者 (amp-access="NOT loggedIn") 將看到此區段以輸入其聯絡方式。

聯絡方式

<section class="checkout-section" amp-access="NOT loggedIn">
  <h3>Contact</h3>
  <label for="frmNameA">Name</label>
  <input name="name" id="frmNameA" placeholder="Full name" autocomplete="name">
  <label for="frmEmailA">Email</label>
  <input type="email" name="email" id="frmEmailA" placeholder="name@example.com" autocomplete="email">
</section>

運送與帳單地址

已登入的使用者 (amp-access="loggedIn") 可以選擇現有的地址,這些地址是使用另一個 amp-list 提取的。此區段最初透過 amp-access-hide 屬性隱藏。

我們為使用者提供第三個選項來輸入新地址。單選按鈕的 [change 動作](/documentation/guides-and-tutorials/learn/amp-actions-and-events) 會觸發地址表單的 [change 動作](/documentation/guides-and-tutorials/learn/amp-actions-and-events) `on="change:manualShippingAddress.toggleVisibility"` 的可見性。

選擇運送地址

<section class="checkout-section" amp-access="loggedIn" amp-access-hide>
  <h3>Select Shipping Address</h3>
  <amp-list width="auto" height="96" layout="fixed-height" items="." single-item credentials="include" src="/static/samples/json/addresses.json" binding="no">
    <template type="amp-mustache">
      <ul class="list-reset">
        {{#addresses}}
        <li>
          {{^default}}
          <input type="radio" id="address{{id}}" name="address" value="{{id}}" on="change:manualShippingAddress.hide">
          <label for="address{{id}}">{{name}}, {{street}}, {{city}} </label>
          {{/default}}
          {{#default}}
          <input type="radio" checked id="defaultAddress{{id}}" name="address" value="{{id}}" on="change:manualShippingAddress.hide">
          <label for="defaultAddress{{id}}">{{name}}, {{street}}, {{city}} {{#default}}<strong>[DEFAULT]</strong>{{/default}}</label>
          {{/default}}
          {{/addresses}}
        </li>
        {{#manual}}
        <li>
          <input type="radio" id="ship-separate" name="address" value="{{id}}" on="change:manualShippingAddress.toggleVisibility">
          <label for="ship-separate">Enter new Shipping Address</label>
        </li>
        {{/manual}}
      </ul>
    </template>
  </amp-list>

  <section class="sub-section" id="manualShippingAddress" hidden>
    <label for="manualShipAddressS">Address</label>
    <input name="ship-address" id="manualShipAddressS" placeholder="123 Any Street" autocomplete="shipping street-address">

    <label for="manualShipCityS">City</label>
    <input name="ship-city" id="manualShipCityS" placeholder="New York" autocomplete="shipping locality">

    <label for="manualShipStateS">State</label>
    <input name="ship-state" id="manualShipStateS" placeholder="NY" autocomplete="shipping region">

    <label for="manualShipZipS">Zip</label>
    <input name="ship-zip" id="manualShipZipS" placeholder="10011" autocomplete="shipping postal-code">

    <label for="manualShipCountryS">Country</label>
    <input name="ship-country" id="manualShipCountryS" placeholder="USA" autocomplete="shipping country">
    <label for="saveNewAddress1">Save Address</label>
    <input id="saveNewAddress1" type="checkbox" checked on="change:shippingAddress.toggleVisibility">
  </section>

  <label for="shippingAddressCheck">Use Shipping as Billing Address</label>
  <input id="shippingAddressCheck" type="checkbox" checked on="change:shippingAddress.toggleVisibility">
</section>

未登入的使用者會看到一個簡單的表單,用於輸入運送地址。我們使用 autocomplete 屬性

啟用 地址自動填寫,這大大簡化了使用者的表單填寫。

輸入運送地址

<section class="checkout-section" amp-access="NOT loggedIn">
  <h3>Enter Shipping Address</h3>
  <label for="shipAddressS">Address</label>
  <input name="ship-address" id="shipAddressS" placeholder="123 Any Street" autocomplete="shipping street-address">

  <label for="shipCityS">City</label>
  <input name="ship-city" id="shipCityS" placeholder="New York" autocomplete="shipping locality">

  <label for="shipStateS">State</label>
  <input name="ship-state" id="shipStateS" placeholder="NY" autocomplete="shipping region">

  <label for="shipZipS">Zip</label>
  <input name="ship-zip" id="shipZipS" placeholder="10011" autocomplete="shipping postal-code">

  <label for="shipCountryS">Country</label>
  <input name="ship-country" id="shipCountryS" placeholder="USA" autocomplete="shipping country">

  <label for="shippingAddressCheck">Use Shipping as Billing Address</label>
  <input type="checkbox" checked on="change:shippingAddress.toggleVisibility">
</section>

運送地址表單是選填的。我們最初使用 hidden 屬性隱藏它,以便可以透過

toggleVisibility 動作 (on="change:shippingAddress.toggleVisibility") 切換其可見性。

<section class="checkout-section" hidden id="billingAddress">
  <h3>Enter Billing Address</h3>
  <label for="billingAddressS">Address</label>
  <input name="billing-address" id="billingAddressS" placeholder="123 Any Street" autocomplete="billing street-address">

  <label for="billingCityS">City</label>
  <input name="billing-city" id="billingCityS" placeholder="New York" autocomplete="billing locality">

  <label for="billingStateS">State</label>
  <input name="billing-state" id="billingStateS" placeholder="NY" autocomplete="billing region">

  <label for="billingZipS">Zip</label>
  <input name="billing-zip" id="billingZipS" placeholder="10011" autocomplete="billing postal-code">

  <label for="billingCountryS">Country</label>
  <input name="billing-country" id="billingCountryS" placeholder="USA" autocomplete="billing country">
</section>

付款詳細資訊

已登入的使用者 (amp-access="loggedIn") 可以選擇現有的信用卡,該信用卡使用 amp-list 提取,類似於動態呈現運送地址的方式。也可以手動輸入信用卡詳細資訊。

選擇付款詳細資訊

<section class="checkout-section" amp-access="loggedIn" amp-access-hide>
  <h3>Select Payment Details</h3>
  <amp-list width="auto" height="96" layout="fixed-height" items="." single-item credentials="include" src="/static/samples/json/credit-cards.json" binding="no">
    <template type="amp-mustache">
      <ul class="list-reset">
        {{#cards}}
        <li>
          {{^default}}
          <input type="radio" id="cc{{id}}" name="cc" value="{{id}}" on="change:manualCC.hide">
          {{/default}}
          {{#default}}
          <input type="radio" checked id="defaultCC{{id}}" name="cc" value="{{id}}" on="change:manualCC.hide">
          {{/default}}
          <label for="defaultCC{{id}}">{{title}} {{#default}}<strong>[DEFAULT]</strong>{{/default}}</label>
          {{/cards}}
        </li>
        {{#manual}}
        <li>
          <input type="radio" id="new-cc" name="cc" value="{{id}}" on="change:manualCC.toggleVisibility">
          <label for="new-cc">Enter new Credit Card</label>
        </li>
        {{/manual}}
      </ul>
    </template>
  </amp-list>

  <section class="sub-section" id="manualCC" hidden>
    <label for="manualCCNameCC">Name on card</label>
    <input name="ccname" id="manualCCNameCC" placeholder="Full Name" autocomplete="cc-name">

    <label for="manualCCCCNum">Card Number</label>
    <input name="cardnumber" id="manualCCCCNum" autocomplete="cc-number">

    <label for="manualCCCVC">CVC</label>
    <input name="cvc" id="manualCCCVC" autocomplete="cc-csc">

    <label for="manualCCExp">Expiry</label>
    <input name="cc-exp" id="manualCCExp" placeholder="MM-YYYY" autocomplete="cc-exp">
    <label for="saveNewAddress2">Save Credit Card</label>
    <input id="saveNewAddress2" type="checkbox" checked on="change:shippingAddress.toggleVisibility">
  </section>
</section>

未登入的使用者可以手動輸入其信用卡詳細資訊。請注意,我們正在使用信用卡自動填寫標記。

輸入信用卡詳細資訊

<section class="checkout-section" amp-access="NOT loggedIn" amp-access-hide>
  <h3>Enter Credit Card Details</h3>
  <label for="nameCC">Name on card</label>
  <input name="ccname" id="nameCC" placeholder="Full Name" autocomplete="cc-name">

  <label for="ccNum">Card Number</label>
  <input name="cardnumber" id="ccNum" autocomplete="cc-number">

  <label for="ccCVC">CVC</label>
  <input name="cvc" id="ccCVC" autocomplete="cc-csc">

  <label for="ccExp">Expiry</label>
  <input name="cc-exp" id="ccExp" placeholder="MM-YYYY" autocomplete="cc-exp">
</section>

表單提交

立即付款按鈕只會提交包含不同結帳表單區段的表單。

非真實交易...
<div [hidden]="checkoutSuccess">
  <input type="submit" value="Pay Now">
  <span>Not for real ...</span>
</div>

這是我們在成功結帳且 checkoutSuccess 變數設定為 true 後將顯示的訊息。

<section hidden [hidden]="checkoutSuccess" class="checkout-section">
  <h3>Checkout success!</h3>
</section>

此範例不包含任何表單驗證。但是,可以使用 AMP 對自訂表單驗證的支援輕鬆新增此功能。

需要更多說明嗎?

如果此頁面上的說明未涵蓋您的所有問題,請隨時與其他 AMP 使用者聯繫,討論您的確切使用案例。

前往 Stack Overflow
無法解釋的功能?

AMP 專案強烈鼓勵您的參與和貢獻!我們希望您能成為我們開放原始碼社群的持續參與者,但我們也歡迎您針對您特別熱衷的問題做出一次性的貢獻。

在 GitHub 上編輯範例