패스를 만들고 JWT로 인코딩한 후에는 Android 앱에서 패스를 발급할 수 있습니다. 이렇게 하려면 사용자의 기기에서 Google 월렛 API를 사용할 수 있는지 확인하고 'Google 월렛에 추가' 버튼을 표시한 다음 사용자가 버튼을 탭하면 패스를 Google 월렛에 저장해야 합니다.
기본 요건
패스를 발급하려고 하기 전에 다음을 완료했는지 확인하세요.
1. Google 월렛 Android SDK 설치
Google 월렛 Android SDK를 사용하려면 앱 수준 build.gradle
파일의 dependencies
섹션에 com.google.android.gms:play-services-pay
를 추가합니다.
implementation "com.google.android.gms:play-services-pay:16.5.0"
2. 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
}
자바
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
}
다른 디자인 패턴을 사용하는 경우 도메인에 맞는 비즈니스 로직을 적절하게 배치하는 것이 좋습니다. 예를 들어, MVVM 패턴을 사용한다면 활동 또는 프래그먼트 (예: UI 요소, 활동 결과)에 UI 관련 비즈니스 로직을 배치하고 뷰 모델 (예: 클라이언트 인스턴스화, 네트워크 호출 트리거)에는 운영 로직을 배치합니다.
그런 다음 PayClient
를 사용하여 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
}
}
자바
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의 사용 가능 여부를 확인해야 할 때 애플리케이션에서 방금 정의한 메서드를 호출합니다.
API를 사용할 수 없는 경우 처리
API를 사용할 수 없는 이유로는 Android 또는 Google Play 서비스 버전이 최신이 아니거나 사용자의 국가에서 Google 월렛을 사용할 수 없는 등 여러 가지가 있습니다.
API를 사용할 수 없는 경우 버튼을 숨기고 다른 통합 (예: JWT 링크 사용)으로 대체하는 것이 좋습니다. 단, API를 사용할 수 없는 사용자도 향후 API 사용이 가능할 수 있습니다.
3. '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 월렛에 패스 추가
서명되지 않은 JWT를 savePasses
메서드에 전달하여 OfferObject
를 추가할 수 있습니다.
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
}
자바
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
}
}
}
}
자바
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
값이 포함됩니다.