| // Copyright 2020 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.components.payments; |
| |
| import android.graphics.Bitmap; |
| import android.graphics.drawable.BitmapDrawable; |
| import android.os.Handler; |
| |
| import androidx.annotation.Nullable; |
| |
| import org.chromium.base.annotations.CalledByNative; |
| import org.chromium.base.annotations.JNINamespace; |
| import org.chromium.base.annotations.NativeMethods; |
| import org.chromium.payments.mojom.PaymentDetailsModifier; |
| import org.chromium.payments.mojom.PaymentItem; |
| import org.chromium.payments.mojom.PaymentMethodData; |
| import org.chromium.payments.mojom.PaymentOptions; |
| import org.chromium.payments.mojom.PaymentRequestDetailsUpdate; |
| import org.chromium.payments.mojom.PaymentResponse; |
| import org.chromium.payments.mojom.PaymentShippingOption; |
| |
| import java.nio.ByteBuffer; |
| import java.util.Arrays; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| /** Wrapper around a C++ payment app. */ |
| @JNINamespace("payments") |
| public class JniPaymentApp extends PaymentApp { |
| private final Handler mHandler = new Handler(); |
| private final @PaymentAppType int mPaymentAppType; |
| |
| // The Java object owns the C++ payment app and frees it in dismissInstrument(). |
| private long mNativeObject; |
| |
| private AbortCallback mAbortCallback; |
| private InstrumentDetailsCallback mInvokeCallback; |
| |
| @CalledByNative |
| private JniPaymentApp(String id, String label, String sublabel, Bitmap icon, |
| @PaymentAppType int paymentAppType, long nativeObject) { |
| super(id, label, sublabel, new BitmapDrawable(icon)); |
| mPaymentAppType = paymentAppType; |
| mNativeObject = nativeObject; |
| } |
| |
| @CalledByNative |
| public void onAbortResult(boolean aborted) { |
| mHandler.post(() -> { |
| if (mAbortCallback == null) return; |
| mAbortCallback.onInstrumentAbortResult(aborted); |
| mAbortCallback = null; |
| }); |
| } |
| |
| @CalledByNative |
| public void onInvokeResult(String methodName, String stringifiedDetails, PayerData payerData) { |
| mHandler.post(() -> { |
| if (mInvokeCallback == null) return; |
| mInvokeCallback.onInstrumentDetailsReady(methodName, stringifiedDetails, payerData); |
| mInvokeCallback = null; |
| }); |
| } |
| |
| @CalledByNative |
| public void onInvokeError(String errorMessage) { |
| mHandler.post(() -> { |
| if (mInvokeCallback == null) return; |
| mInvokeCallback.onInstrumentDetailsError(errorMessage); |
| mInvokeCallback = null; |
| }); |
| } |
| |
| @CalledByNative |
| private static PayerData createPayerData(String payerName, String payerPhone, String payerEmail, |
| Address shippingAddress, String selectedShippingOptionId) { |
| return new PayerData( |
| payerName, payerPhone, payerEmail, shippingAddress, selectedShippingOptionId); |
| } |
| |
| @CalledByNative |
| private static Address createShippingAddress(String country, String[] addressLine, |
| String region, String city, String dependentLocality, String postalCode, |
| String sortingCode, String organization, String recipient, String phone) { |
| return new Address(country, addressLine, region, city, dependentLocality, postalCode, |
| sortingCode, organization, recipient, phone); |
| } |
| |
| @Override |
| public Set<String> getInstrumentMethodNames() { |
| return new HashSet<>( |
| Arrays.asList(JniPaymentAppJni.get().getInstrumentMethodNames(mNativeObject))); |
| } |
| |
| @Override |
| public boolean isValidForPaymentMethodData(String method, @Nullable PaymentMethodData data) { |
| return JniPaymentAppJni.get().isValidForPaymentMethodData( |
| mNativeObject, method, data != null ? data.serialize() : null); |
| } |
| |
| @Override |
| public boolean handlesShippingAddress() { |
| return JniPaymentAppJni.get().handlesShippingAddress(mNativeObject); |
| } |
| |
| @Override |
| public boolean handlesPayerName() { |
| return JniPaymentAppJni.get().handlesPayerName(mNativeObject); |
| } |
| |
| @Override |
| public boolean handlesPayerEmail() { |
| return JniPaymentAppJni.get().handlesPayerEmail(mNativeObject); |
| } |
| |
| @Override |
| public boolean handlesPayerPhone() { |
| return JniPaymentAppJni.get().handlesPayerPhone(mNativeObject); |
| } |
| |
| @Override |
| @Nullable |
| public String getCountryCode() { |
| return JniPaymentAppJni.get().getCountryCode(mNativeObject); |
| } |
| |
| @Override |
| public boolean canMakePayment() { |
| return JniPaymentAppJni.get().canMakePayment(mNativeObject); |
| } |
| |
| @Override |
| public boolean canPreselect() { |
| return JniPaymentAppJni.get().canPreselect(mNativeObject); |
| } |
| |
| @Override |
| public void 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) { |
| mInvokeCallback = callback; |
| JniPaymentAppJni.get().invokePaymentApp(mNativeObject, /*callback=*/this); |
| } |
| |
| @Override |
| public void updateWith(PaymentRequestDetailsUpdate response) { |
| JniPaymentAppJni.get().updateWith(mNativeObject, response.serialize()); |
| } |
| |
| @Override |
| public void onPaymentDetailsNotUpdated() { |
| JniPaymentAppJni.get().onPaymentDetailsNotUpdated(mNativeObject); |
| } |
| |
| @Override |
| public boolean isWaitingForPaymentDetailsUpdate() { |
| return JniPaymentAppJni.get().isWaitingForPaymentDetailsUpdate(mNativeObject); |
| } |
| |
| @Override |
| public void abortPaymentApp(AbortCallback callback) { |
| mAbortCallback = callback; |
| JniPaymentAppJni.get().abortPaymentApp(mNativeObject, this); |
| } |
| |
| @Override |
| @Nullable |
| public String getApplicationIdentifierToHide() { |
| return JniPaymentAppJni.get().getApplicationIdentifierToHide(mNativeObject); |
| } |
| |
| @Override |
| @Nullable |
| public Set<String> getApplicationIdentifiersThatHideThisApp() { |
| return new HashSet<>(Arrays.asList( |
| JniPaymentAppJni.get().getApplicationIdentifiersThatHideThisApp(mNativeObject))); |
| } |
| |
| @Override |
| public long getUkmSourceId() { |
| return JniPaymentAppJni.get().getUkmSourceId(mNativeObject); |
| } |
| |
| @Override |
| public void setPaymentHandlerHost(PaymentHandlerHost host) { |
| JniPaymentAppJni.get().setPaymentHandlerHost(mNativeObject, host); |
| } |
| |
| @Override |
| public void dismissInstrument() { |
| if (mNativeObject == 0) return; |
| JniPaymentAppJni.get().freeNativeObject(mNativeObject); |
| mNativeObject = 0; |
| } |
| |
| @Override |
| public void finalize() throws Throwable { |
| dismissInstrument(); |
| super.finalize(); |
| } |
| |
| @Override |
| public @PaymentAppType int getPaymentAppType() { |
| return mPaymentAppType; |
| } |
| |
| @Override |
| public PaymentResponse setAppSpecificResponseFields(PaymentResponse response) { |
| byte[] byteResult = JniPaymentAppJni.get().setAppSpecificResponseFields( |
| mNativeObject, response.serialize()); |
| return PaymentResponse.deserialize(ByteBuffer.wrap(byteResult)); |
| } |
| |
| @NativeMethods |
| interface Natives { |
| String[] getInstrumentMethodNames(long nativeJniPaymentApp); |
| boolean isValidForPaymentMethodData( |
| long nativeJniPaymentApp, String method, ByteBuffer dataByteBuffer); |
| boolean handlesShippingAddress(long nativeJniPaymentApp); |
| boolean handlesPayerName(long nativeJniPaymentApp); |
| boolean handlesPayerEmail(long nativeJniPaymentApp); |
| boolean handlesPayerPhone(long nativeJniPaymentApp); |
| String getCountryCode(long nativeJniPaymentApp); |
| boolean canMakePayment(long nativeJniPaymentApp); |
| boolean canPreselect(long nativeJniPaymentApp); |
| void invokePaymentApp(long nativeJniPaymentApp, JniPaymentApp callback); |
| void updateWith(long nativeJniPaymentApp, ByteBuffer responseByteBuffer); |
| void onPaymentDetailsNotUpdated(long nativeJniPaymentApp); |
| boolean isWaitingForPaymentDetailsUpdate(long nativeJniPaymentApp); |
| void abortPaymentApp(long nativeJniPaymentApp, JniPaymentApp callback); |
| String getApplicationIdentifierToHide(long nativeJniPaymentApp); |
| String[] getApplicationIdentifiersThatHideThisApp(long nativeJniPaymentApp); |
| long getUkmSourceId(long nativeJniPaymentApp); |
| void setPaymentHandlerHost(long nativeJniPaymentApp, PaymentHandlerHost paymentHandlerHost); |
| void freeNativeObject(long nativeJniPaymentApp); |
| byte[] setAppSpecificResponseFields(long nativeJniPaymentApp, ByteBuffer paymentResponse); |
| } |
| } |