نکات عملکردی

این سند برخی از تکنیک ها را پوشش می دهد که می توانید برای بهبود عملکرد برنامه خود از آنها استفاده کنید. در برخی موارد، نمونه هایی از سایر APIها یا APIهای عمومی برای نشان دادن ایده های ارائه شده استفاده می شود. با این حال، همان مفاهیم برای Google Wallet API قابل اعمال است.

فشرده سازی با استفاده از gzip

یک راه آسان و راحت برای کاهش پهنای باند مورد نیاز برای هر درخواست، فعال کردن فشرده‌سازی gzip است. اگرچه این امر به زمان اضافی CPU برای فشرده سازی نتایج نیاز دارد، اما معاوضه با هزینه های شبکه معمولاً آن را بسیار ارزشمند می کند.

برای دریافت پاسخ کدگذاری شده با gzip، باید دو کار انجام دهید: یک هدر Accept-Encoding تنظیم کنید، و عامل کاربری خود را طوری تغییر دهید که شامل رشته gzip باشد. در اینجا نمونه ای از هدرهای HTTP که به درستی شکل گرفته اند برای فعال کردن فشرده سازی gzip آورده شده است:

Accept-Encoding: gzip
User-Agent: my program (gzip)

کار با منابع جزئی

راه دیگر برای بهبود عملکرد تماس‌های API، ارسال و دریافت تنها بخشی از داده‌هایی است که به آن‌ها علاقه دارید. این به برنامه شما امکان می‌دهد از انتقال، تجزیه و ذخیره فیلدهای غیر ضروری جلوگیری کند، بنابراین می‌تواند از منابعی از جمله شبکه استفاده کند. CPU و حافظه کارآمدتر.

دو نوع درخواست جزئی وجود دارد:

  • پاسخ جزئی : درخواستی که در آن مشخص می‌کنید کدام فیلدها در پاسخ گنجانده شوند (از پارامتر درخواست fields استفاده کنید).
  • Patch : یک درخواست به روز رسانی که در آن فقط فیلدهایی را که می خواهید تغییر دهید ارسال می کنید (از فعل PATCH HTTP استفاده کنید).

جزئیات بیشتر در مورد درخواست های جزئی در بخش های بعدی ارائه شده است.

پاسخ نسبی

به طور پیش فرض، سرور پس از پردازش درخواست ها، نمایش کامل یک منبع را پس می فرستد. برای عملکرد بهتر، می‌توانید از سرور بخواهید فقط فیلدهایی را که واقعاً به آن نیاز دارید ارسال کند و در عوض پاسخی جزئی دریافت کنید.

برای درخواست پاسخ جزئی، از پارامتر درخواست fields استفاده کنید تا فیلدهایی را که می خواهید برگردانید مشخص کنید. می توانید از این پارامتر با هر درخواستی که داده های پاسخ را برمی گرداند استفاده کنید.

توجه داشته باشید که پارامتر fields فقط بر داده‌های پاسخ تأثیر می‌گذارد. بر روی داده هایی که باید ارسال کنید، در صورت وجود، تأثیری نمی گذارد. برای کاهش حجم داده‌ای که هنگام اصلاح منابع ارسال می‌کنید، از درخواست وصله استفاده کنید.

مثال

مثال زیر استفاده از پارامتر fields با یک API "دمو" عمومی (تخیلی) نشان می دهد.

درخواست ساده: این درخواست HTTP GET پارامتر fields را حذف می کند و منبع کامل را برمی گرداند.

https://www.googleapis.com/demo/v1

پاسخ منبع کامل: داده‌های کامل منبع شامل فیلدهای زیر است، همراه با بسیاری دیگر که برای اختصار حذف شده‌اند.

{
  "kind": "demo",
  ...
  "items": [
  {
    "title": "First title",
    "comment": "First comment.",
    "characteristics": {
      "length": "short",
      "accuracy": "high",
      "followers": ["Jo", "Will"],
    },
    "status": "active",
    ...
  },
  {
    "title": "Second title",
    "comment": "Second comment.",
    "characteristics": {
      "length": "long",
      "accuracy": "medium"
      "followers": [ ],
    },
    "status": "pending",
    ...
  },
  ...
  ]
}

درخواست پاسخ جزئی: درخواست زیر برای همین منبع از پارامتر fields استفاده می‌کند تا میزان داده‌های برگشتی را به میزان قابل توجهی کاهش دهد.

https://www.googleapis.com/demo/v1?fields=kind,items(title,characteristics/length)

پاسخ جزئی: در پاسخ به درخواست بالا، سرور پاسخی را ارسال می‌کند که فقط حاوی اطلاعات نوع به همراه یک آرایه موارد کاهش‌یافته است که فقط شامل عنوان HTML و اطلاعات مشخصه طول در هر مورد است.

200 OK
{
  "kind": "demo",
  "items": [{
    "title": "First title",
    "characteristics": {
      "length": "short"
    }
  }, {
    "title": "Second title",
    "characteristics": {
      "length": "long"
    }
  },
  ...
  ]
}

توجه داشته باشید که پاسخ یک شی JSON است که فقط شامل فیلدهای انتخاب شده و اشیاء والد محصور آنها می شود.

جزئیات در مورد نحوه قالب بندی پارامتر fields در ادامه پوشش داده می شود و به دنبال آن جزئیات بیشتری در مورد آنچه دقیقاً در پاسخ برگردانده می شود، ارائه می شود.

خلاصه نحو پارامتر فیلدها

