العمل باستخدام رموز JSON للويب (JWT)

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

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

ترميز بطاقة في JWT

عند إنشاء FlightObject، يمكنك التفافها باستخدام JWT غير موقَّع باستخدام السمة payload.FlightObjects، كما هو موضّح في المقتطف التالي:

JSON

{
  "iss": "OWNER_EMAIL_ADDRESS",
  "aud": "google",
  "typ": "savetowallet",
  "iat": "UNIX_TIME",
  "origins": [],
  "payload": {
      "flightObjects": [ NEW_OBJECT ]
  }
}

لمزيد من المعلومات حول التنسيق المتوقّع لملفات JWT، يُرجى الاطّلاع على مرجع JWT.

التوقيع على JWT

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

الويب والبريد الإلكتروني والرسائل القصيرة SMS

يجب توقيع JWT باستخدام مفتاح حساب الخدمة المرتبط بحساب خدمة Google Cloud الذي فوّضته في Google Wallet Business Console. ستتحقّق Google Wallet API من هذه المطالبات من خلال التحقّق من توقيع JWT.

سيؤدي توقيع JWT إلى إنشاء رمز مميز يمكن استخدامه بعد ذلك لإنشاء ميزة "الإضافة إلى محفظة Google". الرابط الذي يمكن استخدامه لإصدار البطاقة إلى المستخدم:

Java

لبدء الدمج في Java، راجع عيّنات من الرموز البرمجية على GitHub.

/**
 * Generate a signed JWT that creates a new pass class and object.
 *
 * <p>When the user opens the "Add to Google Wallet" URL and saves the pass to their wallet, the
 * pass class and object defined in the JWT are created. This allows you to create multiple pass
 * classes and objects in one API call when the user saves the pass to their wallet.
 *
 * @param issuerId The issuer ID being used for this request.
 * @param classSuffix Developer-defined unique ID for this pass class.
 * @param objectSuffix Developer-defined unique ID for the pass object.
 * @return An "Add to Google Wallet" link.
 */
public String createJWTNewObjects(String issuerId, String classSuffix, String objectSuffix) {
  // See link below for more information on required properties
  // https://developers.google.com/wallet/tickets/boarding-passes/rest/v1/flightclass
  FlightClass newClass =
      new FlightClass()
          .setId(String.format("%s.%s", issuerId, classSuffix))
          .setIssuerName("Issuer name")
          .setReviewStatus("UNDER_REVIEW")
          .setLocalScheduledDepartureDateTime("2023-07-02T15:30:00")
          .setFlightHeader(
              new FlightHeader()
                  .setCarrier(new FlightCarrier().setCarrierIataCode("LX"))
                  .setFlightNumber("123"))
          .setOrigin(new AirportInfo().setAirportIataCode("LAX").setTerminal("1").setGate("A2"))
          .setDestination(
              new AirportInfo().setAirportIataCode("SFO").setTerminal("2").setGate("C3"));

  // See link below for more information on required properties
  // https://developers.google.com/wallet/tickets/boarding-passes/rest/v1/flightobject
  FlightObject newObject =
      new FlightObject()
          .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)))
          .setPassengerName("Passenger name")
          .setBoardingAndSeatingInfo(
              new BoardingAndSeatingInfo().setBoardingGroup("B").setSeatNumber("42"))
          .setReservationInfo(new ReservationInfo().setConfirmationCode("Confirmation code"));

  // Create the JWT as a HashMap object
  HashMap<String, Object> claims = new HashMap<String, Object>();
  claims.put("iss", ((ServiceAccountCredentials) credentials).getClientEmail());
  claims.put("aud", "google");
  claims.put("origins", List.of("www.example.com"));
  claims.put("typ", "savetowallet");

  // Create the Google Wallet payload and add to the JWT
  HashMap<String, Object> payload = new HashMap<String, Object>();
  payload.put("flightClasses", List.of(newClass));
  payload.put("flightObjects", List.of(newObject));
  claims.put("payload", payload);

  // The 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);

  System.out.println("Add to Google Wallet link");
  System.out.printf("https://pay.google.com/gp/v/save/%s%n", token);

  return String.format("https://pay.google.com/gp/v/save/%s", token);
}

PHP

لبدء عملية الدمج باستخدام لغة PHP، يُرجى الرجوع إلى عيّنات من الرموز البرمجية على GitHub.

/**
 * Generate a signed JWT that creates a new pass class and object.
 *
 * When the user opens the "Add to Google Wallet" URL and saves the pass to
 * their wallet, the pass class and object defined in the JWT are
 * created. This allows you to create multiple pass classes and objects in
 * one API call when the user saves the pass to their wallet.
 *
 * @param string $issuerId The issuer ID being used for this request.
 * @param string $classSuffix Developer-defined unique ID for the pass class.
 * @param string $objectSuffix Developer-defined unique ID for the pass object.
 *
 * @return string An "Add to Google Wallet" link.
 */
