1 // Copyright 2016 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.components.payments; 6 7 import android.graphics.drawable.Drawable; 8 9 import androidx.annotation.Nullable; 10 11 import org.chromium.base.task.PostTask; 12 import org.chromium.components.autofill.EditableOption; 13 import org.chromium.content_public.browser.UiThreadTaskTraits; 14 import org.chromium.payments.mojom.PaymentDetailsModifier; 15 import org.chromium.payments.mojom.PaymentItem; 16 import org.chromium.payments.mojom.PaymentMethodData; 17 import org.chromium.payments.mojom.PaymentOptions; 18 import org.chromium.payments.mojom.PaymentRequestDetailsUpdate; 19 import org.chromium.payments.mojom.PaymentShippingOption; 20 21 import java.util.List; 22 import java.util.Map; 23 import java.util.Set; 24 25 /** 26 * The base class for a single payment app, e.g., a payment handler. 27 */ 28 public abstract class PaymentApp extends EditableOption { 29 /** 30 * Whether complete and valid autofill data for merchant's request is available, e.g., if 31 * merchant specifies `requestPayerEmail: true`, then this variable is true only if the autofill 32 * data contains a valid email address. May be used in canMakePayment() for some types of 33 * app, such as AutofillPaymentInstrument. 34 */ 35 protected boolean mHaveRequestedAutofillData; 36 37 /** 38 * The interface for the requester of payment details from the app. 39 */ 40 public interface InstrumentDetailsCallback { 41 /** 42 * Called by the payment app to let Chrome know that the payment app's UI is now hidden, but 43 * the payment details have not been returned yet. This is a good time to show a "loading" 44 * progress indicator UI. 45 */ onInstrumentDetailsLoadingWithoutUI()46 void onInstrumentDetailsLoadingWithoutUI(); 47 48 /** 49 * Called after retrieving payment details. 50 * 51 * @param methodName Method name. For example, "visa". 52 * @param stringifiedDetails JSON-serialized object. For example, {"card": "123"}. 53 * @param payerData Payer's shipping address and contact information. 54 */ onInstrumentDetailsReady( String methodName, String stringifiedDetails, PayerData payerData)55 void onInstrumentDetailsReady( 56 String methodName, String stringifiedDetails, PayerData payerData); 57 58 /** 59 * Called if unable to retrieve payment details. 60 * @param errorMessage Developer-facing error message to be used when rejecting the promise 61 * returned from PaymentRequest.show(). 62 */ onInstrumentDetailsError(String errorMessage)63 void onInstrumentDetailsError(String errorMessage); 64 } 65 66 /** The interface for the requester to abort payment. */ 67 public interface AbortCallback { 68 /** 69 * Called after aborting payment is finished. 70 * 71 * @param abortSucceeded Indicates whether abort is succeed. 72 */ onInstrumentAbortResult(boolean abortSucceeded)73 void onInstrumentAbortResult(boolean abortSucceeded); 74 } 75 PaymentApp(String id, String label, String sublabel, Drawable icon)76 protected PaymentApp(String id, String label, String sublabel, Drawable icon) { 77 super(id, label, sublabel, icon); 78 } 79 PaymentApp( String id, String label, String sublabel, String tertiarylabel, Drawable icon)80 protected PaymentApp( 81 String id, String label, String sublabel, String tertiarylabel, Drawable icon) { 82 super(id, label, sublabel, tertiarylabel, icon); 83 } 84 85 /** 86 * Sets the modified total for this payment app. 87 * 88 * @param modifiedTotal The new modified total to use. 89 */ setModifiedTotal(@ullable String modifiedTotal)90 public void setModifiedTotal(@Nullable String modifiedTotal) { 91 updatePromoMessage(modifiedTotal); 92 } 93 94 /** 95 * Returns a set of payment method names for this app, e.g., "basic-card". 96 * 97 * @return The method names for this app. 98 */ getInstrumentMethodNames()99 public abstract Set<String> getInstrumentMethodNames(); 100 101 /** 102 * @return Whether this is an autofill app. All autofill apps are sorted below all non-autofill 103 * apps. 104 */ isAutofillInstrument()105 public boolean isAutofillInstrument() { 106 return false; 107 } 108 109 /** @return Whether this is a server autofill app. */ isServerAutofillInstrument()110 public boolean isServerAutofillInstrument() { 111 return false; 112 } 113 114 /** 115 * @return Whether this is a replacement for all server autofill apps. If at least one of 116 * the displayed apps returns true here, then all apps that return true in 117 * isServerAutofillInstrument() should be hidden. 118 */ isServerAutofillInstrumentReplacement()119 public boolean isServerAutofillInstrumentReplacement() { 120 return false; 121 } 122 123 /** 124 * @return Whether the app supports the payment method with the method data. For example, 125 * supported card types and networks in the data should be verified for 'basic-card' 126 * payment method. 127 */ isValidForPaymentMethodData(String method, @Nullable PaymentMethodData data)128 public boolean isValidForPaymentMethodData(String method, @Nullable PaymentMethodData data) { 129 return getInstrumentMethodNames().contains(method); 130 } 131 132 /** 133 * @return Whether the app can collect and return shipping address. 134 */ handlesShippingAddress()135 public boolean handlesShippingAddress() { 136 return false; 137 } 138 139 /** 140 * @return Whether the app can collect and return payer's name. 141 */ handlesPayerName()142 public boolean handlesPayerName() { 143 return false; 144 } 145 146 /** 147 * @return Whether the app can collect and return payer's email. 148 */ handlesPayerEmail()149 public boolean handlesPayerEmail() { 150 return false; 151 } 152 153 /** 154 * @return Whether the app can collect and return payer's phone. 155 */ handlesPayerPhone()156 public boolean handlesPayerPhone() { 157 return false; 158 } 159 160 /** @return The country code (or null if none) associated with this payment app. */ 161 @Nullable getCountryCode()162 public String getCountryCode() { 163 return null; 164 } 165 166 /** 167 * @param haveRequestedAutofillData Whether complete and valid autofill data for merchant's 168 * request is available. 169 */ setHaveRequestedAutofillData(boolean haveRequestedAutofillData)170 public void setHaveRequestedAutofillData(boolean haveRequestedAutofillData) { 171 mHaveRequestedAutofillData = haveRequestedAutofillData; 172 } 173 174 /** 175 * @return Whether presence of this payment app should cause the 176 * PaymentRequest.canMakePayment() to return true. 177 */ canMakePayment()178 public boolean canMakePayment() { 179 return true; 180 } 181 182 /** @return Whether this payment app can be pre-selected for immediate payment. */ canPreselect()183 public boolean canPreselect() { 184 return true; 185 } 186 187 /** @return Whether skip-UI flow with this app requires a user gesture. */ isUserGestureRequiredToSkipUi()188 public boolean isUserGestureRequiredToSkipUi() { 189 return true; 190 } 191 192 /** 193 * Invoke the payment app to retrieve the payment details. 194 * 195 * The callback will be invoked with the resulting payment details or error. 196 * 197 * @param id The unique identifier of the PaymentRequest. 198 * @param merchantName The name of the merchant. 199 * @param origin The origin of this merchant. 200 * @param iframeOrigin The origin of the iframe that invoked PaymentRequest. 201 * @param certificateChain The site certificate chain of the merchant. Can be null for localhost 202 * or local file, which are secure contexts without SSL. 203 * @param methodDataMap The payment-method specific data for all applicable payment methods, 204 * e.g., whether the app should be invoked in test or production, a 205 * merchant identifier, or a public key. 206 * @param total The total amount. 207 * @param displayItems The shopping cart items. 208 * @param modifiers The relevant payment details modifiers. 209 * @param paymentOptions The payment options of the PaymentRequest. 210 * @param shippingOptions The shipping options of the PaymentRequest. 211 * @param callback The object that will receive the payment details. 212 */ invokePaymentApp(String id, String merchantName, String origin, String iframeOrigin, @Nullable byte[][] certificateChain, Map<String, PaymentMethodData> methodDataMap, PaymentItem total, List<PaymentItem> displayItems, Map<String, PaymentDetailsModifier> modifiers, PaymentOptions paymentOptions, List<PaymentShippingOption> shippingOptions, InstrumentDetailsCallback callback)213 public void invokePaymentApp(String id, String merchantName, String origin, String iframeOrigin, 214 @Nullable byte[][] certificateChain, Map<String, PaymentMethodData> methodDataMap, 215 PaymentItem total, List<PaymentItem> displayItems, 216 Map<String, PaymentDetailsModifier> modifiers, PaymentOptions paymentOptions, 217 List<PaymentShippingOption> shippingOptions, InstrumentDetailsCallback callback) {} 218 219 /** 220 * Update the payment information in response to payment method, shipping address, or shipping 221 * option change events. 222 * 223 * @param response The merchant's response to the payment method, shipping address, or shipping 224 * option change events. 225 */ updateWith(PaymentRequestDetailsUpdate response)226 public void updateWith(PaymentRequestDetailsUpdate response) {} 227 228 /** 229 * Called when the merchant ignored the payment method, shipping address or shipping option 230 * change event. 231 */ onPaymentDetailsNotUpdated()232 public void onPaymentDetailsNotUpdated() {} 233 234 /** 235 * @return True after changePaymentMethodFromInvokedApp(), changeShippingOptionFromInvokedApp(), 236 * or changeShippingAddressFromInvokedApp() and before update updateWith() or 237 * onPaymentDetailsNotUpdated(). 238 */ isWaitingForPaymentDetailsUpdate()239 public boolean isWaitingForPaymentDetailsUpdate() { 240 return false; 241 } 242 243 /** 244 * Abort invocation of the payment app. 245 * @param callback The callback to return abort result. 246 */ abortPaymentApp(AbortCallback callback)247 public void abortPaymentApp(AbortCallback callback) { 248 PostTask.postTask(UiThreadTaskTraits.DEFAULT, new Runnable() { 249 @Override 250 public void run() { 251 callback.onInstrumentAbortResult(false); 252 } 253 }); 254 } 255 256 /** Cleans up any resources held by the payment app. For example, closes server connections. */ dismissInstrument()257 public abstract void dismissInstrument(); 258 259 /** @return Whether the payment app is ready for a minimal UI flow. */ isReadyForMinimalUI()260 public boolean isReadyForMinimalUI() { 261 return false; 262 } 263 264 /** @return Account balance for minimal UI flow. */ 265 @Nullable accountBalance()266 public String accountBalance() { 267 return null; 268 } 269 270 /** Disable opening a window for this payment app. */ disableShowingOwnUI()271 public void disableShowingOwnUI() {} 272 273 /** 274 * @return The identifier for another payment app that should be hidden when this payment app is 275 * present. 276 */ 277 @Nullable getApplicationIdentifierToHide()278 public String getApplicationIdentifierToHide() { 279 return null; 280 } 281 282 /** 283 * @return The set of identifier of other apps that would cause this app to be hidden, if any of 284 * them are present, e.g., ["com.bobpay.production", "com.bobpay.beta"]. 285 */ 286 @Nullable getApplicationIdentifiersThatHideThisApp()287 public Set<String> getApplicationIdentifiersThatHideThisApp() { 288 return null; 289 } 290 291 /** 292 * @return The ukm source id assigned to the payment app. 293 */ getUkmSourceId()294 public long getUkmSourceId() { 295 return 0; 296 } 297 298 /** 299 * Sets the endpoint for payment handler communication. Must be called before invoking this 300 * payment app. Used only by payment apps that are backed by a payment handler. 301 * @param host The endpoint for payment handler communication. Should not be null. 302 */ setPaymentHandlerHost(PaymentHandlerHost host)303 public void setPaymentHandlerHost(PaymentHandlerHost host) {} 304 305 /** @return The type of payment app. */ getPaymentAppType()306 public @PaymentAppType int getPaymentAppType() { 307 return PaymentAppType.UNDEFINED; 308 } 309 310 /** 311 * @return Whether this app should be chosen over other available payment apps. For example, 312 * when the Play Billing payment app is available in a TWA. 313 */ isPreferred()314 public boolean isPreferred() { 315 return false; 316 } 317 } 318