فرمت مقدار پارامتر درخواست fields بر اساس نحو XPath است. نحو پشتیبانی شده در زیر خلاصه شده است و نمونه های اضافی در بخش زیر ارائه شده است.

  • از یک لیست جدا شده با کاما برای انتخاب چندین فیلد استفاده کنید.
  • از a/b برای انتخاب فیلد b که در فیلد a تودرتو است استفاده کنید. از a/b/c برای انتخاب یک فیلد c تو در تو در b استفاده کنید.

    استثنا: برای پاسخ‌های API که از بسته‌بندی‌های «داده» استفاده می‌کنند، که در آن پاسخ درون یک شی data که شبیه data: { ... } ، « data » را در مشخصات fields لحاظ نکنید. گنجاندن شی داده با مشخصات فیلدهایی مانند data/a/b باعث ایجاد خطا می شود. در عوض، فقط از مشخصات fields مانند a/b استفاده کنید.

  • از یک انتخابگر فرعی برای درخواست مجموعه ای از فیلدهای فرعی خاص از آرایه ها یا اشیاء با قرار دادن عبارات در پرانتز " ( ) " استفاده کنید.

    برای مثال: fields=items(id,author/email) فقط شناسه مورد و ایمیل نویسنده را برای هر عنصر در آرایه آیتم ها برمی گرداند. شما همچنین می توانید یک زیر فیلد را مشخص کنید که در آن fields=items(id) معادل fields=items/id باشد.

  • در صورت نیاز از حروف عام در انتخاب زمینه استفاده کنید.

    به عنوان مثال: fields=items/pagemap/* تمام اشیاء موجود در نقشه صفحه را انتخاب می کند.

نمونه های بیشتری از استفاده از پارامتر فیلدها

مثال‌های زیر شامل توضیحاتی در مورد چگونگی تأثیر مقدار پارامتر fields بر پاسخ است.

توجه: مانند تمام مقادیر پارامتر پرس و جو، مقدار پارامتر fields باید با URL رمزگذاری شده باشد. برای خوانایی بهتر، مثال های این سند رمزگذاری را حذف می کنند.

فیلدهایی را که می خواهید برگردانید شناسایی کنید یا فیلدهایی را انتخاب کنید.
مقدار پارامتر درخواست fields لیستی از فیلدها است که با کاما از هم جدا شده اند و هر فیلد نسبت به ریشه پاسخ مشخص می شود. بنابراین، اگر شما یک عملیات لیست را انجام می دهید، پاسخ یک مجموعه است و به طور کلی شامل مجموعه ای از منابع است. اگر عملیاتی را انجام می دهید که یک منبع را برمی گرداند، فیلدهایی نسبت به آن منبع مشخص می شوند. اگر فیلدی که انتخاب می‌کنید یک آرایه باشد (یا بخشی از آن باشد)، سرور بخش انتخاب شده از تمام عناصر آرایه را برمی‌گرداند.

در اینجا چند نمونه در سطح مجموعه آورده شده است:
نمونه ها اثر
items همه عناصر موجود در آرایه آیتم ها، از جمله تمام فیلدهای هر عنصر، اما هیچ فیلد دیگری را برمی گرداند.
etag,items هم فیلد etag و هم همه عناصر موجود در آرایه آیتم ها را برمی گرداند.
items/title فقط فیلد title برای همه عناصر موجود در آرایه آیتم ها برمی گرداند.

هر زمان که یک فیلد تودرتو برگردانده می شود، پاسخ شامل اشیاء والد محصور می شود. فیلدهای والد هیچ فیلد فرزند دیگری را شامل نمی شود مگر اینکه آنها نیز صریحاً انتخاب شده باشند.
context/facets/label فقط فیلد label برای همه اعضای آرایه facets برمی‌گرداند که خود در زیر شیء context قرار دارد.
items/pagemap/*/title برای هر عنصر در آرایه آیتم‌ها، فقط فیلد title (در صورت وجود) همه اشیایی را که فرزندان pagemap هستند برمی‌گرداند.