public function createJwtNewObjects(string $issuerId, string $classSuffix, string $objectSuffix)
{
  // See link below for more information on required properties
  // https://developers.google.com/wallet/tickets/boarding-passes/rest/v1/flightclass
  $newClass = new FlightClass([
    'id' => "{$issuerId}.{$classSuffix}",
    'issuerName' => 'Issuer name',
    'reviewStatus' => 'UNDER_REVIEW',
    'localScheduledDepartureDateTime' => '2023-07-02T15:30:00',
    'flightHeader' => new FlightHeader([
      'carrier' => new FlightCarrier([
        'carrierIataCode' => 'LX'
      ]),
      'flightNumber' => '123'
    ]),
    'origin' => new AirportInfo([
      'airportIataCode' => 'LAX',
      'terminal' => '1',
      'gate' => 'A2'
    ]),
    'destination' => new AirportInfo([
      'airportIataCode' => 'SFO',
      'terminal' => '2',
      'gate' => 'C3'
    ])
  ]);

  // See link below for more information on required properties
  // https://developers.google.com/wallet/tickets/boarding-passes/rest/v1/flightobject
  $newObject = new FlightObject([
    '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
      ])
    ],
    'passengerName' => 'Passenger name',
    'boardingAndSeatingInfo' => new BoardingAndSeatingInfo([
      'boardingGroup' => 'B',
      'seatNumber' => '42'
    ]),
    'reservationInfo' => new ReservationInfo([
      'confirmationCode' => 'Confirmation code'
    ])
  ]);

  // The service account credentials are used to sign the JWT
  $serviceAccount = json_decode(file_get_contents($this->keyFilePath), true);

  // Create the JWT as an array of key/value pairs
  $claims = [
    'iss' => $serviceAccount['client_email'],
    'aud' => 'google',
    'origins' => ['www.example.com'],
    'typ' => 'savetowallet',
    'payload' => [
      'flightClasses' => [
        $newClass
      ],
      'flightObjects' => [
        $newObject
      ]
    ]
  ];

  $token = JWT::encode(
    $claims,
    $serviceAccount['private_key'],
    'RS256'
  );

  print "Add to Google Wallet link\n";
  print "https://pay.google.com/gp/v/save/{$token}";

  return "https://pay.google.com/gp/v/save/{$token}";
}

Python

لبدء عملية الدمج في بايثون، يُرجى الرجوع إلى عيّنات من الرموز البرمجية على GitHub.

