نکته‌های عملکرد

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

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

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

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

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

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

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

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

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

جزئیات بیشتر درباره ارسال درخواست‌های جزئی در بخش‌های زیر ارائه شده است.

پاسخ جزئی

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

برای درخواست پاسخ جزئی، از پارامتر درخواست 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 تودرتو است استفاده کنید.

    استثنا: برای پاسخ‌های میانای برنامه‌سازی کاربردی که از پوشاننده‌های «داده» استفاده می‌کنند، جایی که پاسخ در شیء 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 باید کدگذاری نشانی وب باشد. برای خوانایی بهتر، مثال‌های این سند کدبندی را حذف می‌کنند.

فیلدهایی را که می‌خواهید برگردانده شوند شناسایی کنید، یا انتخاب‌های فیلد را انجام دهید.
مقدار پارامتر درخواست 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 است پردازش کرد، رمز وضعیت اچ‌تی‌تی‌پی‌اس 200 OK را به‌همراه داده‌های درخواست‌شده برمی‌گرداند. اگر پارامتر پُرسمان fields خطا داشته باشد یا به‌هر دلیلی نامعتبر باشد، سرور کد وضعیت HTTP 400 Bad Request را به‌همراه پیام خطایی که به کاربر می‌گوید انتخاب فیلد او چه مشکلی داشته است (برای نمونه، "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"
    }
  },
  ...
  ]
}

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

وصله (به‌روزرسانی جزئی)

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

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

مثال

این مثال یک درخواست وصله ساده را نشان می‌دهد که فقط عنوان منبع 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 استفاده کنید.

معناشناسی درخواست وصله

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

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

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

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

یک روش مفید می‌تواند این باشد که ابتدا پاسخ جزئی را با داده‌هایی که می‌خواهید اصلاح کنید بازیابی کنید. این امر به‌ویژه برای منابعی که از ETags استفاده می‌کنند مهم است، زیرا برای به‌روزرسانی موفقیت‌آمیز منبع باید مقدار ETag فعلی را در سرصفحه If-Match HTTP ارائه دهید. پس‌از دریافت داده‌ها، می‌توانید مقادیر موردنظرتان را تغییر دهید و نمایش جزئی اصلاح‌شده را با درخواست وصله برگردانید. در اینجا مثالی آورده شده است که فرض می‌کند منبع «نمایشی» از 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" g>"Liz"], /* New follower Liz is present; deleted Will is missing. */
    "accuracy": "high"         /* New characteristic is present. */
  }
}

ساختن درخواست وصله به‌طور مستقیم

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

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

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

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 را به‌همراه نمایش کامل منبع اصلاح‌شده برمی‌گرداند. اگر API از ETag استفاده کند، سرور مقادیر ETag را هنگام پردازش موفقیت‌آمیز درخواست وصله به‌روز می‌کند، درست همان‌طور که با PUT انجام می‌دهد.

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

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

نشانه‌گذاری جایگزین وقتی فعل HTTP از نوع PATCH پشتیبانی نمی‌شود

اگر دیوار آتش شما درخواست‌های HTTP PATCH را مجاز نمی‌داند، درخواست HTTP POST را انجام دهید و سرصفحه ملغی‌کننده را روی PATCH تنظیم کنید، همان‌طور که در زیر نشان داده شده است:

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

تفاوت بین وصله و به‌روزرسانی

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

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

درخواست‌های دسته‌ای به «کیف پول Google»

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

کد نمونه زیر درخواست‌های دسته‌ای را نشان می‌دهد. مثال‌های Java و PHP از کتابخانه‌های «کیف پول Google» برای ساده‌سازی ایجاد کلاس و شیء استفاده می‌کنند.

جاوا

برای شروع یکپارچه‌سازی در Java، به نمونه‌های کد کامل ما در 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";
  }
}

Python

برای شروع ادغام در Python، به نمونه‌های کد کامل ما در 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#‎

برای شروع ادغام در 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)
	}
}