در اینجا چند نمونه در سطح منبع آورده شده است:
نمونه ها اثر
title فیلد title منبع درخواستی را برمی گرداند.
author/uri فیلد فرعی uri شی author را در منبع درخواستی برمی گرداند.
links/*/href
فیلد href همه اشیایی که فرزند links هستند را برمی گرداند.
فقط بخش‌هایی از فیلدهای خاص را با استفاده از انتخاب‌های فرعی درخواست کنید.
به طور پیش فرض، اگر درخواست شما فیلدهای خاصی را مشخص کند، سرور اشیاء یا عناصر آرایه را به طور کامل برمی گرداند. می توانید پاسخی را مشخص کنید که فقط شامل قسمت های فرعی خاصی باشد. شما این کار را با استفاده از نحو انتخاب فرعی " ( ) " مانند مثال زیر انجام می دهید.
مثال اثر
items(title,author/uri) فقط مقادیر title و uri نویسنده را برای هر عنصر در آرایه آیتم ها برمی گرداند.

رسیدگی به پاسخ های جزئی

پس از اینکه سرور یک درخواست معتبر که شامل پارامتر پرس و جو fields است را پردازش کرد، یک کد وضعیت HTTP 200 OK را به همراه داده های درخواستی ارسال می کند. اگر پارامتر پرس و جو fields دارای خطا باشد یا در غیر این صورت نامعتبر باشد، سرور یک کد وضعیت 400 Bad Request را به همراه یک پیام خطایی که به کاربر می‌گوید در انتخاب فیلدهایش چه مشکلی داشته است (به عنوان مثال، "Invalid field selection a/b" . "Invalid field selection a/b" ).

در اینجا نمونه پاسخ جزئی نشان داده شده در بخش مقدماتی بالا است. درخواست از پارامتر fields برای تعیین اینکه کدام فیلدها را برگرداند استفاده می کند.

https://www.googleapis.com/demo/v1?fields=kind,items(title,characteristics/length)

پاسخ جزئی به این صورت است:

200 OK
{
  "kind": "demo",
  "items": [{
    "title": "First title",
    "characteristics": {
      "length": "short"
    }
  }, {
    "title": "Second title",
    "characteristics": {
      "length": "long"
    }
  },
  ...
  ]
}

توجه: برای APIهایی که از پارامترهای پرس و جو برای صفحه بندی داده ها پشتیبانی می کنند (مثلاً maxResults و nextPageToken )، از این پارامترها برای کاهش نتایج هر پرس و جو به اندازه قابل مدیریت استفاده کنید. در غیر این صورت، افزایش عملکرد ممکن با پاسخ نسبی ممکن است محقق نشود.

پچ (به روز رسانی جزئی)

همچنین می توانید هنگام اصلاح منابع از ارسال داده های غیر ضروری خودداری کنید. برای ارسال داده های به روز شده فقط برای فیلدهای خاصی که در حال تغییر آن هستید، از فعل HTTP PATCH استفاده کنید. معنای وصله توضیح داده شده در این سند متفاوت (و ساده تر) از آنها برای اجرای قدیمی تر، GData به روز رسانی جزئی است.

مثال کوتاه زیر نشان می‌دهد که چگونه استفاده از وصله، داده‌هایی را که برای ایجاد یک به‌روزرسانی کوچک باید ارسال کنید، به حداقل می‌رساند.

مثال

این مثال یک درخواست وصله ساده را نشان می دهد تا فقط عنوان یک منبع API "دمو" عمومی (تخیلی) را به روز کند. این منبع همچنین دارای یک نظر، مجموعه‌ای از ویژگی‌ها، وضعیت و بسیاری فیلدهای دیگر است، اما این درخواست فقط فیلد title را ارسال می‌کند، زیرا این تنها فیلدی است که اصلاح می‌شود:

PATCH https://www.googleapis.com/demo/v1/324
Authorization: Bearer your_auth_token
Content-Type: application/json

{
  "title": "New title"
}

پاسخ:

200 OK
{
  "title": "New title",
  "comment": "First comment.",
  "characteristics": {
    "length": "short",
    "accuracy": "high",
    "followers": ["Jo", "Will"],
  },
  "status": "active",
  ...
}

سرور یک کد وضعیت 200 OK را به همراه نمایش کامل منبع به روز شده برمی گرداند. از آنجایی که فقط قسمت title در درخواست وصله گنجانده شده است، این تنها مقداری است که با قبل متفاوت است.

توجه: اگر از پارامتر fields پاسخ جزئی در ترکیب با پچ استفاده کنید، می‌توانید کارایی درخواست‌های به‌روزرسانی خود را حتی بیشتر افزایش دهید. درخواست پچ فقط اندازه درخواست را کاهش می دهد. پاسخ جزئی اندازه پاسخ را کاهش می دهد. بنابراین برای کاهش حجم داده های ارسالی در هر دو جهت، از یک درخواست پچ با پارامتر fields استفاده کنید.

معناشناسی درخواست پچ

بدنه درخواست وصله فقط شامل فیلدهای منبعی است که می خواهید تغییر دهید. هنگامی که یک فیلد را مشخص می‌کنید، باید هر شیء والد محصور کننده را نیز درج کنید، همانطور که والدین محصور کننده با یک پاسخ جزئی برگردانده می‌شوند. داده‌های اصلاح‌شده‌ای که ارسال می‌کنید، در صورت وجود، در داده‌های شی والد ادغام می‌شوند.

  • افزودن: برای افزودن فیلدی که قبلاً وجود ندارد، فیلد جدید و مقدار آن را مشخص کنید.
  • Modify: برای تغییر مقدار یک فیلد موجود، فیلد را مشخص کرده و آن را به مقدار جدید تنظیم کنید.
  • حذف: برای حذف یک فیلد، فیلد را مشخص کرده و آن را روی null قرار دهید. به عنوان مثال، "comment": null . همچنین می‌توانید کل یک شی (اگر قابل تغییر باشد) را با تنظیم آن بر روی null حذف کنید. اگر از Java API Client Library استفاده می کنید، به جای آن از Data.NULL_STRING استفاده کنید. برای جزئیات، JSON null را ببینید.

نکته در مورد آرایه‌ها: درخواست‌های وصله‌ای که حاوی آرایه‌ها هستند، آرایه موجود را با آرایه‌ای که ارائه می‌کنید جایگزین می‌کنند. شما نمی توانید موارد را در یک آرایه به صورت تکه ای تغییر دهید، اضافه یا حذف کنید.

استفاده از وصله در چرخه خواندن، اصلاح و نوشتن

این می تواند تمرین مفیدی باشد که با بازیابی یک پاسخ جزئی با داده هایی که می خواهید تغییر دهید شروع کنید. این امر به ویژه برای منابعی که از ETags استفاده می‌کنند مهم است، زیرا برای به‌روزرسانی موفقیت‌آمیز منبع، باید مقدار ETag فعلی را در هدر HTTP If-Match ارائه دهید. پس از دریافت داده‌ها، می‌توانید مقادیری را که می‌خواهید تغییر دهید تغییر دهید و نمایش جزئی اصلاح شده را با یک درخواست وصله ارسال کنید. در اینجا مثالی وجود دارد که فرض می کند منبع دمو از ETags استفاده می کند:

GET https://www.googleapis.com/demo/v1/324?fields=etag,title,comment,characteristics
Authorization: Bearer your_auth_token

این پاسخ جزئی است:

200 OK
{
  "etag": "ETagString"
  "title": "New title"
  "comment": "First comment.",
  "characteristics": {
    "length": "short",
    "level": "5",
    "followers": ["Jo", "Will"],
  }
}

درخواست پچ زیر بر اساس آن پاسخ است. همانطور که در زیر نشان داده شده است، از پارامتر fields نیز برای محدود کردن داده های بازگشتی در پاسخ وصله استفاده می کند:

PATCH https://www.googleapis.com/demo/v1/324?fields=etag,title,comment,characteristics
Authorization: Bearer your_auth_token
Content-Type: application/json
If-Match: "ETagString"
{
  "etag": "ETagString"
  "title": "",                  /* Clear the value of the title by setting it to the empty string. */
  "comment": null,              /* Delete the comment by replacing its value with null. */
  "characteristics": {
    "length": "short",
    "level": "10",              /* Modify the level value. */
    "followers": ["Jo", "Liz"], /* Replace the followers array to delete Will and add Liz. */
    "accuracy": "high"          /* Add a new characteristic. */
  },
}

