text: /*
   * Copyright (C) 2015-2019 Apple Inc. All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in the
   *    documentation and/or other materials provided with the distribution.
   *
   * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
   * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
   * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   * THE POSSIBILITY OF SUCH DAMAGE.
   */
  
  #pragma once
  
  #if ENABLE(APPLE_PAY)
  
  #include "PaymentContact.h"
  #include <wtf/Optional.h>
  #include <wtf/Vector.h>
  #include <wtf/text/WTFString.h>
  
  #if USE(APPLE_INTERNAL_SDK)
  #include <WebKitAdditions/ApplePaySessionPaymentRequestAdditions.h>
  #endif
  
  namespace WebCore {
  
  enum class PaymentAuthorizationStatus;
  
  class ApplePaySessionPaymentRequest {
  public:
      WEBCORE_EXPORT ApplePaySessionPaymentRequest();
      WEBCORE_EXPORT ~ApplePaySessionPaymentRequest();
  
      unsigned version() const { return m_version; }
      void setVersion(unsigned version) { m_version = version; }
  
      const String& countryCode() const { return m_countryCode; }
      void setCountryCode(const String& countryCode) { m_countryCode = countryCode; }
  
      const String& currencyCode() const { return m_currencyCode; }
      void setCurrencyCode(const String& currencyCode) { m_currencyCode = currencyCode; }
  
      struct ContactFields {
          bool postalAddress { false };
          bool phone { false };
          bool email { false };
          bool name { false };
          bool phoneticName { false };
      };
  
      const ContactFields& requiredBillingContactFields() const { return m_requiredBillingContactFields; }
      void setRequiredBillingContactFields(const ContactFields& requiredBillingContactFields) { m_requiredBillingContactFields = requiredBillingContactFields; }
  
      const PaymentContact& billingContact() const { return m_billingContact; }
      void setBillingContact(const PaymentContact& billingContact) { m_billingContact = billingContact; }
  
      const ContactFields& requiredShippingContactFields() const { return m_requiredShippingContactFields; }
      void setRequiredShippingContactFields(const ContactFields& requiredShippingContactFields) { m_requiredShippingContactFields = requiredShippingContactFields; }
  
      const PaymentContact& shippingContact() const { return m_shippingContact; }
      void setShippingContact(const PaymentContact& shippingContact) { m_shippingContact = shippingContact; }
  
      const Vector<String>& supportedNetworks() const { return m_supportedNetworks; }
      void setSupportedNetworks(const Vector<String>& supportedNetworks) { m_supportedNetworks = supportedNetworks; }
  
      struct MerchantCapabilities {
          bool supports3DS { false };
          bool supportsEMV { false };
          bool supportsCredit { false };
          bool supportsDebit { false };
      };
  
      const MerchantCapabilities& merchantCapabilities() const { return m_merchantCapabilities; }
      void setMerchantCapabilities(const MerchantCapabilities& merchantCapabilities) { m_merchantCapabilities = merchantCapabilities; }
  
      struct LineItem {
          enum class Type {
              Pending,
              Final,
          } type { Type::Final };
  
          String amount;
          String label;
      };
  
      enum class ShippingType {
          Shipping,
          Delivery,
          StorePickup,
          ServicePickup,
      };
      ShippingType shippingType() const { return m_shippingType; }
      void setShippingType(ShippingType shippingType) { m_shippingType = shippingType; }
  
      struct ShippingMethod {
          String label;
          String detail;
          String amount;
  
          String identifier;
      };
      const Vector<ShippingMethod>& shippingMethods() const { return m_shippingMethods; }
      void setShippingMethods(const Vector<ShippingMethod>& shippingMethods) { m_shippingMethods = shippingMethods; }
  
      const Vector<LineItem>& lineItems() const { return m_lineItems; }
      void setLineItems(const Vector<LineItem>& lineItems) { m_lineItems = lineItems; }
  
      const LineItem& total() const { return m_total; };
      void setTotal(const LineItem& total) { m_total = total; }
  
      struct TotalAndLineItems {
          ApplePaySessionPaymentRequest::LineItem total;
          Vector<ApplePaySessionPaymentRequest::LineItem> lineItems;
      };
  
      const String& applicationData() const { return m_applicationData; }
      void setApplicationData(const String& applicationData) { m_applicationData = applicationData; }
  
      const Vector<String>& supportedCountries() const { return m_supportedCountries; }
      void setSupportedCountries(Vector<String>&& supportedCountries) { m_supportedCountries = WTFMove(supportedCountries); }
  
      enum class Requester {
          ApplePayJS,
          PaymentRequest,
      };
  
      Requester requester() const { return m_requester; }
      void setRequester(Requester requester) { m_requester = requester; }
  
  #if defined(APPLEPAYSESSIONPAYMENTREQUEST_PUBLIC_ADDITIONS)
  APPLEPAYSESSIONPAYMENTREQUEST_PUBLIC_ADDITIONS
  #undef APPLEPAYSESSIONPAYMENTREQUEST_PUBLIC_ADDITIONS
  #endif
  
  private:
      unsigned m_version { 0 };
  
      String m_countryCode;
      String m_currencyCode;
  
      ContactFields m_requiredBillingContactFields;
      PaymentContact m_billingContact;
  
      ContactFields m_requiredShippingContactFields;
      PaymentContact m_shippingContact;
  
      Vector<String> m_supportedNetworks;
      MerchantCapabilities m_merchantCapabilities;
  
      ShippingType m_shippingType { ShippingType::Shipping };
      Vector<ShippingMethod> m_shippingMethods;
  
      Vector<LineItem> m_lineItems;
      LineItem m_total;
  
      String m_applicationData;
      Vector<String> m_supportedCountries;
  
      Requester m_requester { Requester::ApplePayJS };
  
  #if defined(APPLEPAYSESSIONPAYMENTREQUEST_PRIVATE_ADDITIONS)
  APPLEPAYSESSIONPAYMENTREQUEST_PRIVATE_ADDITIONS
  #undef APPLEPAYSESSIONPAYMENTREQUEST_PRIVATE_ADDITIONS
  #endif
  };
  
  struct PaymentError {
      enum class Code {
          Unknown,
          ShippingContactInvalid,
          BillingContactInvalid,
          AddressUnserviceable,
      };
  
      enum class ContactField {
          PhoneNumber,
          EmailAddress,
          Name,
          PhoneticName,
          PostalAddress,
          AddressLines,
          SubLocality,
          Locality,
          PostalCode,
          SubAdministrativeArea,
          AdministrativeArea,
          Country,
          CountryCode,
      };
  
      Code code;
      String message;
      Optional<ContactField> contactField;
  };
  
  struct PaymentAuthorizationResult {
      PaymentAuthorizationStatus status;
      Vector<PaymentError> errors;
  };
  
  struct ShippingContactUpdate {
      Vector<PaymentError> errors;
  
      Vector<ApplePaySessionPaymentRequest::ShippingMethod> newShippingMethods;
      ApplePaySessionPaymentRequest::TotalAndLineItems newTotalAndLineItems;
  };
  
  struct ShippingMethodUpdate {
      ApplePaySessionPaymentRequest::TotalAndLineItems newTotalAndLineItems;
  };
  
  WEBCORE_EXPORT bool isFinalStateResult(const Optional<PaymentAuthorizationResult>&);
  
  }
  
  namespace WTF {
  
  template<> struct EnumTraits<WebCore::PaymentError::Code> {
      using values = EnumValues<
          WebCore::PaymentError::Code,
          WebCore::PaymentError::Code::Unknown,
          WebCore::PaymentError::Code::ShippingContactInvalid,
          WebCore::PaymentError::Code::BillingContactInvalid,
          WebCore::PaymentError::Code::AddressUnserviceable
      >;
  };
  
  template<> struct EnumTraits<WebCore::PaymentError::ContactField> {
      using values = EnumValues<
          WebCore::PaymentError::ContactField,
          WebCore::PaymentError::ContactField::PhoneNumber,
          WebCore::PaymentError::ContactField::EmailAddress,
          WebCore::PaymentError::ContactField::Name,
          WebCore::PaymentError::ContactField::PhoneticName,
          WebCore::PaymentError::ContactField::PostalAddress,
          WebCore::PaymentError::ContactField::AddressLines,
          WebCore::PaymentError::ContactField::SubLocality,
          WebCore::PaymentError::ContactField::Locality,
          WebCore::PaymentError::ContactField::PostalCode,
          WebCore::PaymentError::ContactField::SubAdministrativeArea,
          WebCore::PaymentError::ContactField::AdministrativeArea,
          WebCore::PaymentError::ContactField::Country,
          WebCore::PaymentError::ContactField::CountryCode
      >;
  };
  
  }
  
  #endif
  