הזנת פרטי משלוח ופרטים ליצירת קשר מאפליקציית תשלום ל-Android

איך מעדכנים את אפליקציית התשלום ל-Android כדי לספק כתובת למשלוח ופרטים ליצירת קשר עם משלם באמצעות ממשקי API של תשלומים באינטרנט.

Sahel Sharify
Sahel Sharify

פורסם: 17 ביולי 2020, עודכן לאחרונה: 27 במאי 2025

הזנת כתובת למשלוח ופרטים ליצירת קשר באמצעות טופס אינטרנטי עלולה להיות מסורבלת ללקוחות. היא עלולה לגרום לשגיאות ולהפחית את שיעור ההמרה.

לכן, Payment Request API תומך בתכונה שמאפשרת לבקש כתובת למשלוח ופרטים ליצירת קשר. היתרונות של השימוש בשיטה הזו:

  • המשתמשים יכולים לבחור את הכתובת הנכונה בכמה הקשות פשוטות.
  • הכתובת תמיד מוחזרת בפורמט סטנדרטי.
  • הסיכוי להזנת כתובת שגויה נמוך יותר.

דפדפנים יכולים לדחות את האיסוף של כתובת למשלוח ופרטים ליצירת קשר לאפליקציית תשלום, כדי לספק חוויית תשלום אחידה. הפונקציונליות הזו נקראת הענקת הרשאה.

בכל הזדמנות אפשרית, Chrome מעביר את איסוף כתובת המשלוח ופרטי הקשר של הלקוח לאפליקציית התשלום של Android שהופעלה. ההעברה הזו מצמצמת את החיכוך במהלך התשלום.

אפשרויות המשלוח והמחיר הכולל באתר של המוכר יכולים להתעדכן באופן דינמי בהתאם לכתובת המשלוח ולאפשרות המשלוח שהלקוח בחר.

שינוי של אפשרות המשלוח והכתובת למשלוח בפעולה. אתם יכולים לראות איך זה משפיע באופן דינמי על אפשרויות המשלוח ועל המחיר הכולל.

כדי להוסיף תמיכה בהענקת הרשאה לאפליקציית תשלום קיימת ל-Android:

  1. הצהרה על העברות הרשאות נתמכות
  2. ניתוח של תוספים של כוונת PAY לאפשרויות תשלום נדרשות.
  3. העברת המידע הנדרש בתגובה לתשלום.
  4. אופציונלי: תמיכה בזרימה דינמית:
    1. לעדכן את המוכר לגבי שינויים באמצעי התשלום, בכתובת למשלוח או באפשרות המשלוח שהמשתמש בחר.
    2. קבלת פרטי תשלום מעודכנים מהמוֹכר (לדוגמה, הסכום הכולל המותאם בהתאם לעלות של אפשרות המשלוח שנבחרה).

הצהרה על האצלות נתמכות

הדפדפן צריך לדעת מה רשימת הפרטים הנוספים שאפליקציית התשלום יכולה לספק, כדי שהוא יוכל להעביר לאפליקציה את האחריות לאיסוף הפרטים האלה. צריך להצהיר על ההעברות הנתמכות כ-<meta-data> בקובץ AndroidManifest.xml של האפליקציה.

<activity
  android:name=".PaymentActivity"
    <meta-data
    android:name="org.chromium.payment_supported_delegations"
    android:resource="@array/chromium_payment_supported_delegations" />
</activity>

הערך של android:resource צריך להפנות אל <string-array> שמכיל את כל הערכים הבאים או קבוצת משנה שלהם:

  • payerName
  • payerEmail
  • payerPhone
  • shippingAddress

בדוגמה הבאה אפשר לספק רק כתובת למשלוח וכתובת אימייל של המשלם.

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <string-array name="chromium_payment_supported_delegations">
    <item>payerEmail</item>
    <item>shippingAddress</item>
  </string-array>
</resources>

ניתוח של תוספות ל-intent‏ PAY לאפשרויות תשלום נדרשות

המוכר יכול לציין מידע נוסף שנדרש באמצעות מילון paymentOptions. ‫Chrome יספק את רשימת האפשרויות הנדרשות שהאפליקציה יכולה לספק על ידי העברת paymentOptions Intent extras לפעילות PAY.

paymentOptions

