Процесс разработки карт для Google Кошелька

Google Wallet API предоставляет набор типов карт, оптимизированных для определенных сценариев использования, таких как подарочные карты, посадочные талоны, билеты на мероприятия и т. д. Также есть универсальные карты, которые можно использовать, если ни один из типов не подходит.

В этой статье рассказывается, как создать и выпустить карту с помощью Google Wallet API. Некоторые из описанных ниже шагов можно выполнить разными способами, но в целом все типы карт создаются по одному и тому же базовому процессу разработки.

Подробные инструкции по созданию карт вы найдете в руководствах для веб-сайтов, электронной почты и SMS и приложений Android.

Назначение

Класс карт определяет набор свойств, общих для нескольких карт, аналогично шаблону. Например, если вы выпускаете билеты на мероприятие, в классе карт будут определены поля, одинаковые для всех билетов, такие как название события, дата и время мероприятия.

Каждая выпущенная вами карта должна ссылаться на класс карт. Каждому классу карт нужно присвоить уникальный идентификатор, который будет использоваться при создании карт.

Как это делается

Класс карт и билетов определяется в формате JSON и может быть создан с помощью Google Кошелька REST API, Android SDK или Google Wallet Business Console.

Показать пример класса Passes

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

Назначение

Объект Passes определяет свойства уникальной карты, которая будет выпущена для определенного пользователя. Например, объект карты для билета на мероприятие определяет поля, уникальные для конкретного билета, такие как номер места или QR-код для этого билета.

При создании объекта Passes API Google Wallet сохраняет новую карту и связывает ее с вашим аккаунтом эмитента. Сохраненная карта сочетает в себе уникальные свойства объекта Passes Object и свойства шаблона связанного класса Passes Class.

Каждому объекту Passes Object необходимо присвоить уникальный идентификатор, который будет использоваться для ссылки на него при выпуске карты.

Как это делается

Объект Passes определяется в формате JSON и может быть создан с помощью Google Кошелька REST API или Android SDK.

Показать пример объекта Passes Object

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

Назначение

Чтобы выпустить карту для пользователя, класс и объект карты должны быть закодированы в веб-токене JSON (JWT). Формат JWT – это распространенный открытый стандарт для представления утверждений между двумя сторонами. При выпуске карт с помощью Google Wallet API JWT используются для отправки утверждения о том, что пользователь имеет право на доступ к определенной карте, связанной с вашим аккаунтом эмитента.

Когда JWT отправляется в Google Wallet API, закодированные данные используются для идентификации определенной карты и ее выпуска для пользователя. Если карта уже выпущена, эти данные также позволяют Google Wallet API определить, что карта является дубликатом, чтобы она не была добавлена в Google Кошелек пользователя более одного раза.

Как это делается

Токены JWT определяются в формате JSON на основе спецификации JWT. Чтобы определить JWT для выпуска карты с помощью Google Wallet API, укажите информацию о карте в свойстве payload токена JWT.

Показать пример JWT

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

Назначение

Все JWT, отправленные в Google Wallet API для выпуска карты, должны быть подписаны с использованием учетных данных, которые вы ранее указали в Google Wallet Business Console. При подписании используются ваши учетные данные для шифрования JWT, чтобы ваши карты оставались в безопасности, а Google Wallet API мог подтвердить, что закодированные в нем данные карты действительны и связаны с вашим аккаунтом эмитента.

Как это делается

Клиентские библиотеки Google Кошелька и Android SDK предоставляют удобные методы для подписи JWT. Также существует множество библиотек с открытым исходным кодом, которые упрощают подписание кода.

Если вы используете Google Wallet REST API, то JWT подписывается ключом сервисного аккаунта Google Cloud. Если вы используете Google Кошелек Android SDK, то он автоматически подписывает JWT с помощью цифрового отпечатка SHA-1 сертификата подписи приложения.

Чтобы защитить учетные данные, JWT-токены должны подписываться только на вашем сервере или с помощью Google Кошелька Android SDK в вашем приложении.

Показать пример подписи кода

Java

  // 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", Arrays.asList("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("eventTicketObjects", Arrays.asList(newObject));
  claims.put("payload", payload);

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

Node.JS

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

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

Python

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

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

Назначение

После создания подписанного JWT вы можете выпустить карту для пользователя Google Кошелька. Для этого нужно добавить кнопку или ссылку "Добавить в Google Кошелек". Когда пользователь нажимает на кнопку или гиперссылку, подписанный JWT отправляется в Google Wallet API, который затем расшифровывает его с помощью сохраненных учетных данных. После аутентификации подписи JWT карта будет выпущена и пользователь сможет сохранить ее в Google Кошельке.

Как это делается

Используйте Google Кошелек Android SDK для нативных приложений Android. Для всех остальных платформ, включая приложения для iOS, обычные и мобильные сайты, электронные письма и текстовые сообщения, создайте гиперссылку в формате https://pay.google.com/gp/v/save/<signed_jwt>. По возможности лучше всего предоставить пользователю эту ссылку в виде кнопки "Добавить в Google Кошелек".

Подробную информацию о том, как использовать кнопку "Добавить в Google Кошелек", можно найти в правилах фирменного оформления Google Wallet API.

Показать пример кода

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

Android SDK

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

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

После того как пользователь сохранит выпущенную карту, она появится в его приложении "Google Кошелек" вместе с другими сохраненными картами.

Как создавать объекты и классы карт в JWT

Классы и объекты карт и билетов можно создавать заранее с помощью Google Кошелька REST API или Android SDK. После создания класса его идентификатор используется для выпуска карт.

Вы также можете создавать классы и объекты карт непосредственно перед выпуском карты, встраивая их JSON-код прямо в JWT, который используется для выпуска карты пользователю. При использовании этого метода классы и объекты карт создаются с помощью Google Wallet API, когда подписанный JWT отправляется с помощью кнопки или ссылки "Добавить в Google Кошелек".

Например, ниже показан JWT с новым классом и объектом билетов, определенных с помощью свойств payload.eventTicketClasses и payload.eventTicketObjects. Обратите внимание, что эти свойства являются массивами, поэтому они могут принимать один или несколько классов или объектов Passes. Вы также можете указать в JWT только новый объект Passes, который ссылается на существующий класс Passes по его идентификатору.

Показать пример JWT

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