// Copyright 2016 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.
package org.chromium.chrome.browser.payments;
import android.text.TextUtils;
import android.util.JsonWriter;
import org.chromium.chrome.browser.autofill.PersonalDataManager;
import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
import org.chromium.chrome.browser.autofill.PersonalDataManager.FullCardRequestDelegate;
import org.chromium.content_public.browser.WebContents;
import org.chromium.payments.mojom.PaymentItem;
import org.json.JSONObject;
import java.io.IOException;
import java.io.StringWriter;
import java.util.List;
import javax.annotation.Nullable;
/**
* The locally stored credit card payment instrument.
*/
public class AutofillPaymentInstrument
extends PaymentInstrument implements FullCardRequestDelegate {
private final WebContents mWebContents;
private CreditCard mCard;
private boolean mIsComplete;
@Nullable private AutofillProfile mBillingAddress;
@Nullable private DetailsCallback mCallback;
/**
* Builds a payment instrument for the given credit card.
*
* @param webContents The web contents where PaymentRequest was invoked.
* @param card The autofill card that can be used for payment.
* @param billingAddress The billing address for the card.
*/
public AutofillPaymentInstrument(
WebContents webContents, CreditCard card, @Nullable AutofillProfile billingAddress) {
super(card.getGUID(), card.getObfuscatedNumber(), card.getName(),
card.getIssuerIconDrawableId());
mWebContents = webContents;
mCard = card;
mIsComplete = false;
mBillingAddress = billingAddress;
}
@Override
public String getMethodName() {
return mCard.getBasicCardPaymentType();
}
@Override
public void getDetails(String unusedMerchantName, String unusedOrigin, PaymentItem unusedTotal,
List<PaymentItem> unusedCart, JSONObject unusedDetails, DetailsCallback callback) {
assert mIsComplete;
assert mCallback == null;
mCallback = callback;
PersonalDataManager.getInstance().getFullCard(mWebContents, mCard, this);
}
@Override
public void onFullCardDetails(CreditCard card, String cvc) {
StringWriter stringWriter = new StringWriter();
JsonWriter json = new JsonWriter(stringWriter);
try {
json.beginObject();
json.name("cardholderName").value(card.getName());
json.name("cardNumber").value(card.getNumber());
json.name("expiryMonth").value(card.getMonth());
json.name("expiryYear").value(card.getYear());
json.name("cardSecurityCode").value(cvc);
json.name("billingAddress").beginObject();
json.name("country").value(ensureNotNull(mBillingAddress.getCountryCode()));
json.name("region").value(ensureNotNull(mBillingAddress.getRegion()));
json.name("city").value(ensureNotNull(mBillingAddress.getLocality()));
json.name("dependentLocality")
.value(ensureNotNull(mBillingAddress.getDependentLocality()));
json.name("addressLine").beginArray();
String multipleLines = ensureNotNull(mBillingAddress.getStreetAddress());
if (!TextUtils.isEmpty(multipleLines)) {
String[] lines = multipleLines.split("\n");
for (int i = 0; i < lines.length; i++) {
json.value(lines[i]);
}
}
json.endArray();
json.name("postalCode").value(ensureNotNull(mBillingAddress.getPostalCode()));
json.name("sortingCode").value(ensureNotNull(mBillingAddress.getSortingCode()));
json.name("languageCode").value(ensureNotNull(mBillingAddress.getLanguageCode()));
json.name("organization").value(ensureNotNull(mBillingAddress.getCompanyName()));
json.name("recipient").value(ensureNotNull(mBillingAddress.getFullName()));
json.name("phone").value(ensureNotNull(mBillingAddress.getPhoneNumber()));
json.endObject();
json.endObject();
} catch (IOException e) {
onFullCardError();
return;
}
mCallback.onInstrumentDetailsReady(card.getBasicCardPaymentType(), stringWriter.toString());
}
private static String ensureNotNull(@Nullable String value) {
return value == null ? "" : value;
}
@Override
public void onFullCardError() {
mCallback.onInstrumentDetailsError();
mCallback = null;
}
@Override
public void dismiss() {}
/** @return Whether the card is complete and ready to be sent to the merchant as-is. */
public boolean isComplete() {
return mIsComplete;
}
/** Marks this card complete and ready to be sent to the merchant without editing first. */
public void setIsComplete() {
mIsComplete = true;
}
/**
* Updates the instrument and marks it "complete." Called after the user has edited this
* instrument.
*
* @param card The new credit card to use. The GUID should not change.
* @param billingAddress The billing address for the card. The GUID should match the billing
* address ID of the new card to use.
*/
public void completeInstrument(CreditCard card, AutofillProfile billingAddress) {
assert card != null;
assert billingAddress != null;
assert card.getBillingAddressId() != null;
assert card.getBillingAddressId().equals(billingAddress.getGUID());
mCard = card;
mBillingAddress = billingAddress;
mIsComplete = true;
updateIdentifierLabelsAndIcon(card.getGUID(), card.getObfuscatedNumber(), card.getName(),
null, card.getIssuerIconDrawableId());
}
/** @return The credit card represented by this payment instrument. */
public CreditCard getCard() {
return mCard;
}
}