Google 월렛 패스 개발 절차

Google Wallet API는 기프트 카드, 탑승권, 이벤트 티켓 등 특정 사용 사례에 최적화된 사전 정의된 패스 유형 집합을 제공합니다. 특정 패스 유형을 사용할 수 없는 사용 사례를 위한 일반 패스 유형도 있습니다.

이 도움말에서는 Google Wallet API를 사용하여 패스를 만들고 발급하는 데 필요한 기본 단계를 설명합니다. 아래에 설명된 단계를 실행하는 방법에는 여러 가지가 있지만 대략적으로 모든 패스 유형은 동일한 기본 개발 흐름에 따라 생성됩니다.

패스 생성에 관한 자세한 안내는 웹, 이메일, SMS 또는 Android 앱 가이드를 참고하세요.

용도

패스 클래스는 템플릿과 유사하게 여러 패스에서 공통적으로 사용되는 속성 집합을 정의합니다. 예를 들어 이벤트 티켓을 발급하는 경우 패스 클래스는 모든 티켓에서 동일한 필드(예: 이벤트 이름, 날짜, 시간)를 정의합니다.

발급하는 모든 패스는 패스 클래스를 참조해야 합니다. 또한 생성한 모든 패스 클래스에 고유한 ID를 할당해야 합니다. 패스 클래스는 패스를 만들 때 이 ID를 참조하는 데 사용됩니다.

작동 방식

패스 클래스는 JSON 형식으로 정의되며 Google Wallet REST API, Android SDK를 사용하거나 Google 월렛 비즈니스 콘솔에서 만들 수 있습니다.

예시 패스 클래스 표시

{
  "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"
      }
    }
  }
}
    

용도

패스 객체는 특정 사용자에게 발급되는 고유한 패스의 속성을 정의합니다. 예를 들어 이벤트 티켓의 패스 객체는 특정 티켓의 고유한 필드(예: 해당 티켓의 좌석 번호 또는 QR 코드)를 정의합니다.

패스 객체가 생성되면 Google Wallet API에서 새 패스를 저장하고 발급기관 계정과 연결합니다. 저장된 패스는 패스 객체의 고유한 속성과 연결된 패스 클래스의 템플릿 속성의 조합입니다.

또한 각 패스 객체에 고유 ID를 할당해야 하며, 이 ID는 패스 발급 시 이를 참조하는 데 사용됩니다.

작동 방식

패스 객체는 JSON 형식으로 정의되며 Google Wallet REST API 또는 Android SDK를 사용하여 만들 수 있습니다.

예시 패스 객체 표시

{
  "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는 JWT 사양에 따라 JSON 형식으로 정의됩니다. Google Wallet API로 패스를 발급하기 위한 JWT를 정의하려면 발급하려는 패스에 대한 정보를 JWT의 payload 속성에 입력합니다.

JWT 예시 표시

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

용도

패스를 발급하기 위해 Google Wallet API로 전송되는 모든 JWT는 이전에 Google 월렛 비즈니스 콘솔에 제공한 사용자 인증 정보로 서명해야 합니다. 서명 시 사용자 인증 정보를 사용하여 JWT를 암호화하여 패스를 안전하게 유지하고 Google Wallet API에서 인코딩된 패스 세부정보가 유효하며 발급기관 계정과 연결되어 있는지 인증할 수 있습니다.

작동 방식

Google 월렛 클라이언트 라이브러리와 Android SDK는 JWT에 서명할 수 있는 편리한 방법을 제공합니다. 또한 수많은 오픈소스 라이브러리가 마련되어 있어 개발자가 선택할 수 있도록 코드 서명의 복잡성을 처리할 수 있습니다.

Google Wallet REST API를 사용하여 패스를 발급하는 경우 JWT는 Google Cloud 서비스 계정 키로 서명됩니다. Google 월렛 Android SDK를 사용하는 경우 SDK가 앱 서명 인증서의 SHA-1 지문으로 JWT 서명을 자동으로 처리합니다.

사용자 인증 정보를 보호하기 위해 JWT는 서버에서만 서명하거나 앱에서 Google 월렛 Android SDK를 사용해야 합니다.

코드 서명 예시 표시

Java

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

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

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

Node.JS

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

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

Python

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

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

용도

서명된 JWT를 생성했으면 Google 월렛 사용자에게 패스를 발급할 준비가 된 것입니다. 이를 수행하려면 사용자에게 'Google 월렛에 추가' 버튼 또는 링크를 표시해야 합니다. 사용자가 버튼이나 하이퍼링크를 클릭하면 서명된 JWT가 Google Wallet API로 전송되고 Google Wallet API에서 저장된 사용자 인증 정보를 사용하여 복호화합니다. JWT 서명이 인증되면 패스가 발급되어 사용자의 Google 월렛에 저장됩니다.

작동 방식

Android 앱용 'Google 월렛에 추가' 버튼을 만들려면 버튼 생성 메서드를 제공하는 Google 월렛 Android SDK를 사용하세요. 웹, 이메일, 문자 메시지를 포함한 다른 모든 플랫폼의 경우 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 Wallet REST API 또는 Android SDK를 사용하여 미리 만들 수 있습니다. 생성된 후에는 ID를 참조하여 패스를 발급하는 데 사용됩니다.

또는 사용자에게 패스를 발급하는 데 사용되는 JWT에 JSON을 직접 삽입하여 '적시에' 패스 클래스와 패스 객체를 만들 수도 있습니다. 이 방법에서는 'Google 월렛에 추가' 버튼 또는 링크를 사용하여 서명된 JWT가 전송될 때 Google Wallet API가 패스 클래스 및 패스 객체를 만듭니다.

예를 들어 다음은 payload.eventTicketClassespayload.eventTicketObjects 속성을 사용하여 정의된 새 패스 클래스와 패스 객체가 있는 JWT를 보여줍니다. 이러한 속성은 배열이므로 하나 이상의 패스 클래스 또는 패스 객체를 허용할 수 있습니다. JWT에서 ID로 기존 패스 클래스를 참조하는 새 패스 객체만 지정할 수도 있습니다.

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": ""
        }
      }]
    }
  }