سرور با یک کد وضعیت HTTP 200 OK و نمایش بخشی از منبع به روز شده پاسخ می دهد:

200 OK
{
  "etag": "newETagString"
  "title": "",                 /* Title is cleared; deleted comment field is missing. */
  "characteristics": {
    "length": "short",
    "level": "10",             /* Value is updated.*/
    "followers": ["Jo" "Liz"], /* New follower Liz is present; deleted Will is missing. */
    "accuracy": "high"         /* New characteristic is present. */
  }
}

ساخت درخواست پچ به طور مستقیم

برای برخی از درخواست‌های وصله، باید آنها را بر اساس داده‌هایی که قبلاً بازیابی کرده‌اید، قرار دهید. به عنوان مثال، اگر می خواهید یک آیتم را به یک آرایه اضافه کنید و نمی خواهید هیچ یک از عناصر آرایه موجود را از دست بدهید، ابتدا باید داده های موجود را دریافت کنید. به طور مشابه، اگر یک API از ETags استفاده می کند، باید مقدار ETag قبلی را همراه با درخواست خود ارسال کنید تا منبع با موفقیت به روز شود.

توجه: می‌توانید از هدر HTTP "If-Match: *" برای وادار کردن یک وصله در هنگام استفاده از تگ‌های ET استفاده کنید. اگر این کار را انجام دهید، نیازی به خواندن قبل از نوشتن ندارید.

با این حال، برای موقعیت‌های دیگر، می‌توانید درخواست پچ را مستقیماً بدون بازیابی داده‌های موجود ایجاد کنید. به عنوان مثال، می توانید به راحتی یک درخواست وصله تنظیم کنید که یک فیلد را به یک مقدار جدید به روز می کند یا یک فیلد جدید اضافه می کند. در اینجا یک مثال است:

PATCH https://www.googleapis.com/demo/v1/324?fields=comment,characteristics
Authorization: Bearer your_auth_token
Content-Type: application/json

{
  "comment": "A new comment",
  "characteristics": {
    "volume": "loud",
    "accuracy": null
  }
}

با این درخواست، اگر فیلد نظر دارای یک مقدار موجود باشد، مقدار جدید آن را بازنویسی می کند. در غیر این صورت به مقدار جدید تنظیم می شود. به طور مشابه، اگر مشخصه حجمی وجود داشته باشد، مقدار آن بازنویسی می شود. اگر نه، ایجاد می شود. فیلد دقت، در صورت تنظیم، حذف می شود.

مدیریت پاسخ به یک پچ

پس از پردازش یک درخواست پچ معتبر، API یک کد پاسخ HTTP 200 OK را همراه با نمایش کامل منبع اصلاح شده برمی گرداند. اگر ETag ها توسط API استفاده شوند، سرور مقادیر ETag را هنگامی که با موفقیت یک درخواست وصله را پردازش می کند، به روز می کند، درست مانند PUT .

درخواست وصله کل نمایش منبع را برمی گرداند مگر اینکه از پارامتر fields برای کاهش مقدار داده ای که برمی گرداند استفاده کنید.

اگر یک درخواست وصله منجر به یک وضعیت منبع جدید شود که از نظر نحوی یا معنایی نامعتبر است، سرور یک کد وضعیت HTTP 400 Bad Request یا 422 Unprocessable Entity را برمی گرداند و وضعیت منبع بدون تغییر باقی می ماند. به عنوان مثال، اگر سعی کنید مقدار یک فیلد ضروری را حذف کنید، سرور یک خطا را برمی‌گرداند.

هنگامی که فعل HTTP PATCH پشتیبانی نمی شود، نماد جایگزین کنید

اگر فایروال شما اجازه درخواست HTTP PATCH را نمی دهد، یک درخواست HTTP POST انجام دهید و هدر override را روی PATCH تنظیم کنید، مانند شکل زیر:

POST https://www.googleapis.com/...
X-HTTP-Method-Override: PATCH
...

تفاوت پچ و آپدیت

در عمل، وقتی داده‌هایی را برای درخواست به‌روزرسانی ارسال می‌کنید که از فعل HTTP PUT استفاده می‌کند، فقط باید آن فیلدهایی را ارسال کنید که ضروری یا اختیاری هستند. اگر مقادیری را برای فیلدهایی که توسط سرور تنظیم شده ارسال کنید، نادیده گرفته می شوند. اگرچه ممکن است این روش دیگری برای انجام به‌روزرسانی جزئی به نظر برسد، اما این رویکرد دارای محدودیت‌هایی است. با به‌روزرسانی‌هایی که از فعل HTTP PUT استفاده می‌کنند، اگر پارامترهای لازم را ارائه نکنید، درخواست با شکست مواجه می‌شود و اگر پارامترهای اختیاری را ارائه نکنید، داده‌های تنظیم‌شده قبلی را پاک می‌کند.

