مسار تطوير بطاقة "محفظة Google"

توفّر Google Wallet API مجموعة محدّدة مسبقًا من أنواع البطاقات التي تم تحسينها لحالات استخدام معيّنة، مثل بطاقات الهدايا وبطاقات صعود الطائرة وتذاكر حضور الفعاليات وغيرها. هناك أيضًا نوع بطاقة عامة مخصّص لحالات الاستخدام التي لا يتوفر فيها نوع بطاقة معيّن.

تهدف هذه المقالة إلى إطلاعك على الخطوات الأساسية المطلوبة لإنشاء بطاقة وإصدارها باستخدام Google Wallet API. هناك طرق متعددة لإنجاز بعض الخطوات المفصّلة أدناه، ولكن بشكل عام، يتم إنشاء جميع أنواع البطاقات باتّباع خطوات التطوير الأساسية نفسها.

للحصول على جولة تفصيلية حول إنشاء بطاقة، يمكنك الاطّلاع على أدلة الويب والرسائل الإلكترونية والرسائل القصيرة أو تطبيقات Android.

الغرض منه

تحدد فئة البطاقات مجموعة من الخصائص المشتركة بين عدة بطاقات، على غرار النموذج. على سبيل المثال، إذا كنت تُصدِر تذاكر لفعالية، ستحدّد "فئة البطاقات" الحقول نفسها في جميع التذاكر، مثل اسم الفعالية وتاريخها ووقتها.

يجب أن تشير كل بطاقة تُصدرها إلى فئة بطاقات. عليك أيضًا تخصيص معرّف فريد لكل فئة بطاقات تنشئها، بحيث يتم استخدامه كمرجع عند إنشاء البطاقات.

كيفية إجراء ذلك

يتم تحديد فئة البطاقات بتنسيق JSON ويمكن إنشاؤها باستخدام Google Wallet REST API أو حزمة تطوير البرامج (SDK) لنظام التشغيل Android أو في Google Wallet Business Console.

عرض أمثلة لفئة البطاقات

{
  "id": "ISSUER_ID.EVENT_CLASS_ID",
  "issuerName": "[TEST ONLY] Heraldic Event",
  "localizedIssuerName": {
    "defaultValue": {
      "language": "en-US",
      "value": "[TEST ONLY] Heraldic Event"
    }
  },
  "logo": {
    "sourceUri": {
      "uri": "https://images.unsplash.com/photo-1475721027785-f74eccf877e2?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=660&h=660"
    },
    "contentDescription": {
      "defaultValue": {
        "language": "en-US",
        "value": "LOGO_IMAGE_DESCRIPTION"
      }
    }
  },
  "eventName": {
    "defaultValue": {
      "language": "en-US",
      "value": "Google Live"
    }
  },
  "venue": {
    "name": {
      "defaultValue": {
        "language": "en-US",
        "value": "Shoreline Amphitheater"
      }
    },
    "address": {
      "defaultValue": {
        "language": "en-US",
        "value": "ADDRESS_OF_THE_VENUE"
      }
    }
  },
  "dateTime": {
    "start": "2023-04-12T11:30"
  },
  "reviewStatus": "UNDER_REVIEW",
  "hexBackgroundColor": "#264750",
  "heroImage": {
    "sourceUri": {
      "uri": "https://images.unsplash.com/photo-1501281668745-f7f57925c3b4?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1032&h=336"
    },
    "contentDescription": {
      "defaultValue": {
        "language": "en-US",
        "value": "HERO_IMAGE_DESCRIPTION"
      }
    }
  }
}
    

الغرض منه

يحدّد عنصر التمرير خصائص البطاقة الفريدة التي سيتم إصدارها لمستخدم محدّد. على سبيل المثال، يحدّد عنصر البطاقات لتذكرة فعالية ما الحقول الفريدة لهذه التذكرة، مثل رقم المقعد أو رمز الاستجابة السريعة لتلك التذكرة.

عندما يتم إنشاء عنصر من "البطاقات"، تخزّن واجهة برمجة التطبيقات Google Wallet API بطاقة جديدة وتربطها بحساب "جهة الإصدار" الخاص بك. هذه البطاقة المخزّنة هي مجموعة من الخصائص الفريدة لـ "عنصر البطاقات" وخصائص النموذج لفئة البطاقات المرتبطة.