paymentOptions הוא קבוצת המשנה של אפשרויות התשלום שצוינו על ידי המוכר, שלגביהן האפליקציה שלכם הצהירה על תמיכה בהעברת הרשאה.

Kotlin

val paymentOptions: Bundle? = extras.getBundle("paymentOptions")
val requestPayerName: Boolean? = paymentOptions?.getBoolean("requestPayerName")
val requestPayerPhone: Boolean? = paymentOptions?.getBoolean("requestPayerPhone")
val requestPayerEmail: Boolean? = paymentOptions?.getBoolean("requestPayerEmail")
val requestShipping: Boolean? = paymentOptions?.getBoolean("requestShipping")
val shippingType: String? = paymentOptions?.getString("shippingType")

Java

Bundle paymentOptions = extras.getBundle("paymentOptions");
if (paymentOptions != null) {
    Boolean requestPayerName = paymentOptions.getBoolean("requestPayerName");
    Boolean requestPayerPhone = paymentOptions.getBoolean("requestPayerPhone");
    Boolean requestPayerEmail = paymentOptions.getBoolean("requestPayerEmail");
    Boolean requestShipping = paymentOptions.getBoolean("requestShipping");
    String shippingType = paymentOptions.getString("shippingType");
}

הוא יכול לכלול את הפרמטרים הבאים:

  • requestPayerName – ערך בוליאני שמציין אם נדרש שם המשלם.
  • requestPayerPhone – ערך בוליאני שמציין אם נדרש מספר הטלפון של המשלם.
  • requestPayerEmail – ערך בוליאני שמציין אם נדרשת כתובת האימייל של המשלם.
  • requestShipping – ערך בוליאני שמציין אם נדרשים פרטי משלוח.
  • shippingType – מחרוזת שמציגה את סוג המשלוח. סוג המשלוח יכול להיות "shipping", "delivery" או "pickup". האפליקציה יכולה להשתמש ברמז הזה בממשק המשתמש שלה כשהיא מבקשת את כתובת המשתמש או את אפשרויות המשלוח שהוא בוחר.

shippingOptions

shippingOptions הוא מערך של אפשרויות משלוח שצוינו על ידי המוכר, שאפשר להעביר אותו כחבילה. הפרמטר הזה יופיע רק כשpaymentOptions.requestShipping == true.

Kotlin

val shippingOptions: List<ShippingOption>? =
    extras.getParcelableArray("shippingOptions")?.mapNotNull {
        p -> from(p as Bundle)
    }

Java

Parcelable[] shippingOptions = extras.getParcelableArray("shippingOptions");
for (Parcelable it : shippingOptions) {
  if (it != null && it instanceof Bundle) {
    Bundle shippingOption = (Bundle) it;
  }
}

כל אפשרות משלוח היא Bundle עם המפתחות הבאים.

  • id – המזהה של אפשרות המשלוח.
  • label – התווית של אפשרות המשלוח שמוצגת למשתמש.
  • amount – חבילת עלויות המשלוח שמכילה את המפתחות currency ו-value עם ערכי מחרוזת.
    • currency מייצג את המטבע של עלות המשלוח, כקוד אלפביתי בן 3 אותיות בפורמט תקין של ISO4217
    • value מציין את ערך עלות המשלוח כערך כספי עשרוני תקין
  • selected – מציין אם אפשרות המשלוח צריכה להיות מסומנת כשמוצגות אפשרויות המשלוח באפליקציית התשלום.

לכל המפתחות חוץ מ-selected יש ערכי מחרוזת. selected הוא ערך בוליאני.

Kotlin

val id: String = bundle.getString("id")
val label: String = bundle.getString("label")
val amount: Bundle = bundle.getBundle("amount")
val selected: Boolean = bundle.getBoolean("selected", false)

Java

String id = bundle.getString("id");
String label = bundle.getString("label");
Bundle amount = bundle.getBundle("amount");
Boolean selected = bundle.getBoolean("selected", false);

העברת מידע נדרש בתגובה לתשלום

האפליקציה שלך צריכה לכלול בתשובה שלה לפעילות PAY את המידע הנוסף הנדרש.

