Android SDK를 시작하기 전에 기본 요건을 완료했는지 확인하세요.
Android SDK를 사용하면 Google 월렛에 패스를 추가할 수 있습니다. 앱에 Google 월렛 버튼을 추가하면 사용자가 Google 월렛에 패스를 추가하는 간단하면서도 재미있는 경험을 할 수 있습니다.
다음 단계에 따라 Android 애플리케이션에 Google 월렛 버튼을 추가합니다.
1. Passes 객체 만들기
참고: 패스 객체를 만들려면 패스 클래스가 필요합니다. 아직 패스를 만들지 않았다면 패스 클래스 만들기 방법에 대한 안내를 따릅니다.
다음 필수 속성을 포함하여 상응하는 GenericObject
를 정의합니다.
classId
: 기본 요건에서 생성된 패스 클래스 ID입니다.id
: 객체의 고유 ID입니다.
genericType
: 카드가 속한 유형입니다. 카드가 사용 가능한 옵션과 일치하지 않으면GENERIC_TYPE_UNSPECIFIED
로 설정합니다.
cardTitle
: 패스의 제목입니다.
header
: 사용자 이름과 같은 패스의 헤더입니다.
logo
subheader
이러한 속성이 일반 패스에 표시되는 방법에 관한 자세한 내용은 레이아웃 템플릿을 참고하세요.
다음은 일반 일반 샘플의 정의입니다.
JSON
{
"id": "ISSUER_ID.OBJECT_ID",
"classId": "ISSUER_ID.CLASS_ID",
"genericType": "GENERIC_TYPE_UNSPECIFIED",
"cardTitle": {
"defaultValue": {
"language": "en",
"value": "Card title"
}
},
"subheader": {
"defaultValue": {
"language": "en",
"value": "Attendee"
}
},
"header": {
"defaultValue": {
"language": "en",
"value": "Alex McJacobs"
}
},
"logo": {
"sourceUri": {
"uri": "https://storage.googleapis.com/wallet-lab-tools-codelab-artifacts-public/pass_google_logo.jpg"
}
}
}
2. 객체로 서명되지 않은 JWT 만들기
GenericObject
가 생성되면 다음 스니펫과 같이 payload.GenericObjects
속성을 사용하여 서명되지 않은 JWT로 래핑합니다.
JSON
{
"iss": "OWNER_EMAIL_ADDRESS",
"aud": "google",
"typ": "savetowallet",
"iat": "UNIX_TIME",
"origins": [],
"payload": {
"genericObjects": [ NEW_OBJECT ]
}
}
3. UI에 Google 월렛 버튼 포함
Google 월렛은 애플리케이션에서 Google 월렛에 추가 과정을 트리거하는 데 사용할 수 있는 익숙한 버튼을 제공합니다. 버튼의 벡터 애셋은 버튼 가이드라인에서 확인할 수 있습니다.
Android 스튜디오의 File > New > Vector
Asset
아래에서 벡터 애셋을 가져올 수 있습니다. 마법사에서 'Local file'을 선택하고 이름 (예:
add_to_google_wallet_button.xml
)를 클릭하고 로컬 드라이브에서 파일을 찾아 가져옵니다.
이제 가져온 드로어블을 사용하여 사용자 인터페이스에 버튼을 추가할 수 있습니다.
<ImageButton
android:id="@+id/addToGoogleWalletButton"
android:layout_width="match_parent"
android:layout_height="48dp"
android:minWidth="200dp"
android:clickable="true"
android:src="@drawable/add_to_google_wallet_button" />
버튼의 layout_height
는 48dp이고 너비는 200dp 이상이어야 합니다.
4. 대상 기기에서 Google Wallet API를 사용할 수 있는지 확인
새 객체를 저장하기 전에 PayClient
클래스에서 getPayApiAvailabilityStatus
메서드를 호출하여 대상 기기에서 Google Wallet API를 사용할 수 있는지 확인합니다. 먼저 멤버를 활동에 추가하여 버튼을 표시하고 활동이 생성될 때 이를 인스턴스화합니다.
Kotlin
import com.google.android.gms.pay.PayClient
private lateinit var walletClient: PayClient
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
walletClient = Pay.getClient(this)
// Additional logic in your onCreate method
}
Java
import com.google.android.gms.pay.PayClient;
private final PayClient walletClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
walletClient = Pay.getClient(application);
// Additional logic in your onCreate method
}
이제 클라이언트를 사용하여 API를 사용할 수 있는지 확인합니다.
Kotlin
import com.google.android.gms.pay.PayApiAvailabilityStatus
private fun fetchCanUseGoogleWalletApi() {
walletClient
.getPayApiAvailabilityStatus(PayClient.RequestType.SAVE_PASSES)
.addOnSuccessListener { status ->
if (status == PayApiAvailabilityStatus.AVAILABLE) {
// The API is available, show the button in your UI
} else {
// The user or device is not eligible for using the Pay API
}
}
.addOnFailureListener {
// Hide the button and optionally show an error message
}
}
Java
import com.google.android.gms.pay.PayApiAvailabilityStatus;
private void fetchCanAddPassesToGoogleWallet() {
walletClient
.getPayApiAvailabilityStatus(PayClient.RequestType.SAVE_PASSES)
.addOnSuccessListener(status -> {
if (status == PayApiAvailabilityStatus.AVAILABLE) {
// The API is available, show the button in your UI
} else {
// The user or device is not eligible for using the Pay API
};
})
.addOnFailureListener(exception -> {
// Google Play Services is too old, or API availability not verified
// Hide the button and optionally show an error message
});
}
마지막으로 API의 가용성을 확인해야 할 때 애플리케이션에서 위에 정의된 메서드를 호출합니다.
5. Google 월렛에 객체 추가
2단계의 서명되지 않은 JWT를savePasses
메서드에 전달하여 GenericObject
을 추가할 수 있습니다.
Google 월렛 버튼을 클릭하여 추가 작업을 시작할 수 있습니다.
Kotlin
import android.os.Bundle
import android.view.View
import com.google.android.gms.samples.wallet.databinding.ActivityCheckoutBinding
private val addToGoogleWalletRequestCode = 1000
private lateinit var layout: ActivityCheckoutBinding
private lateinit var addToGoogleWalletButton: View
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Use view binding to access the UI elements
layout = ActivityCheckoutBinding.inflate(layoutInflater)
setContentView(layout.root)
addToGoogleWalletButton = layout.addToGoogleWalletButton
addToGoogleWalletButton.setOnClickListener {
walletClient.savePasses(newObjectJson, this, addToGoogleWalletRequestCode)
}
// Additional logic in your onCreate method
}
Java
import android.os.Bundle;
import android.view.View;
import com.google.android.gms.samples.wallet.databinding.ActivityCheckoutBinding;
private static final int ADD_TO_GOOGLE_WALLET_REQUEST_CODE = 999;
private ActivityCheckoutBinding layout:
private View addToGoogleWalletButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Use view binding to access the UI elements
layout = ActivityCheckoutBinding.inflate(getLayoutInflater());
setContentView(layout.getRoot());
addToGoogleWalletButton = layout.addToGoogleWalletButton;
addToGoogleWalletButton.setOnClickListener(v -> {
walletClient.savePasses(newObjectJson, this, ADD_TO_GOOGLE_WALLET_REQUEST_CODE);
});
// Additional logic in your onCreate method
}
savePasses
메서드는 저장 흐름을 트리거하고 저장 흐름이 완료된 후 onActivityResult
메서드를 호출합니다. onActivityResult
의 구현은 다음과 유사합니다.
Kotlin
import android.content.Intent
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == addToGoogleWalletRequestCode) {
when (resultCode) {
RESULT_OK -> {
// Pass saved successfully
}
RESULT_CANCELED -> {
// Save operation canceled
}
PayClient.SavePassesResult.SAVE_ERROR -> data?.let { intentData ->
val errorMessage = intentData.getStringExtra(PayClient.EXTRA_API_ERROR_MESSAGE)
// Handle error
}
else -> {
// Handle unexpected (non-API) exception
}
}
}
}
Java
import android.content.Intent;
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == ADD_TO_GOOGLE_WALLET_REQUEST_CODE) {
switch (resultCode) {
case RESULT_OK: {
// Pass saved successfully
break;
}
case RESULT_CANCELED: {
// Save operation canceled
break;
}
case PayClient.SavePassesResult.SAVE_ERROR: {
if (data != null) {
String apiErrorMessage = data.getStringExtra(PayClient.EXTRA_API_ERROR_MESSAGE);
// Handle error
}
break;
}
default: {
// Handle unexpected (non-API) exception
}
}
}
}
패스가 성공적으로 추가되면 resultCode
에는 Activity.RESULT_OK
값이 포함됩니다.
[테스트 전용] 패스
아직 데모 모드인 경우 생성한 모든 패스에는 패스 제목에 추가 텍스트 '[테스트 전용]'이 포함됩니다. 이는 데모 패스를 실시간 패스와 구별하기 위한 것입니다. 팀으로부터 프로덕션 승인을 받으면 사용자가 연결된 기기에서 월렛 앱을 다시 열 때 이러한 데모 모드 패스에 더 이상 텍스트가 표시되지 않습니다.
다음 단계
- 일반 패스의 사용 사례를 평가하고 비즈니스 요구사항에 적합한 사용 사례 구현
- 브랜드 가이드라인에 따라 일반 패스의 모양을 맞춤설정합니다.
- Google Pay 및 월렛 콘솔의 'Google Wallet API' 섹션에서 최종 검토를 위해 UX 절차를 제출합니다.
- 통합을 테스트하고 게시하세요
- 궁금하신 사항이 더 있나요? FAQ를 참고하세요.