ويجب أيضًا تخصيص معرّف فريد لكل عنصر من عناصر البطاقات يتم استخدامه للإشارة إليه عند إصدار بطاقة.

كيفية إجراء ذلك

"عنصر البطاقات" هو عبارة عن تنسيق JSON يمكن إنشاؤه باستخدام Google Wallet REST API أو حزمة تطوير البرامج (SDK) لنظام التشغيل Android.

عرض أمثلة على عنصر البطاقات

{
  "id": "ISSUER_ID.OBJECT_ID",
  "classId": "ISSUER_ID.EVENT_CLASS_ID",
  "state": "ACTIVE",
  "seatInfo": {
    "seat": {
      "defaultValue": {
        "language": "en-us",
        "value": "5"
      }
    },
    "row": {
      "defaultValue": {
        "language": "en-us",
        "value": "G"
      }
    },
    "section": {
      "defaultValue": {
        "language": "en-us",
        "value": "40"
      }
    },
    "gate": {
      "defaultValue": {
        "language": "en-us",
        "value": "3A"
      }
    }
  },
  "barcode": {
    "type": "QR_CODE",
    "value": "BARCODE_VALUE",
    "alternateText": ""
  }
}
    

الغرض منه

لإصدار بطاقة لمستخدم، يجب ترميز "فئة البطاقات" و"عنصر البطاقات" بتنسيق JSON المميّز على الويب (JWT). تنسيق JWT هو معيار شائع ومفتوح لتمثيل المطالبات بين طرفين. في حال إصدار البطاقات باستخدام Google Wallet API، يتم استخدام نماذج JWT لإرسال ادّعاء بأنّ المستخدم لديه حق الوصول إلى بطاقة معيّنة مرتبطة بحساب جهة الإصدار الخاص بك.

عند إرسال رمز JWT إلى Google Wallet API، يتم استخدام البيانات المشفرة لتحديد بطاقة معيّنة وإصدارها للمستخدم. إذا سبق أن تم إصدار البطاقة، تتيح هذه البيانات أيضًا لواجهة Google Wallet API تحديد أنّ البطاقة مكرّرة بحيث لا تتم إضافتها إلى "محفظة Google" لدى المستخدم أكثر من مرة.

كيفية إجراء ذلك

يتم تحديد JWT بتنسيق JSON استنادًا إلى مواصفات JWT. لتحديد مستند JWT لإصدار بطاقة باستخدام Google Wallet API، عليك تقديم معلومات عن البطاقة التي تريد إصدارها في سمة payload الخاصة بتطبيق JWT.

عرض مثال JWT

{
  "iss": "issuer@example.com",
  "aud": "google",
  "typ": "savetowallet",
  "iat": 1696877738,
  "origins": [
    "www.example.com"
  ],
  "payload": {
    "eventTicketObjects": [
      {
        "id": "ISSUER_ID.LOYALTY_OBJECT_SUFFIX"
      }
    ]
  }
}
    

الغرض منه

يجب توقيع كل نماذج JWT التي يتم إرسالها إلى Google Wallet API لإصدار بطاقة باستخدام بيانات الاعتماد التي قدَّمتها سابقًا في Google Wallet Business Console. يستخدم التوقيع بيانات الاعتماد الخاصة بك لتشفير مستند JWT للحفاظ على أمان بطاقاتك والسماح لواجهة Google Wallet API بالمصادقة على أنّ تفاصيل البطاقة المرمّزة فيها صالحة ومرتبطة بحساب جهة الإصدار الخاص بك.

كيفية إجراء ذلك

توفّر مكتبات عملاء "محفظة Google" وحزمة تطوير البرامج (SDK) لنظام التشغيل Android طرقًا ملائمة لتوقيع ملفات JWT. هناك أيضًا العديد من المكتبات المفتوحة المصدر المتاحة التي تعالج تعقيدات توقيع الرموز لتختار من بينها.

بالنسبة إلى المستخدمين الذين يستخدمون Google Wallet REST API لإصدار البطاقات، يتم توقيع JWT باستخدام مفتاح حساب على Google Cloud Service. بالنسبة إلى مستخدمي حزمة تطوير البرامج (SDK) لنظام التشغيل Android في "محفظة Google"، ستتعامل حزمة SDK تلقائيًا مع توقيع JWT باستخدام بصمة الإصبع SHA-1 لشهادة توقيع التطبيق.

