| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_PAYMENTS_CLIENT_H_ |
| #define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_PAYMENTS_CLIENT_H_ |
| |
| #include <set> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/scoped_refptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/values.h" |
| #include "components/autofill/core/browser/autofill_client.h" |
| #include "components/autofill/core/browser/data_model/autofill_profile.h" |
| #include "components/autofill/core/browser/data_model/credit_card.h" |
| #include "components/autofill/core/browser/payments/card_unmask_challenge_option.h" |
| #include "components/autofill/core/browser/payments/card_unmask_delegate.h" |
| #include "components/signin/public/identity_manager/access_token_fetcher.h" |
| #include "components/signin/public/identity_manager/access_token_info.h" |
| #include "google_apis/gaia/google_service_auth_error.h" |
| #include "third_party/abseil-cpp/absl/types/optional.h" |
| |
| namespace signin { |
| class IdentityManager; |
| } // namespace signin |
| |
| namespace network { |
| struct ResourceRequest; |
| class SimpleURLLoader; |
| class SharedURLLoaderFactory; |
| } // namespace network |
| |
| namespace autofill { |
| |
| class AccountInfoGetter; |
| class MigratableCreditCard; |
| |
| namespace payments { |
| |
| // Callback type for MigrateCards callback. |result| is the Payments Rpc result. |
| // |save_result| is an unordered_map parsed from the response whose key is the |
| // unique id (guid) for each card and value is the server save result string. |
| // |display_text| is the returned tip from Payments to show on the UI. |
| typedef base::OnceCallback<void( |
| AutofillClient::PaymentsRpcResult result, |
| std::unique_ptr<std::unordered_map<std::string, std::string>> save_result, |
| const std::string& display_text)> |
| MigrateCardsCallback; |
| |
| // Billable service number is defined in Payments server to distinguish |
| // different requests. |
| const int kUnmaskCardBillableServiceNumber = 70154; |
| const int kUploadCardBillableServiceNumber = 70073; |
| const int kMigrateCardsBillableServiceNumber = 70264; |
| |
| class PaymentsRequest; |
| |
| // PaymentsClient issues Payments RPCs and manages responses and failure |
| // conditions. Only one request may be active at a time. Initiating a new |
| // request will cancel a pending request. |
| // Tests are located in |
| // src/components/autofill/content/browser/payments/payments_client_unittest.cc. |
| class PaymentsClient { |
| public: |
| // The names of the fields used to send non-location elements as part of an |
| // address. Used in the implementation and in tests which verify that these |
| // values are set or not at appropriate times. |
| static const char kRecipientName[]; |
| static const char kPhoneNumber[]; |
| |
| // Details for card unmasking, such as the suggested method of authentication, |
| // along with any information required to facilitate the authentication. |
| struct UnmaskDetails { |
| UnmaskDetails(); |
| ~UnmaskDetails(); |
| UnmaskDetails& operator=(const UnmaskDetails& other); |
| |
| // The type of authentication method suggested for card unmask. |
| AutofillClient::UnmaskAuthMethod unmask_auth_method = |
| AutofillClient::UnmaskAuthMethod::kUnknown; |
| // Set to true if the user should be offered opt-in for FIDO Authentication. |
| bool offer_fido_opt_in = false; |
| // Public Key Credential Request Options required for authentication. |
| // https://www.w3.org/TR/webauthn/#dictdef-publickeycredentialrequestoptions |
| absl::optional<base::Value> fido_request_options; |
| // Set of credit cards ids that are eligible for FIDO Authentication. |
| std::set<std::string> fido_eligible_card_ids; |
| }; |
| |
| // A collection of the information required to make a credit card unmask |
| // request. |
| struct UnmaskRequestDetails { |
| UnmaskRequestDetails(); |
| UnmaskRequestDetails(const UnmaskRequestDetails& other); |
| UnmaskRequestDetails& operator=(const UnmaskRequestDetails& other); |
| ~UnmaskRequestDetails(); |
| |
| int64_t billing_customer_number = 0; |
| CreditCard card; |
| std::string risk_data; |
| CardUnmaskDelegate::UserProvidedUnmaskDetails user_response; |
| absl::optional<base::Value> fido_assertion_info; |
| std::u16string otp; |
| // An opaque token used to chain consecutive payments requests together. |
| std::string context_token; |
| // The url origin of the website where the unmasking happened. Should be |
| // populated when the unmasking is for a virtual card. |
| absl::optional<GURL> last_committed_url_origin; |
| }; |
| |
| // Information retrieved from an UnmaskRequest. |
| struct UnmaskResponseDetails { |
| UnmaskResponseDetails(); |
| UnmaskResponseDetails(const UnmaskResponseDetails& other); |
| ~UnmaskResponseDetails(); |
| UnmaskResponseDetails& operator=(const UnmaskResponseDetails& other); |
| |
| UnmaskResponseDetails& with_real_pan(std::string r) { |
| real_pan = r; |
| return *this; |
| } |
| |
| UnmaskResponseDetails& with_dcvv(std::string d) { |
| dcvv = d; |
| return *this; |
| } |
| |
| std::string real_pan; |
| std::string dcvv; |
| // The expiration month of the card. It falls in between 1 - 12. Should be |
| // populated when the card is a virtual card which does not necessarily have |
| // the same expiration date as its related actual card. |
| std::string expiration_month; |
| // The four-digit expiration year of the card. Should be populated when the |
| // card is a virtual card which does not necessarily have the same |
| // expiration date as its related actual card. |
| std::string expiration_year; |
| // Challenge required for enrolling user into FIDO authentication for future |
| // card unmasking. |
| absl::optional<base::Value> fido_creation_options; |
| // Challenge required for authorizing user for FIDO authentication for |
| // future card unmasking. |
| absl::optional<base::Value> fido_request_options; |
| // An opaque token used to logically chain consecutive UnmaskCard and |
| // OptChange calls together. |
| std::string card_authorization_token; |
| // Available card unmask challenge options. |
| std::vector<CardUnmaskChallengeOption> card_unmask_challenge_options; |
| // An opaque token used to chain consecutive payments requests together. |
| // Client should not update or modify this token. |
| std::string context_token; |
| // An intermediate status in cases other than immediate success or failure. |
| std::string flow_status; |
| |
| // The type of the returned credit card. |
| AutofillClient::PaymentsRpcCardType card_type = |
| AutofillClient::PaymentsRpcCardType::kUnknown; |
| }; |
| |
| // Information required to either opt-in or opt-out a user for FIDO |
| // Authentication. |
| struct OptChangeRequestDetails { |
| OptChangeRequestDetails(); |
| OptChangeRequestDetails(const OptChangeRequestDetails& other); |
| ~OptChangeRequestDetails(); |
| |
| std::string app_locale; |
| |
| // The reason for making the request. |
| enum Reason { |
| // Unknown default. |
| UNKNOWN_REASON = 0, |
| // The user wants to enable FIDO authentication for card unmasking. |
| ENABLE_FIDO_AUTH = 1, |
| // The user wants to disable FIDO authentication for card unmasking. |
| DISABLE_FIDO_AUTH = 2, |
| // The user is authorizing a new card for future FIDO authentication |
| // unmasking. |
| ADD_CARD_FOR_FIDO_AUTH = 3, |
| }; |
| |
| // Reason for the request. |
| Reason reason; |
| // Signature required for enrolling user into FIDO authentication for future |
| // card unmasking. |
| absl::optional<base::Value> fido_authenticator_response; |
| // An opaque token used to logically chain consecutive UnmaskCard and |
| // OptChange calls together. |
| std::string card_authorization_token = std::string(); |
| }; |
| |
| // Information retrieved from an OptChange request. |
| struct OptChangeResponseDetails { |
| OptChangeResponseDetails(); |
| OptChangeResponseDetails(const OptChangeResponseDetails& other); |
| ~OptChangeResponseDetails(); |
| |
| // Unset if response failed. True if user is opted-in for FIDO |
| // authentication for card unmasking. False otherwise. |
| absl::optional<bool> user_is_opted_in; |
| // Challenge required for enrolling user into FIDO authentication for future |
| // card unmasking. |
| absl::optional<base::Value> fido_creation_options; |
| // Challenge required for authorizing user for FIDO authentication for |
| // future card unmasking. |
| absl::optional<base::Value> fido_request_options; |
| }; |
| |
| // A collection of the information required to make a credit card upload |
| // request. |
| struct UploadRequestDetails { |
| UploadRequestDetails(); |
| UploadRequestDetails(const UploadRequestDetails& other); |
| ~UploadRequestDetails(); |
| |
| int64_t billing_customer_number = 0; |
| int detected_values; |
| CreditCard card; |
| std::u16string cvc; |
| std::vector<AutofillProfile> profiles; |
| std::u16string context_token; |
| std::string risk_data; |
| std::string app_locale; |
| std::vector<const char*> active_experiments; |
| }; |
| |
| // A collection of the information required to make local credit cards |
| // migration request. |
| struct MigrationRequestDetails { |
| MigrationRequestDetails(); |
| MigrationRequestDetails(const MigrationRequestDetails& other); |
| ~MigrationRequestDetails(); |
| |
| int64_t billing_customer_number = 0; |
| std::u16string context_token; |
| std::string risk_data; |
| std::string app_locale; |
| }; |
| |
| // A collection of the information required to make select challenge option |
| // request. |
| struct SelectChallengeOptionRequestDetails { |
| SelectChallengeOptionRequestDetails(); |
| SelectChallengeOptionRequestDetails( |
| const SelectChallengeOptionRequestDetails& other); |
| ~SelectChallengeOptionRequestDetails(); |
| |
| CardUnmaskChallengeOption selected_challenge_option; |
| // An opaque token used to chain consecutive payments requests together. |
| std::string context_token; |
| int64_t billing_customer_number = 0; |
| }; |
| |
| // An enum set in the GetUploadDetailsRequest indicating the source of the |
| // request when uploading a card to Google Payments. It should stay consistent |
| // with the same enum in Google Payments server code. |
| enum UploadCardSource { |
| // Source unknown. |
| UNKNOWN_UPLOAD_CARD_SOURCE, |
| // Single card is being uploaded from the normal credit card offer-to-save |
| // prompt during a checkout flow. |
| UPSTREAM_CHECKOUT_FLOW, |
| // Single card is being uploaded from chrome://settings/payments. |
| UPSTREAM_SETTINGS_PAGE, |
| // Single card is being uploaded after being scanned by OCR. |
| UPSTREAM_CARD_OCR, |
| // 1+ cards are being uploaded from a migration request that started during |
| // a checkout flow. |
| LOCAL_CARD_MIGRATION_CHECKOUT_FLOW, |
| // 1+ cards are being uploaded from a migration request that was initiated |
| // from chrome://settings/payments. |
| LOCAL_CARD_MIGRATION_SETTINGS_PAGE, |
| }; |
| |
| // TODO(crbug.com/1285086): Remove the |server_id| field from |
| // UploadCardResponseDetails since it is never used. |
| // A collection of information received in the response for an |
| // UploadCardRequest. |
| struct UploadCardResponseDetails { |
| std::string server_id; |
| // TODO(crbug.com/1281695): Add |virtual_card_enrollment_state| and |
| // |card_art_url| data members when integrating all of the logic for the |
| // virtual card enrollment flow. |
| }; |
| |
| // TODO(crbug.com/1281695): Add GetDetailsForEnrollRequest. |
| // A collection of information received in the response for a |
| // GetDetailsForEnrollRequest. |
| struct GetDetailsForEnrollmentResponseDetails { |
| GetDetailsForEnrollmentResponseDetails(); |
| GetDetailsForEnrollmentResponseDetails( |
| const GetDetailsForEnrollmentResponseDetails&) = delete; |
| GetDetailsForEnrollmentResponseDetails& operator=( |
| const GetDetailsForEnrollmentResponseDetails&) = delete; |
| ~GetDetailsForEnrollmentResponseDetails(); |
| // |vcn_context_token| is used in the sequential Enroll call, where it |
| // allows the server to get the instrument id for this |vcn_context_token| |
| // and link this specific GetDetailsForEnroll call with its corresponding |
| // enroll call. |
| std::string vcn_context_token; |
| // Google's legal message lines in the virtual card enroll flow for this |
| // specific card based on |vcn_context_token|. |
| LegalMessageLines google_legal_message; |
| // The issuer's legal message lines in the virtual card enroll flow for this |
| // specific card based on |vcn_context_token|. |
| LegalMessageLines issuer_legal_message; |
| }; |
| |
| // |url_loader_factory| is reference counted so it has no lifetime or |
| // ownership requirements. |identity_manager| and |account_info_getter| must |
| // all outlive |this|. Either delegate might be nullptr. |is_off_the_record| |
| // denotes incognito mode. |
| PaymentsClient( |
| scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, |
| signin::IdentityManager* const identity_manager, |
| AccountInfoGetter* const account_info_getter, |
| bool is_off_the_record = false); |
| |
| PaymentsClient(const PaymentsClient&) = delete; |
| PaymentsClient& operator=(const PaymentsClient&) = delete; |
| |
| virtual ~PaymentsClient(); |
| |
| // Starts fetching the OAuth2 token in anticipation of future Payments |
| // requests. Called as an optimization, but not strictly necessary. Should |
| // *not* be called in advance of GetUploadDetails or UploadCard because |
| // identifying information should not be sent until the user has explicitly |
| // accepted an upload prompt. |
| void Prepare(); |
| |
| // The user has interacted with a credit card form and may attempt to unmask a |
| // card. This request returns what method of authentication is suggested, |
| // along with any information to facilitate the authentication. |
| virtual void GetUnmaskDetails( |
| base::OnceCallback<void(AutofillClient::PaymentsRpcResult, |
| UnmaskDetails&)> callback, |
| const std::string& app_locale); |
| |
| // The user has attempted to unmask a card with the given cvc. |
| virtual void UnmaskCard( |
| const UnmaskRequestDetails& request_details, |
| base::OnceCallback<void(AutofillClient::PaymentsRpcResult, |
| UnmaskResponseDetails&)> callback); |
| |
| // Opts-in or opts-out the user to use FIDO authentication for card unmasking |
| // on this device. |
| void OptChange(const OptChangeRequestDetails request_details, |
| base::OnceCallback<void(AutofillClient::PaymentsRpcResult, |
| OptChangeResponseDetails&)> callback); |
| |
| // Determine if the user meets the Payments service's conditions for upload. |
| // The service uses |addresses| (from which names and phone numbers are |
| // removed) and |app_locale| to determine which legal message to display. |
| // |detected_values| is a bitmask of CreditCardSaveManager::DetectedValue |
| // values that relays what data is actually available for upload in order to |
| // make more informed upload decisions. |callback| is the callback function |
| // when get response from server. |billable_service_number| is used to set the |
| // billable service number in the GetUploadDetails request. If the conditions |
| // are met, the legal message will be returned via |callback|. |
| // |active_experiments| is used by Payments server to track requests that were |
| // triggered by enabled features. |upload_card_source| is used by Payments |
| // server metrics to track the source of the request. |
| virtual void GetUploadDetails( |
| const std::vector<AutofillProfile>& addresses, |
| const int detected_values, |
| const std::vector<const char*>& active_experiments, |
| const std::string& app_locale, |
| base::OnceCallback<void(AutofillClient::PaymentsRpcResult, |
| const std::u16string&, |
| std::unique_ptr<base::Value>, |
| std::vector<std::pair<int, int>>)> callback, |
| const int billable_service_number, |
| UploadCardSource upload_card_source = |
| UploadCardSource::UNKNOWN_UPLOAD_CARD_SOURCE); |
| |
| // The user has indicated that they would like to upload a card with the given |
| // cvc. This request will fail server-side if a successful call to |
| // GetUploadDetails has not already been made. |
| virtual void UploadCard( |
| const UploadRequestDetails& details, |
| base::OnceCallback<void(AutofillClient::PaymentsRpcResult, |
| const PaymentsClient::UploadCardResponseDetails&)> |
| callback); |
| |
| // The user has indicated that they would like to migrate their local credit |
| // cards. This request will fail server-side if a successful call to |
| // GetUploadDetails has not already been made. |
| virtual void MigrateCards( |
| const MigrationRequestDetails& details, |
| const std::vector<MigratableCreditCard>& migratable_credit_cards, |
| MigrateCardsCallback callback); |
| |
| // The user has chosen one of the available challenge options. Send the |
| // selected challenge option to server to continue the unmask flow. |
| virtual void SelectChallengeOption( |
| const SelectChallengeOptionRequestDetails& details, |
| base::OnceCallback<void(AutofillClient::PaymentsRpcResult, |
| const std::string&)> callback); |
| |
| // Cancels and clears the current |request_|. |
| void CancelRequest(); |
| |
| // Exposed for testing. |
| void set_url_loader_factory_for_testing( |
| scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory); |
| |
| bool is_off_the_record() { return is_off_the_record_; } |
| |
| private: |
| friend class PaymentsClientTest; |
| |
| // Initiates a Payments request using the state in |request|. If |
| // |authenticate| is true, ensures that an OAuth token is avialble first. |
| // Takes ownership of |request|. |
| void IssueRequest(std::unique_ptr<PaymentsRequest> request, |
| bool authenticate); |
| |
| // Creates |resource_request_| to be used later in StartRequest(). |
| void InitializeResourceRequest(); |
| |
| // Callback from |simple_url_loader_|. |
| void OnSimpleLoaderComplete(std::unique_ptr<std::string> response_body); |
| void OnSimpleLoaderCompleteInternal(int response_code, |
| const std::string& data); |
| |
| // Callback that handles a completed access token request. |
| void AccessTokenFetchFinished(GoogleServiceAuthError error, |
| signin::AccessTokenInfo access_token_info); |
| |
| // Handles a completed access token request in the case of failure. |
| void AccessTokenError(const GoogleServiceAuthError& error); |
| |
| // Initiates a new OAuth2 token request. |
| void StartTokenFetch(bool invalidate_old); |
| |
| // Adds the token to |simple_url_loader_| and starts the request. |
| void SetOAuth2TokenAndStartRequest(); |
| |
| // Creates |simple_url_loader_| and calls it to start the request. |
| void StartRequest(); |
| |
| // The URL loader factory for the request. |
| scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; |
| |
| // Provided in constructor; not owned by PaymentsClient. |
| const raw_ptr<signin::IdentityManager> identity_manager_; |
| |
| // Provided in constructor; not owned by PaymentsClient. |
| const raw_ptr<AccountInfoGetter> account_info_getter_; |
| |
| // The current request. |
| std::unique_ptr<PaymentsRequest> request_; |
| |
| // The resource request being used to issue the current request. |
| std::unique_ptr<network::ResourceRequest> resource_request_; |
| |
| // The URL loader being used to issue the current request. |
| std::unique_ptr<network::SimpleURLLoader> simple_url_loader_; |
| |
| // The OAuth2 token fetcher for any account. |
| std::unique_ptr<signin::AccessTokenFetcher> token_fetcher_; |
| |
| // The OAuth2 token, or empty if not fetched. |
| std::string access_token_; |
| |
| // Denotes incognito mode. |
| bool is_off_the_record_; |
| |
| // True if |request_| has already retried due to a 401 response from the |
| // server. |
| bool has_retried_authorization_; |
| |
| base::WeakPtrFactory<PaymentsClient> weak_ptr_factory_{this}; |
| }; |
| |
| } // namespace payments |
| } // namespace autofill |
| |
| #endif // COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_PAYMENTS_CLIENT_H_ |