כדי לעשות זאת, צריך לציין את הפרמטרים הבאים כתוספים של Intent:

  • payerName – השם המלא של המשלם. אם הערך של paymentOptions.requestPayerName הוא true, המחרוזת הזו לא יכולה להיות ריקה.
  • payerPhone – מספר הטלפון של המשלם. אם הערך של paymentOptions.requestPayerPhone הוא true, המחרוזת הזו לא יכולה להיות ריקה.
  • payerEmail – כתובת האימייל של המשלם. אם הערך של paymentOptions.requestPayerEmail הוא true, המחרוזת לא יכולה להיות ריקה.
  • shippingAddress – כתובת המשלוח שהמשתמש סיפק. אם הערך של paymentOptions.requestShipping הוא true, הערך של המאפיין הזה צריך להיות חבילה לא ריקה. לחבילה צריכים להיות המפתחות הבאים שמייצגים חלקים שונים בכתובת פיזית.
    • countryCode
    • postalCode
    • sortingCode
    • region
    • city
    • dependentLocality
    • addressLine
    • organization
    • recipient
    • phone לכל המפתחות מלבד addressLine יש ערכי מחרוזת. ‫addressLine הוא מערך של מחרוזות.
  • shippingOptionId – המזהה של אפשרות המשלוח שהמשתמש בחר. אם הערך של paymentOptions.requestShipping הוא true, המחרוזת הזו לא יכולה להיות ריקה.

אימות תגובת התשלום

אם התוצאה של הפעילות בתגובה לתשלום שהתקבלה מאפליקציית התשלום שהופעלה מוגדרת כ-RESULT_OK, ‏ Chrome יבדוק אם יש פרטים נוספים נדרשים בתוספים שלה. אם האימות ייכשל, Chrome יחזיר הבטחה (promise) שנדחתה מ-request.show() עם אחת מהודעות השגיאה הבאות שמוצגות למפתחים:

'Payment app returned invalid response. Missing field "payerEmail".'
'Payment app returned invalid response. Missing field "payerName".'
'Payment app returned invalid response. Missing field "payerPhone".'
'Payment app returned invalid shipping address in response.'
'... is not a valid CLDR country code, should be 2 upper case letters [A-Z].'
'Payment app returned invalid response. Missing field "shipping option".'

דוגמה לתגובה תקינה:

Kotlin

fun Intent.populateRequestedPaymentOptions() {
    if (requestPayerName) {
        putExtra("payerName", "John Smith")
    }
    if (requestPayerPhone) {
        putExtra("payerPhone", "5555555555")
    }
    if (requestPayerEmail) {
        putExtra("payerEmail", "john.smith@gmail.com")
    }
    if (requestShipping) {
        val address: Bundle = Bundle()
        address.putString("countryCode", "CA")
        val addressLines: Array<String> =
                arrayOf<String>("111 Richmond st. West")
        address.putStringArray("addressLines", addressLines)
        address.putString("region", "Ontario")
        address.putString("city", "Toronto")
        address.putString("postalCode", "M5H2G4")
        address.putString("recipient", "John Smith")
        address.putString("phone", "5555555555")
        putExtra("shippingAddress", address)
        putExtra("shippingOptionId", "standard")
    }
}

Java

private Intent populateRequestedPaymentOptions() {
    Intent result = new Intent();
    if (requestPayerName) {
        result.putExtra("payerName", "John Smith");
    }
    if (requestPayerPhone) {
        presult.utExtra("payerPhone", "5555555555");
    }
    if (requestPayerEmail) {
        result.putExtra("payerEmail", "john.smith@gmail.com");
    }
    if (requestShipping) {
        Bundle address = new Bundle();
        address.putExtra("countryCode", "CA");
        address.putExtra("postalCode", "M5H2G4");
        address.putExtra("region", "Ontario");
        address.putExtra("city", "Toronto");
        String[] addressLines = new String[] {"111 Richmond st. West"};
        address.putExtra("addressLines", addressLines);
        address.putExtra("recipient", "John Smith");
        address.putExtra("phone", "5555555555");
        result.putExtra("shippingAddress", address);
        result.putExtra("shippingOptionId", "standard");
    }
    return result;
}

אופציונלי: תמיכה בתהליך דינמי

לפעמים העלות הכוללת של עסקה עולה, למשל כשהמשתמש בוחר באפשרות של משלוח אקספרס, או כשהרשימה של אפשרויות המשלוח הזמינות או המחירים שלהן משתנים כשהמשתמש בוחר כתובת משלוח בינלאומית. אם האפליקציה מספקת את כתובת המשלוח או את אפשרות המשלוח שהמשתמש בחר, היא צריכה להיות מסוגלת להודיע למוֹכר על שינויים בכתובת המשלוח או באפשרות המשלוח, ולהציג למשתמש את פרטי התשלום המעודכנים (שסופקו על ידי המוכר).