به همین دلیل استفاده از پچ بسیار ایمن تر است. شما فقط داده هایی را برای فیلدهایی که می خواهید تغییر دهید ارائه می دهید. فیلدهایی که حذف می کنید پاک نمی شوند. تنها استثنای این قانون در مورد عناصر یا آرایه‌های تکرار شونده رخ می‌دهد: اگر همه آنها را حذف کنید، همان‌طور که هستند باقی می‌مانند. اگر هر یک از آنها را تهیه کنید، کل مجموعه با مجموعه ای که ارائه می دهید جایگزین می شود.

درخواست‌های دسته‌ای به Google Wallet

Google Wallet API از تماس‌های دسته‌ای API با هم پشتیبانی می‌کند تا تعداد اتصالاتی را که یک کلاینت باید برقرار کند کاهش دهد. برای اطلاعات بیشتر در مورد درخواست دسته ای و ساختار پاسخ، جزئیات دسته را ببینید.

کد نمونه زیر درخواست های دسته بندی را نشان می دهد. مثال‌های جاوا و PHP از کتابخانه‌های Google Wallet برای ساده‌سازی ایجاد کلاس و شی استفاده می‌کنند.

جاوا

برای شروع ادغام خود در جاوا، به نمونه کدهای کامل ما در GitHub مراجعه کنید.

/**
 * Batch create Google Wallet objects from an existing class.
 *
 * @param issuerId The issuer ID being used for this request.
 * @param classSuffix Developer-defined unique ID for this pass class.
 */
public void batchCreateObjects(String issuerId, String classSuffix) throws IOException {
  // Create the batch request client
  BatchRequest batch = service.batch(new HttpCredentialsAdapter(credentials));

  // The callback will be invoked for each request in the batch
  JsonBatchCallback<EventTicketObject> callback =
      new JsonBatchCallback<EventTicketObject>() {
        // Invoked if the request was successful
        public void onSuccess(EventTicketObject response, HttpHeaders responseHeaders) {
          System.out.println("Batch insert response");
          System.out.println(response.toString());
        }

        // Invoked if the request failed
        public void onFailure(GoogleJsonError e, HttpHeaders responseHeaders) {
          System.out.println("Error Message: " + e.getMessage());
        }
      };

  // Example: Generate three new pass objects
  for (int i = 0; i < 3; i++) {
    // Generate a random object suffix
    String objectSuffix = UUID.randomUUID().toString().replaceAll("[^\\w.-]", "_");

    // See link below for more information on required properties
    // https://developers.google.com/wallet/tickets/events/rest/v1/eventticketobject
    EventTicketObject batchObject =
        new EventTicketObject()
            .setId(String.format("%s.%s", issuerId, objectSuffix))
            .setClassId(String.format("%s.%s", issuerId, classSuffix))
            .setState("ACTIVE")
            .setHeroImage(
                new Image()
                    .setSourceUri(
                        new ImageUri()
                            .setUri(
                                "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg"))
                    .setContentDescription(
                        new LocalizedString()
                            .setDefaultValue(
                                new TranslatedString()
                                    .setLanguage("en-US")
                                    .setValue("Hero image description"))))
            .setTextModulesData(
                    List.of(
                            new TextModuleData()
                                    .setHeader("Text module header")
                                    .setBody("Text module body")
                                    .setId("TEXT_MODULE_ID")))
            .setLinksModuleData(
                new LinksModuleData()
                    .setUris(
                        Arrays.asList(
                            new Uri()
                                .setUri("http://maps.google.com/")
                                .setDescription("Link module URI description")
                                .setId("LINK_MODULE_URI_ID"),
                            new Uri()
                                .setUri("tel:6505555555")
                                .setDescription("Link module tel description")
                                .setId("LINK_MODULE_TEL_ID"))))
            .setImageModulesData(
                    List.of(
                            new ImageModuleData()
                                    .setMainImage(
                                            new Image()
                                                    .setSourceUri(
                                                            new ImageUri()
                                                                    .setUri(
                                                                            "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg"))
                                                    .setContentDescription(
                                                            new LocalizedString()
                                                                    .setDefaultValue(
                                                                            new TranslatedString()
                                                                                    .setLanguage("en-US")
                                                                                    .setValue("Image module description"))))
                                    .setId("IMAGE_MODULE_ID")))
            .setBarcode(new Barcode().setType("QR_CODE").setValue("QR code value"))
            .setLocations(
                    List.of(
                            new LatLongPoint()
                                    .setLatitude(37.424015499999996)
                                    .setLongitude(-122.09259560000001)))
            .setSeatInfo(
                new EventSeat()
                    .setSeat(
                        new LocalizedString()
                            .setDefaultValue(
                                new TranslatedString().setLanguage("en-US").setValue("42")))
                    .setRow(
                        new LocalizedString()
                            .setDefaultValue(
                                new TranslatedString().setLanguage("en-US").setValue("G3")))
                    .setSection(
                        new LocalizedString()
                            .setDefaultValue(
                                new TranslatedString().setLanguage("en-US").setValue("5")))
                    .setGate(
                        new LocalizedString()
                            .setDefaultValue(
                                new TranslatedString().setLanguage("en-US").setValue("A"))))
            .setTicketHolderName("Ticket holder name")
            .setTicketNumber("Ticket number");

    service.eventticketobject().insert(batchObject).queue(batch, callback);
  }

  // Invoke the batch API calls
  batch.execute();
}

PHP

برای شروع ادغام خود در PHP، به نمونه کدهای کامل ما در GitHub مراجعه کنید.