لحماية بيانات الاعتماد، يجب تسجيل JWT فقط على الخادم أو باستخدام حزمة تطوير البرامج (SDK) لنظام التشغيل Android في "محفظة Google" في تطبيقك.

عرض مثال لتوقيع الرمز

Java

  // Create the JWT as a HashMap object
  HashMap claims = new HashMap();
  claims.put("iss", ((ServiceAccountCredentials) credentials).getClientEmail());
  claims.put("aud", "google");
  claims.put("origins", Arrays.asList("www.example.com"));
  claims.put("typ", "savetowallet");

  // Create the Google Wallet payload and add to the JWT
  HashMap payload = new HashMap();
  payload.put("eventTicketObjects", Arrays.asList(newObject));
  claims.put("payload", payload);

  // Google Cloud service account credentials are used to sign the JWT
  Algorithm algorithm =
      Algorithm.RSA256(
          null, (RSAPrivateKey) ((ServiceAccountCredentials) credentials).getPrivateKey());
  String token = JWT.create().withPayload(claims).sign(algorithm);
        

Node.JS

  // Create the JWT claims
  let claims = {
    iss: this.credentials.client_email,
    aud: 'google',
    origins: ['www.example.com'],
    typ: 'savetowallet',
    payload: {
      eventTicketObjects: [newObject]
    },
  };

  // The service account credentials are used to sign the JWT
  let token = jwt.sign(claims, this.credentials.private_key, { algorithm: 'RS256' });
        

Python

  # Create the JWT claims
  claims = {
      'iss': self.credentials.service_account_email,
      'aud': 'google',
      'origins': ['www.example.com'],
      'typ': 'savetowallet',
      'payload': {
          # The listed classes and objects will be created
          'eventTicketObjects': [new_object]
      }
  }

  # The service account credentials are used to sign the JWT
  signer = crypt.RSASigner.from_service_account_file(self.key_file_path)
  token = jwt.encode(signer, claims).decode('utf-8')
        

الغرض منه

بعد إنشاء مستند JWT موقَّع، ستصبح جاهزًا لإصدار بطاقتك إلى مستخدم من مستخدمي "محفظة Google". ويتم ذلك من خلال عرض زر "الإضافة إلى محفظة Google" أو الرابط أمام المستخدم. عندما ينقر المستخدم على الزر أو الرابط التشعّبي، يتم إرسال رمز JWT الموقَّع إلى Google Wallet API، وبعد ذلك يفك تشفيره باستخدام بيانات الاعتماد المحفوظة. بعد مصادقة توقيع JWT، سيتم إصدار البطاقة للمستخدم لحفظها في "محفظة Google".

كيفية إجراء ذلك

لإنشاء زر "إضافة إلى محفظة Google" لأحد تطبيقات Android، استخدم حزمة تطوير البرامج (SDK) لمحفظة Google لنظام التشغيل Android، والتي توفر طرقًا لإنشاء الزر. بالنسبة إلى جميع المنصات الأخرى، بما في ذلك الويب والرسائل الإلكترونية والرسائل النصية، أنشِئ رابطًا تشعّبيًا بالتنسيق https://pay.google.com/gp/v/save/<signed_jwt>. حيثما أمكن، من الأفضل تقديم هذا الرابط إلى المستخدم كزر "إضافة إلى محفظة Google".

لمزيد من المعلومات حول استخدام زر "الإضافة إلى محفظة Google"، يُرجى الاطّلاع على إرشادات العلامة التجارية في Google Wallet API.

عرض مثال الرمز البرمجي

  https://pay.google.com/gp/v/save/<signed_jwt>
        

حزمة تطوير البرامج (SDK) لنظام التشغيل Android

  private lateinit var walletClient: PayClient
  private val addToGoogleWalletRequestCode = 1000
  private lateinit var addToGoogleWalletButton: View

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    walletClient = Pay.getClient(this)
    addToGoogleWalletButton.setOnClickListener {
      walletClient.savePasses(newObjectJson, this, addToGoogleWalletRequestCode)
    }
  }
        