כדי להודיע למוֹכר על שינויים חדשים, צריך להטמיע את הממשק IPaymentDetailsUpdateServiceCallback ולהצהיר עליו ב-AndroidManifest.xml באמצעות מסנן הכוונות UPDATE_PAYMENT_DETAILS.

מיד אחרי הפעלת intent‏ PAY, ‏ Chrome יתחבר לשירות UPDATE_PAYMENT_DETAILS (אם הוא קיים) באותו חבילה כמו intent‏ PAY, ויקרא ל-setPaymentDetailsUpdateService(service) כדי לספק לאפליקציית התשלום שלכם את נקודת הקצה IPaymentDetailsUpdateService לצורך קבלת הודעות על שינויים באמצעי התשלום, באפשרות המשלוח או בכתובת למשלוח של המשתמש.

משתמשים ב-packageManager.getPackagesForUid(Binder.getCallingUid()) כשמקבלים תקשורת בין תהליכים (IPC) כדי לוודא שלאפליקציה שהפעילה את intent‏ PAY יש אותו שם חבילה כמו לאפליקציה שהפעילה את השיטות IPaymentDetailsUpdateServiceCallback.

AIDL

יוצרים שני קובצי AIDL עם התוכן הבא:

org/chromium/components/payments/IPaymentDetailsUpdateServiceCallback.aidl

package org.chromium.components.payments;

import android.os.Bundle;
import org.chromium.components.payments.IPaymentDetailsUpdateService;

interface IPaymentDetailsUpdateServiceCallback {
    oneway void updateWith(in Bundle updatedPaymentDetails);

    oneway void paymentDetailsNotUpdated();

    oneway void setPaymentDetailsUpdateService(IPaymentDetailsUpdateService service);
}

org/chromium/components/payments/IPaymentDetailsUpdateService.aidl

package org.chromium.components.payments;

import android.os.Bundle;
import org.chromium.components.payments.IPaymentDetailsUpdateServiceCallback;

interface IPaymentDetailsUpdateService {
    oneway void changePaymentMethod(in Bundle paymentHandlerMethodData,
            IPaymentDetailsUpdateServiceCallback callback);

    oneway void changeShippingOption(in String shippingOptionId,
            IPaymentDetailsUpdateServiceCallback callback);

    oneway void changeShippingAddress(in Bundle shippingAddress,
            IPaymentDetailsUpdateServiceCallback callback);
}

שירות

מטמיעים את השירות IPaymentDetailsUpdateServiceCallback.

Kotlin

class SampleUpdatePaymentDetailsCallbackService : Service() {
    private val binder = object : IPaymentDetailsUpdateServiceCallback.Stub() {
        override fun updateWith(updatedPaymentDetails: Bundle) {}

        override fun paymentDetailsNotUpdated() {}

        override fun setPaymentDetailsUpdateService(service: IPaymentDetailsUpdateService) {}
    }

    override fun onBind(intent: Intent?): IBinder? {
        return binder
    }
}

Java

import org.chromium.components.paymsnts.IPaymentDetailsUpdateServiceCallback;

public class SampleUpdatePaymentDetailsCallbackService extends Service {
    private final IPaymentDetailsUpdateServiceCallback.Stub mBinder =
        new IPaymentDetailsUpdateServiceCallback.Stub() {
            @Override
            public void updateWith(Bundle updatedPaymentDetails) {}

            @Override
            public void paymentDetailsNotUpdated() {}

            @Override
            public void setPaymentDetailsUpdateService(IPaymentDetailsUpdateService service) {}
        };

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }
}

AndroidManifest.xml

חשיפת השירות ל-IPaymentDetailsUpdateServiceCallback ב-AndroidManifest.xml.

<service
    android:name=".SampleUpdatePaymentDetailsCallbackService"
    android:exported="true">
    <intent-filter>
        <action android:name="org.chromium.intent.action.UPDATE_PAYMENT_DETAILS" />
    </intent-filter>
</service>

הודעה למוֹכר על שינויים באמצעי התשלום, בכתובת למשלוח או באפשרות המשלוח שהמשתמש בחר