/**
 * Batch create Google Wallet objects from an existing class.
 *
 * @param string $issuerId The issuer ID being used for this request.
 * @param string $classSuffix Developer-defined unique ID for the pass class.
 */
public function batchCreateObjects(string $issuerId, string $classSuffix)
{
  // Update the client to enable batch requests
  $this->client->setUseBatch(true);
  $batch = $this->service->createBatch();

  // Example: Generate three new pass objects
  for ($i = 0; $i < 3; $i++) {
    // Generate a random object suffix
    $objectSuffix = preg_replace('/[^\w.-]/i', '_', uniqid());

    // See link below for more information on required properties
    // https://developers.google.com/wallet/tickets/events/rest/v1/eventticketobject
    $batchObject = new EventTicketObject([
      'id' => "{$issuerId}.{$objectSuffix}",
      'classId' => "{$issuerId}.{$classSuffix}",
      'state' => 'ACTIVE',
      'heroImage' => new Image([
        'sourceUri' => new ImageUri([
          'uri' => 'https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg'
        ]),
        'contentDescription' => new LocalizedString([
          'defaultValue' => new TranslatedString([
            'language' => 'en-US',
            'value' => 'Hero image description'
          ])
        ])
      ]),
      'textModulesData' => [
        new TextModuleData([
          'header' => 'Text module header',
          'body' => 'Text module body',
          'id' => 'TEXT_MODULE_ID'
        ])
      ],
      'linksModuleData' => new LinksModuleData([
        'uris' => [
          new Uri([
            'uri' => 'http://maps.google.com/',
            'description' => 'Link module URI description',
            'id' => 'LINK_MODULE_URI_ID'
          ]),
          new Uri([
            'uri' => 'tel:6505555555',
            'description' => 'Link module tel description',
            'id' => 'LINK_MODULE_TEL_ID'
          ])
        ]
      ]),
      'imageModulesData' => [
        new ImageModuleData([
          'mainImage' => new Image([
            'sourceUri' => new ImageUri([
              'uri' => 'http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg'
            ]),
            'contentDescription' => new LocalizedString([
              'defaultValue' => new TranslatedString([
                'language' => 'en-US',
                'value' => 'Image module description'
              ])
            ])
          ]),
          'id' => 'IMAGE_MODULE_ID'
        ])
      ],
      'barcode' => new Barcode([
        'type' => 'QR_CODE',
        'value' => 'QR code value'
      ]),
      'locations' => [
        new LatLongPoint([
          'latitude' => 37.424015499999996,
          'longitude' =>  -122.09259560000001
        ])
      ],
      'seatInfo' => new EventSeat([
        'seat' => new LocalizedString([
          'defaultValue' => new TranslatedString([
            'language' => 'en-US',
            'value' => '42'
          ])
        ]),
        'row' => new LocalizedString([
          'defaultValue' => new TranslatedString([
            'language' => 'en-US',
            'value' => 'G3'
          ])
        ]),
        'section' => new LocalizedString([
          'defaultValue' => new TranslatedString([
            'language' => 'en-US',
            'value' => '5'
          ])
        ]),
        'gate' => new LocalizedString([
          'defaultValue' => new TranslatedString([
            'language' => 'en-US',
            'value' => 'A'
          ])
        ])
      ]),
      'ticketHolderName' => 'Ticket holder name',
      'ticketNumber' => 'Ticket number'
    ]);

    $batch->add($this->service->eventticketobject->insert($batchObject));
  }

  // Make the batch request
  $batchResponse = $batch->execute();

  print "Batch insert response\n";
  foreach ($batchResponse as $key => $value) {
    if ($value instanceof Google_Service_Exception) {
      print_r($value->getErrors());
      continue;
    }
    print "{$value->getId()}\n";
  }
}

پایتون

برای شروع ادغام خود در پایتون، به نمونه کدهای کامل ما در GitHub مراجعه کنید.

def batch_create_objects(self, issuer_id: str, class_suffix: str):
    """Batch create Google Wallet objects from an existing class.

    The request body will be a multiline string. See below for information.

    https://cloud.google.com/compute/docs/api/how-tos/batch#example

    Args:
        issuer_id (str): The issuer ID being used for this request.
        class_suffix (str): Developer-defined unique ID for this pass class.
    """
    batch = self.client.new_batch_http_request()

    # Example: Generate three new pass objects
    for _ in range(3):
        # Generate a random object suffix
        object_suffix = str(uuid.uuid4()).replace('[^\\w.-]', '_')

        # See link below for more information on required properties
        # https://developers.google.com/wallet/tickets/events/rest/v1/eventticketobject
        batch_object = {
            'id': f'{issuer_id}.{object_suffix}',
            'classId': f'{issuer_id}.{class_suffix}',
            'state': 'ACTIVE',
            'heroImage': {
                'sourceUri': {
                    'uri':
                        'https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg'
                },
                'contentDescription': {
                    'defaultValue': {
                        'language': 'en-US',
                        'value': 'Hero image description'
                    }
                }
            },
            'textModulesData': [{
                'header': 'Text module header',
                'body': 'Text module body',
                'id': 'TEXT_MODULE_ID'
            }],
            'linksModuleData': {
                'uris': [{
                    'uri': 'http://maps.google.com/',
                    'description': 'Link module URI description',
                    'id': 'LINK_MODULE_URI_ID'
                }, {
                    'uri': 'tel:6505555555',
                    'description': 'Link module tel description',
                    'id': 'LINK_MODULE_TEL_ID'
                }]
            },
            'imageModulesData': [{
                'mainImage': {
                    'sourceUri': {
                        'uri':
                            'http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg'
                    },
                    'contentDescription': {
                        'defaultValue': {
                            'language': 'en-US',
                            'value': 'Image module description'
                        }
                    }
                },
                'id': 'IMAGE_MODULE_ID'
            }],
            'barcode': {
                'type': 'QR_CODE',
                'value': 'QR code'
            },
            'locations': [{
                'latitude': 37.424015499999996,
                'longitude': -122.09259560000001
            }],
            'seatInfo': {
                'seat': {
                    'defaultValue': {
                        'language': 'en-US',
                        'value': '42'
                    }
                },
                'row': {
                    'defaultValue': {
                        'language': 'en-US',
                        'value': 'G3'
                    }
                },
                'section': {
                    'defaultValue': {
                        'language': 'en-US',
                        'value': '5'
                    }
                },
                'gate': {
                    'defaultValue': {
                        'language': 'en-US',
                        'value': 'A'
                    }
                }
            },
            'ticketHolderName': 'Ticket holder name',
            'ticketNumber': 'Ticket number'
        }

        batch.add(self.client.eventticketobject().insert(body=batch_object))

    # Invoke the batch API calls
    response = batch.execute()

    print('Batch complete')