بعد أن يحفظ المستخدم البطاقة الصادرة، ستظهر في تطبيق "محفظة Google" مع أي بطاقات أخرى سبق أن حفظها.

إنشاء كائنات البطاقات وفئات البطاقات في JWT

يمكن إنشاء فئات البطاقات وعناصر البطاقات مسبقًا باستخدام واجهة برمجة التطبيقات REST API في Google Wallet أو حزمة تطوير البرامج (SDK) لنظام التشغيل Android. بعد إنشاء البطاقات، يتم استخدامها لإصدار البطاقات من خلال الإشارة إلى مستند تعريفها.

بدلاً من ذلك، يمكنك أيضًا إنشاء فئات البطاقات وكائنات البطاقات "في الوقت المناسب" من خلال تضمين ملف JSON الخاص بها مباشرةً في JWT الذي يُستخدم لإصدار البطاقة إلى المستخدم. بهذه الطريقة، تنشئ واجهة Google Wallet API "فئات البطاقات" و"كائنات البطاقات" عندما يتم إرسال JWT الموقَّع باستخدام زر أو رابط "الإضافة إلى Google Wallet".

على سبيل المثال، يوضِّح ما يلي عنصر JWT يتضمّن "فئة بطاقات" و"عنصر بطاقات" جديدَين تم تحديدهما باستخدام السمتَين payload.eventTicketClasses وpayload.eventTicketObjects. يُرجى العلم أنّ هذه السمات هي صفائف، وبالتالي يمكنها قبول واحدة أو أكثر من "فئات البطاقات" أو "عناصر البطاقات". ويمكنك أيضًا تحديد عنصر بطاقات جديد في JWT يشير إلى فئة بطاقات حالية من خلال رقم التعريف الخاص به.

عرض مثال JWT

  {
    "iss": "issuer@example.com",
    "aud": "google",
    "typ": "savetowallet",
    "iat": 1696877738,
    "origins": [
      "www.example.com"
    ],
    "payload": {
      "eventTicketClasses": [{
        "id": "ISSUER_ID.EVENT_CLASS_ID",
        "issuerName": "[TEST ONLY] Heraldic Event",
        "localizedIssuerName": {
          "defaultValue": {
            "language": "en-US",
            "value": "[TEST ONLY] Heraldic Event"
          }
        },
        "logo": {
          "sourceUri": {
            "uri": "https://images.unsplash.com/photo-1475721027785-f74eccf877e2?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=660&h=660"
          },
          "contentDescription": {
            "defaultValue": {
              "language": "en-US",
              "value": "LOGO_IMAGE_DESCRIPTION"
            }
          }
        },
        "eventName": {
          "defaultValue": {
            "language": "en-US",
            "value": "Google Live"
          }
        },
        "venue": {
          "name": {
            "defaultValue": {
              "language": "en-US",
              "value": "Shoreline Amphitheater"
            }
          },
          "address": {
            "defaultValue": {
              "language": "en-US",
              "value": "ADDRESS_OF_THE_VENUE"
            }
          }
        },
        "dateTime": {
          "start": "2023-04-12T11:30"
        },
        "reviewStatus": "UNDER_REVIEW",
        "hexBackgroundColor": "#264750",
        "heroImage": {
          "sourceUri": {
            "uri": "https://images.unsplash.com/photo-1501281668745-f7f57925c3b4?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1032&h=336"
          },
          "contentDescription": {
            "defaultValue": {
              "language": "en-US",
              "value": "HERO_IMAGE_DESCRIPTION"
            }
          }
        }
      }],
      "eventTicketObjects": [{
        "id": "ISSUER_ID.OBJECT_ID",
        "classId": "ISSUER_ID.EVENT_CLASS_ID",
        "state": "ACTIVE",
        "seatInfo": {
          "seat": {
            "defaultValue": {
              "language": "en-us",
              "value": "5"
            }
          },
          "row": {
            "defaultValue": {
              "language": "en-us",
              "value": "G"
            }
          },
          "section": {
            "defaultValue": {
              "language": "en-us",
              "value": "40"
            }
          },
          "gate": {
            "defaultValue": {
              "language": "en-us",
              "value": "3A"
            }
          }
        },
        "barcode": {
          "type": "QR_CODE",
          "value": "BARCODE_VALUE",
          "alternateText": ""
        }
      }]
    }
  }