Kotlin

try {
    if (isOptionChange) {
        service?.changeShippingOption(selectedOptionId, callback)
    } else (isAddressChange) {
        service?.changeShippingAddress(selectedAddress, callback)
    } else {
        service?.changePaymentMethod(methodData, callback)
    }
} catch (e: RemoteException) {
    // Handle the remote exception
}

Java

if (service == null) {
  return;
}

try {
    if (isOptionChange) {
        service.changeShippingOption(selectedOptionId, callback);
    } else (isAddressChange) {
        service.changeShippingAddress(selectedAddress, callback);
    } else {
        service.changePaymentMethod(methodData, callback);
    }
} catch (RemoteException e) {
    // Handle the remote exception
}

changePaymentMethod

הודעה על שינויים באמצעי התשלום שהמשתמש בחר נשלחת אל המוכר. חבילת paymentHandlerMethodData מכילה את המפתח methodName ומפתחות אופציונליים details, שכולם עם ערכי מחרוזת. דפדפן Chrome יחפש חבילה לא ריקה עם methodName לא ריק, ואם האימות ייכשל, הוא ישלח updatePaymentDetails עם אחת מהודעות השגיאה הבאות באמצעות callback.updateWith.

'Method data required.'
'Method name required.'

changeShippingOption

הודעה למוֹכר על שינויים באפשרות המשלוח שהמשתמש בחר. הערך של shippingOptionId צריך להיות המזהה של אחת מאפשרויות המשלוח שהמוֹכר הגדיר. דפדפן Chrome יבדוק אם shippingOptionId לא ריק וישלח updatePaymentDetails עם הודעת השגיאה הבאה באמצעות callback.updateWith אם האימות ייכשל.

'Shipping option identifier required.'

changeShippingAddress

הודעה למוֹכר על שינויים בכתובת המשלוח שהמשתמש סיפק. ‫Chrome יחפש חבילת shippingAddress לא ריקה עם countryCode תקין וישלח updatePaymentDetails עם הודעת השגיאה הבאה באמצעות callback.updateWith אם האימות ייכשל.

'Payment app returned invalid shipping address in response.'

הודעת שגיאה על מצב לא תקין

אם Chrome ייתקל במצב לא תקין כשיתקבלו בקשות לשינוי, הוא יתקשר אל callback.updateWith עם חבילת updatePaymentDetails מצונזרת. החבילה תכיל רק את מפתח error עם "Invalid state". דוגמאות למצב לא תקף:

  • כשדפדפן Chrome עדיין ממתין לתגובה של המוכר לשינוי קודם (למשל, אירוע שינוי שמתרחש כרגע).
  • מזהה אפשרות המשלוח שסופק על ידי אפליקציית התשלום לא שייך לאף אחת מאפשרויות המשלוח שצוינו על ידי המוכר.

קבלת פרטי תשלום מעודכנים מהסוחר

Kotlin

override fun updateWith(updatedPaymentDetails: Bundle) {}

override fun paymentDetailsNotUpdated() {}

Java

@Override
public void updateWith(Bundle updatedPaymentDetails) {}

@Override
public void paymentDetailsNotUpdated() {}

updatedPaymentDetails הוא החבילה ששווה למילון PaymentRequestDetailsUpdate WebIDL והיא מכילה את המפתחות האופציונליים הבאים:

  • total – חבילה שמכילה את המפתחות currency ו-value. לשני המפתחות יש ערכי מחרוזת
  • shippingOptions – מערך הניתן להעברה של shipping options
  • error – מחרוזת שמכילה הודעת שגיאה כללית (למשל, אם changeShippingOption לא מספק מזהה חוקי של אפשרות משלוח)
  • stringifiedPaymentMethodErrors – מחרוזת JSON שמייצגת שגיאות אימות של אמצעי התשלום
  • addressErrors – חבילה עם מפתחות אופציונליים זהים ל-shipping address ולערכי מחרוזת. כל מפתח מייצג שגיאת אימות שקשורה לחלק המתאים של כתובת המשלוח.
  • modifiers – מערך של חבילות שאפשר להעביר אותן בין תהליכים, כל אחת עם השדה total והשדה methodData, שהם גם חבילות.

מפתח שלא מופיע מציין שהערך שלו לא השתנה.