سی شارپ

برای شروع ادغام خود در C#، به نمونه کدهای کامل ما در GitHub مراجعه کنید.

/// <summary>
/// Batch create Google Wallet objects from an existing class.
/// </summary>
/// <param name="issuerId">The issuer ID being used for this request.</param>
/// <param name="classSuffix">Developer-defined unique ID for this pass class.</param>
public async void BatchCreateObjects(string issuerId, string classSuffix)
{
  // The request body will be a multiline string
  // See below for more information
  // https://cloud.google.com/compute/docs/api/how-tos/batch//example
  string data = "";

  HttpClient httpClient = new HttpClient();
  httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
    "Bearer",
    credentials.GetAccessTokenForRequestAsync().Result
  );

  // Example: Generate three new pass objects
  for (int i = 0; i < 3; i++)
  {
    // Generate a random object suffix
    string objectSuffix = Regex.Replace(Guid.NewGuid().ToString(), "[^\\w.-]", "_");

    // See link below for more information on required properties
    // https://developers.google.com/wallet/tickets/events/rest/v1/eventticketobject
    EventTicketObject batchObject = new EventTicketObject
    {
      Id = $"{issuerId}.{objectSuffix}",
      ClassId = $"{issuerId}.{classSuffix}",
      State = "ACTIVE",
      HeroImage = new Image
      {
        SourceUri = new ImageUri
        {
          Uri = "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg"
        },
        ContentDescription = new LocalizedString
        {
          DefaultValue = new TranslatedString
          {
            Language = "en-US",
            Value = "Hero image description"
          }
        }
      },
      TextModulesData = new List<TextModuleData>
      {
        new TextModuleData
        {
          Header = "Text module header",
          Body = "Text module body",
          Id = "TEXT_MODULE_ID"
        }
      },
      LinksModuleData = new LinksModuleData
      {
        Uris = new List<Google.Apis.Walletobjects.v1.Data.Uri>
        {
          new Google.Apis.Walletobjects.v1.Data.Uri
          {
            UriValue = "http://maps.google.com/",
            Description = "Link module URI description",
            Id = "LINK_MODULE_URI_ID"
          },
          new Google.Apis.Walletobjects.v1.Data.Uri
          {
            UriValue = "tel:6505555555",
            Description = "Link module tel description",
            Id = "LINK_MODULE_TEL_ID"
          }
        }
      },
      ImageModulesData = new List<ImageModuleData>
      {
        new ImageModuleData
        {
          MainImage = new Image
          {
            SourceUri = new ImageUri
            {
              Uri = "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg"
            },
            ContentDescription = new LocalizedString
            {
              DefaultValue = new TranslatedString
              {
                Language = "en-US",
                Value = "Image module description"
              }
            }
          },
          Id = "IMAGE_MODULE_ID"
        }
      },
      Barcode = new Barcode
      {
        Type = "QR_CODE",
        Value = "QR code"
      },
      Locations = new List<LatLongPoint>
      {
        new LatLongPoint
        {
          Latitude = 37.424015499999996,
          Longitude = -122.09259560000001
        }
      },
      SeatInfo = new EventSeat
      {
        Seat = new LocalizedString
        {
          DefaultValue = new TranslatedString
          {
            Language = "en-US",
            Value = "42"
          }
        },
        Row = new LocalizedString
        {
          DefaultValue = new TranslatedString
          {
            Language = "en-US",
            Value = "G3"
          }
        },
        Section = new LocalizedString
        {
          DefaultValue = new TranslatedString
          {
            Language = "en-US",
            Value = "5"
          }
        },
        Gate = new LocalizedString
        {
          DefaultValue = new TranslatedString
          {
            Language = "en-US",
            Value = "A"
          }
        }
      },
      TicketHolderName = "Ticket holder name",
      TicketNumber = "Ticket number"
    };

    data += "--batch_createobjectbatch\n";
    data += "Content-Type: application/json\n\n";
    data += "POST /walletobjects/v1/eventTicketObject/\n\n";

    data += JsonConvert.SerializeObject(batchObject) + "\n\n";
  }
  data += "--batch_createobjectbatch--";

  // Invoke the batch API calls
  HttpRequestMessage batchObjectRequest = new HttpRequestMessage(
      HttpMethod.Post,
      "https://walletobjects.googleapis.com/batch");

  batchObjectRequest.Content = new StringContent(data);
  batchObjectRequest.Content.Headers.ContentType = new MediaTypeHeaderValue(
      "multipart/mixed");
  // `boundary` is the delimiter between API calls in the batch request
  batchObjectRequest.Content.Headers.ContentType.Parameters.Add(
      new NameValueHeaderValue("boundary", "batch_createobjectbatch"));

  HttpResponseMessage batchObjectResponse = httpClient.Send(
      batchObjectRequest);

  string batchObjectContent = await batchObjectResponse
      .Content
      .ReadAsStringAsync();

  Console.WriteLine("Batch insert response");
  Console.WriteLine(batchObjectContent);
}