def create_jwt_new_objects(self, issuer_id: str, class_suffix: str,
                           object_suffix: str) -> str:
    """Generate a signed JWT that creates a new pass class and object.

    When the user opens the "Add to Google Wallet" URL and saves the pass to
    their wallet, the pass class and object defined in the JWT are
    created. This allows you to create multiple pass classes and objects in
    one API call when the user saves the pass to their wallet.

    Args:
        issuer_id (str): The issuer ID being used for this request.
        class_suffix (str): Developer-defined unique ID for the pass class.
        object_suffix (str): Developer-defined unique ID for the pass object.

    Returns:
        An "Add to Google Wallet" link.
    """

    # Seelink  below for more information on required properties
    # https://developers.google.com/wallet/tickets/boarding-passes/rest/v1/flightclass
    new_class = {
        'id': f'{issuer_id}.{class_suffix}',
        'issuerName': 'Issuer name',
        'reviewStatus': 'UNDER_REVIEW',
        'localScheduledDepartureDateTime': '2023-07-02T15:30:00',
        'flightHeader': {
            'carrier': {
                'carrierIataCode': 'LX'
            },
            'flightNumber': '123'
        },
        'origin': {
            'airportIataCode': 'LAX',
            'terminal': '1',
            'gate': 'A2'
        },
        'destination': {
            'airportIataCode': 'SFO',
            'terminal': '2',
            'gate': 'C3'
        }
    }

    # See link below for more information on required properties
    # https://developers.google.com/wallet/tickets/boarding-passes/rest/v1/flightclass
    new_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
        }],
        'passengerName': 'Passenger name',
        'boardingAndSeatingInfo': {
            'boardingGroup': 'B',
            'seatNumber': '42'
        },
        'reservationInfo': {
            'confirmationCode': 'Confirmation code'
        }
    }

    # 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
            'flightClasses': [new_class],
            'flightObjects': [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')

    print('Add to Google Wallet link')
    print(f'https://pay.google.com/gp/v/save/{token}')

    return f'https://pay.google.com/gp/v/save/{token}'

#C

لبدء الدمج في C#، يمكنك الرجوع إلى عيّنات من الرموز البرمجية على GitHub.

/// <summary>
/// Generate a signed JWT that creates a new pass class and object.
/// <para />
/// When the user opens the "Add to Google Wallet" URL and saves the pass to
/// their wallet, the pass class and object defined in the JWT are created.
/// This allows you to create multiple pass classes and objects in one API
/// call when the user saves the pass to their wallet.
/// <para />
/// The Google Wallet C# library uses Newtonsoft.Json.JsonPropertyAttribute
/// to specify the property names when converting objects to JSON. The
/// Newtonsoft.Json.JsonConvert.SerializeObject method will automatically
/// serialize the object with the right property names.
/// </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>
/// <param name="objectSuffix">Developer-defined unique ID for the pass object.</param>
/// <returns>An "Add to Google Wallet" link.</returns>
public string CreateJWTNewObjects(string issuerId, string classSuffix, string objectSuffix)
{
  // Ignore null values when serializing to/from JSON
  JsonSerializerSettings excludeNulls = new JsonSerializerSettings()
  {
    NullValueHandling = NullValueHandling.Ignore
  };

  // See link below for more information on required properties
  // https://developers.google.com/wallet/tickets/boarding-passes/rest/v1/flightclass
  FlightClass newClass = new FlightClass
  {
    Id = $"{issuerId}.{classSuffix}",
    IssuerName = "Issuer name",
    ReviewStatus = "UNDER_REVIEW",
    LocalScheduledDepartureDateTime = "2023-07-02T15:30:00",
    FlightHeader = new FlightHeader
    {
      Carrier = new FlightCarrier
      {
        CarrierIataCode = "LX"
      },
      FlightNumber = "123"
    },
    Origin = new AirportInfo
    {
      AirportIataCode = "LAX",
      Terminal = "1",
      Gate = "A2"
    },
    Destination = new AirportInfo
    {
      AirportIataCode = "SFO",
      Terminal = "2",
      Gate = "C3"
    }
  };

  // See link below for more information on required properties
  // https://developers.google.com/wallet/tickets/boarding-passes/rest/v1/flightobject
  FlightObject newObject = new FlightObject
  {
    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
      }
    },
    PassengerName = "Passenger name",
    BoardingAndSeatingInfo = new BoardingAndSeatingInfo
    {
      BoardingGroup = "B",
      SeatNumber = "42"
    },
    ReservationInfo = new ReservationInfo
    {
      ConfirmationCode = "Confirmation code"
    }
  };

  // Create JSON representations of the class and object
  JObject serializedClass = JObject.Parse(
      JsonConvert.SerializeObject(newClass, excludeNulls));
  JObject serializedObject = JObject.Parse(
      JsonConvert.SerializeObject(newObject, excludeNulls));

  // Create the JWT as a JSON object
  JObject jwtPayload = JObject.Parse(JsonConvert.SerializeObject(new
  {
    iss = credentials.Id,
    aud = "google",
    origins = new List<string>
    {
      "www.example.com"
    },
    typ = "savetowallet",
    payload = JObject.Parse(JsonConvert.SerializeObject(new
    {
      // The listed classes and objects will be created
      // when the user saves the pass to their wallet
      flightClasses = new List<JObject>
      {
        serializedClass
      },
      flightObjects = new List<JObject>
      {
        serializedObject
      }
    }))
  }));

  // Deserialize into a JwtPayload
  JwtPayload claims = JwtPayload.Deserialize(jwtPayload.ToString());

  // The service account credentials are used to sign the JWT
  RsaSecurityKey key = new RsaSecurityKey(credentials.Key);
  SigningCredentials signingCredentials = new SigningCredentials(
      key, SecurityAlgorithms.RsaSha256);
  JwtSecurityToken jwt = new JwtSecurityToken(
      new JwtHeader(signingCredentials), claims);
  string token = new JwtSecurityTokenHandler().WriteToken(jwt);

  Console.WriteLine("Add to Google Wallet link");
  Console.WriteLine($"https://pay.google.com/gp/v/save/{token}");

  return $"https://pay.google.com/gp/v/save/{token}";
}

Node.js

لبدء عملية الدمج في Node، يُرجى الرجوع إلى عيّنات من الرموز البرمجية على GitHub.

/**
 * Generate a signed JWT that creates a new pass class and object.
 *
 * When the user opens the "Add to Google Wallet" URL and saves the pass to
 * their wallet, the pass class and object defined in the JWT are
 * created. This allows you to create multiple pass classes and objects in
 * one API call when the user saves the pass to their wallet.
 *
 * @param {string} issuerId The issuer ID being used for this request.
 * @param {string} classSuffix Developer-defined unique ID for the pass class.
 * @param {string} objectSuffix Developer-defined unique ID for the pass object.
 *
 * @returns {string} An "Add to Google Wallet" link.
 */
createJwtNewObjects(issuerId, classSuffix, objectSuffix) {
  // See link below for more information on required properties
  // https://developers.google.com/wallet/tickets/boarding-passes/rest/v1/flightclass
  let newClass = {
    'id': `${issuerId}.${classSuffix}`,
    'issuerName': 'Issuer name',
    'reviewStatus': 'UNDER_REVIEW',
    'localScheduledDepartureDateTime': '2023-07-02T15:30:00',
    'flightHeader': {
      'carrier': {
        'carrierIataCode': 'LX'
      },
      'flightNumber': '123'
    },
    'origin': {
      'airportIataCode': 'LAX',
      'terminal': '1',
      'gate': 'A2'
    },
    'destination': {
      'airportIataCode': 'SFO',
      'terminal': '2',
      'gate': 'C3'
    }
  };

  // See link below for more information on required properties
  // https://developers.google.com/wallet/tickets/boarding-passes/rest/v1/flightobject
  let newObject = {
    '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
      }
    ],
    'passengerName': 'Passenger name',
    'boardingAndSeatingInfo': {
      'boardingGroup': 'B',
      'seatNumber': '42'
    },
    'reservationInfo': {
      'confirmationCode': 'Confirmation code'
    }
  };

  // Create the JWT claims
  let claims = {
    iss: this.credentials.client_email,
    aud: 'google',
    origins: ['www.example.com'],
    typ: 'savetowallet',
    payload: {
      // The listed classes and objects will be created
      flightClasses: [newClass],
      flightObjects: [newObject]
    }
  };

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

  console.log('Add to Google Wallet link');
  console.log(`https://pay.google.com/gp/v/save/${token}`);

  return `https://pay.google.com/gp/v/save/${token}`;
}

البدء

لبدء عملية الدمج في Go، يُرجى الرجوع إلى العيّنات الكاملة من الرموز البرمجية على GitHub. عيّنات التعليمات البرمجية على GitHub.

// Generate a signed JWT that creates a new pass class and object.
//
// When the user opens the "Add to Google Wallet" URL and saves the pass to
// their wallet, the pass class and object defined in the JWT are
// created. This allows you to create multiple pass classes and objects in
// one API call when the user saves the pass to their wallet.
func (d *demoFlight) createJwtNewObjects(issuerId, classSuffix, objectSuffix string) {
	flightObject := new(walletobjects.FlightObject)
	flightObject.Id = fmt.Sprintf("%s.%s", issuerId, objectSuffix)
	flightObject.ClassId = fmt.Sprintf("%s.%s", issuerId, classSuffix)
	flightObject.State = "ACTIVE"
	flightObject.PassengerName = "Passenger name"
	flightObject.ReservationInfo = &walletobjects.ReservationInfo{
		ConfirmationCode: "Confirmation code",
	}

	flightJson, _ := json.Marshal(flightObject)
	var payload map[string]any
	json.Unmarshal([]byte(fmt.Sprintf(`
	{
		"flightObjects": [%s]
	}
	`, flightJson)), &payload)
	claims := jwt.MapClaims{
		"iss":     d.credentials.Email,
		"aud":     "google",
		"origins": []string{"www.example.com"},
		"typ":     "savetowallet",
		"payload": payload,
	}

	// The service account credentials are used to sign the JWT
	key, _ := jwt.ParseRSAPrivateKeyFromPEM(d.credentials.PrivateKey)
	token, _ := jwt.NewWithClaims(jwt.SigningMethodRS256, claims).SignedString(key)

	fmt.Println("Add to Google Wallet link")
	fmt.Println("https://pay.google.com/gp/v/save/" + token)
}

تطبيقات Android

عند استدعاء طريقة savePasses لإصدار بطاقة إلى أحد المستخدمين، توقّع حزمة تطوير البرامج (SDK) لنظام التشغيل Android في "محفظة Google" تلقائيًا جهاز JWT باستخدام الملف المرجعي SHA-1 لمفتاح توقيع التطبيق الذي قدّمته في Google Wallet Business Console. بدلاً من ذلك، يمكنك أيضًا إصدار البطاقة باستخدام ملف JWT موقَّع سابقًا باستخدام طريقة savePassesJwt في حزمة تطوير البرامج (SDK) لنظام التشغيل Android.

للمزيد من المعلومات، يُرجى الاطّلاع على مقالة إصدار البطاقات باستخدام حزمة تطوير البرامج (SDK) لنظام التشغيل Android.