Node.js

برای شروع ادغام خود در Node، به نمونه کدهای کامل ما در GitHub مراجعه کنید.

/**
 * Batch create Google Wallet objects from an existing class.
 *
 * @param {string} issuerId The issuer ID being used for this request.
 * @param {string} classSuffix Developer-defined unique ID for this pass class.
 */
async batchCreateObjects(issuerId, classSuffix) {
  // See below for more information
  // https://cloud.google.com/compute/docs/api/how-tos/batch#example
  let data = '';
  let batchObject;
  let objectSuffix;

  // Example: Generate three new pass objects
  for (let i = 0; i < 3; i++) {
    // Generate a random object suffix
    objectSuffix = uuidv4().replace('[^\w.-]', '_');

    // See link below for more information on required properties
    // https://developers.google.com/wallet/tickets/events/rest/v1/eventticketobject
    batchObject = {
      'id': `${issuerId}.${objectSuffix}`,
      'classId': `${issuerId}.${classSuffix}`,
      'state': 'ACTIVE',
      'heroImage': {
        'sourceUri': {
          'uri': 'https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg'
        },
        'contentDescription': {
          'defaultValue': {
            'language': 'en-US',
            'value': 'Hero image description'
          }
        }
      },
      'textModulesData': [
        {
          'header': 'Text module header',
          'body': 'Text module body',
          'id': 'TEXT_MODULE_ID'
        }
      ],
      'linksModuleData': {
        'uris': [
          {
            'uri': 'http://maps.google.com/',
            'description': 'Link module URI description',
            'id': 'LINK_MODULE_URI_ID'
          },
          {
            'uri': 'tel:6505555555',
            'description': 'Link module tel description',
            'id': 'LINK_MODULE_TEL_ID'
          }
        ]
      },
      'imageModulesData': [
        {
          'mainImage': {
            'sourceUri': {
              'uri': 'http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg'
            },
            'contentDescription': {
              'defaultValue': {
                'language': 'en-US',
                'value': 'Image module description'
              }
            }
          },
          'id': 'IMAGE_MODULE_ID'
        }
      ],
      'barcode': {
        'type': 'QR_CODE',
        'value': 'QR code'
      },
      'locations': [
        {
          'latitude': 37.424015499999996,
          'longitude': -122.09259560000001
        }
      ],
      'seatInfo': {
        'seat': {
          'defaultValue': {
            'language': 'en-US',
            'value': '42'
          }
        },
        'row': {
          'defaultValue': {
            'language': 'en-US',
            'value': 'G3'
          }
        },
        'section': {
          'defaultValue': {
            'language': 'en-US',
            'value': '5'
          }
        },
        'gate': {
          'defaultValue': {
            'language': 'en-US',
            'value': 'A'
          }
        },
      },
      'ticketHolderName': 'Ticket holder name',
      'ticketNumber': 'Ticket number'
    };

    data += '--batch_createobjectbatch\n';
    data += 'Content-Type: application/json\n\n';
    data += 'POST /walletobjects/v1/eventTicketObject\n\n';

    data += JSON.stringify(batchObject) + '\n\n';
  }
  data += '--batch_createobjectbatch--';

  // Invoke the batch API calls
  let response = await this.client.context._options.auth.request({
    url: 'https://walletobjects.googleapis.com/batch',
    method: 'POST',
    data: data,
    headers: {
      // `boundary` is the delimiter between API calls in the batch request
      'Content-Type': 'multipart/mixed; boundary=batch_createobjectbatch'
    }
  });

  console.log('Batch insert response');
  console.log(response);
}

برو

برای شروع ادغام خود در Go، به نمونه کدهای کامل ما در نمونه کدهای GitHub در Github مراجعه کنید.

// Batch create Google Wallet objects from an existing class.
func (d *demoEventticket) batchCreateObjects(issuerId, classSuffix string) {
	data := ""
	for i := 0; i < 3; i++ {
		objectSuffix := strings.ReplaceAll(uuid.New().String(), "-", "_")

		eventticketObject := new(walletobjects.EventTicketObject)
		eventticketObject.Id = fmt.Sprintf("%s.%s", issuerId, objectSuffix)
		eventticketObject.ClassId = fmt.Sprintf("%s.%s", issuerId, classSuffix)
		eventticketObject.TicketHolderName = "Ticket holder name"
		eventticketObject.TicketNumber = "Ticket number"
		eventticketObject.State = "ACTIVE"

		eventticketJson, _ := json.Marshal(eventticketObject)
		batchObject := fmt.Sprintf("%s", eventticketJson)

		data += "--batch_createobjectbatch\n"
		data += "Content-Type: application/json\n\n"
		data += "POST /walletobjects/v1/eventTicketObject\n\n"
		data += batchObject + "\n\n"
	}
	data += "--batch_createobjectbatch--"

	res, err := d.credentials.Client(oauth2.NoContext).Post("https://walletobjects.googleapis.com/batch", "multipart/mixed; boundary=batch_createobjectbatch", bytes.NewBuffer([]byte(data)))

	if err != nil {
		fmt.Println(err)
	} else {
		b, _ := io.ReadAll(res.Body)
		fmt.Printf("Batch insert response:\n%s\n", b)
	}
}