Membangun Pengalaman Checkout secara Cepat di Android dengan Google Pay (Kotlin)

1. Pengantar

Google Pay API memberi pengguna kesempatan untuk membayar di mana saja, menggunakan informasi pembayaran yang disimpan di Akun Google mereka. Di lab ini, Anda akan menggunakan library klien Google Pay untuk Android guna meningkatkan pengalaman pembayaran dari contoh aplikasi seluler yang disederhanakan, dengan menciptakan pengalaman yang lebih cepat, nyaman, dan aman, yang pada gilirannya menghasilkan lebih banyak konversi dan kepuasan pelanggan.

Auto T-Shirt Shop adalah toko inovatif yang memanfaatkan kemajuan terkini di bidang kecerdasan buatan dan menggunakan informasi seperti preferensi gaya, cuaca, waktu dalam setahun, dan tren mode, untuk memberi saran tentang item yang paling tepat untuk dibeli.

Metrik engagement sudah melampaui batas. Sayangnya, angka tersebut juga mencerminkan banyaknya pengabaian selama proses pembayaran. Bertekad untuk mengatasi hal tersebut, salah satu pemilik project ingat pernah melihat video yang menunjukkan hasil menjanjikan yang diberikan Google Pay untuk situs lain yang serupa sehingga memutuskan untuk mencobanya dan memercayai Anda untuk menangani integrasi tersebut.

Yang akan Anda bangun

Codelab ini akan memandu Anda dalam mengintegrasikan Google Pay ke dalam aplikasi yang sudah ada, termasuk menentukan apakah pengguna dapat membayar menggunakan metode pembayaran yang didukung oleh Google Pay, penempatan dan desain tombol pembayaran, serta pelaksanaan transaksi.

f5f96f8afc94448c.png

Yang akan Anda pelajari

  • Cara mengintegrasikan Google Pay ke aplikasi yang sudah ada
  • Cara memilih di antara beberapa metode pembayaran pilihan Anda
  • Cara menentukan apakah pengguna siap membayar menggunakan Google Pay

Yang akan Anda perlukan

  • Komputer dengan akses internet
  • Lingkungan pengembangan yang siap untuk membangun aplikasi Android (sebaiknya gunakan Android Studio)
  • Perangkat Android dengan versi layanan Google Play terbaru terinstal

2. Mulai

Meng-clone repositori dari GitHub:

Gunakan perintah berikut untuk meng-clone repositori ke folder di komputer Anda:

$ git clone https://github.com/google-pay/android-quickstart

Atau, jika Anda memilih file ZIP:

Menelusuri aplikasi contoh

Seperti yang Anda lihat, repositori ini memiliki struktur file yang tidak rumit. Tujuan utama codelab ini ialah memberi Anda kemampuan untuk mengadaptasi integrasi ini ke aplikasi Anda yang sudah ada dan yang akan datang, apa pun bahasa pemrograman, library, atau alat yang Anda pilih untuk digunakan.

3. Mengintegrasikan Google Pay ke dalam aplikasi (atau aplikasi Anda sendiri)

Menjelajahi aplikasi

Setelah aplikasi Anda dibangun, Anda dapat melihat pratinjaunya menggunakan emulator atau perangkat yang sebenarnya. Sebaiknya gunakan perangkat dengan Akun Google dan metode pembayaran yang sudah dikaitkan dengannya.

Aplikasi yang dibangun dengan codelab ini adalah toko seluler demo yang, menggunakan model machine learning yang sangat canggih, akan menyarankan satu kaus kepada pengunjung berdasarkan sejumlah fitur yang sangat kompleks. Sekarang, jika Anda bertanya pada diri sendiri mengapa situs tersebut merekomendasikan kaos yang berbeda setiap kali Anda memuat ulang situs..., sejujurnya, model machine learning yang sangat canggih hanyalah generator acak (maaf).

Toko demo ini telah dibangun sedemikian rupa sehingga menyerupai tampilan aplikasi Anda yang sudah ada atau yang akan datang, sebelum Anda menambahkan sarana pembelian. Bahkan, meskipun kami menyarankan Anda menggunakan aplikasi demo ini, Anda bebas melanjutkan dan menggunakan codelab ini untuk mengintegrasikan Google Pay ke dalam aplikasi Anda yang sudah ada.

Sekarang, jika Anda belum melakukannya, jalankan aplikasi demo seperti saat ini.

175215c8c8696ede.png

Jika Anda bisa melihat demo aplikasinya, tidak ada yang aneh, bukan? Tampilan detail produk, dengan gambar, harga, deskripsi, dan tombol untuk membawa Anda ke formulir pembayaran biasa.

Tujuan dari lab ini adalah untuk menggantikan alur yang pada dasarnya membosankan ini dengan pengalaman dua ketukan yang didukung oleh Google Pay.

Mari kita rencanakan!

Untuk lebih memahami integrasi ini, prosesnya dibagi menjadi langkah-langkah mendasar berikut:

  1. Menambahkan dependensi yang diperlukan
  2. Menentukan dapat tidaknya membayar dengan Google Pay
  3. Menampilkan tombol untuk membayar dengan Google Pay
  4. Membuat dan mengirim permintaan pembayaran
  5. Mengumpulkan hasil

4. Menambahkan dependensi yang diperlukan

Menambahkan layanan Google Play ke build.gradle Anda

Hal pertama yang perlu Anda lakukan untuk mulai menggunakan Google Pay API adalah menambahkan dependensi ke layanan Google Play yang berisi paket yang Anda perlukan. Untuk melakukannya, tambahkan item implementation berikut ke daftar dependencies di file build.gradle dalam modul aplikasi Anda. Dalam codelab ini, modul tersebut bernama app:

implementation "com.google.android.gms:play-services-wallet:18.0.0"

Mengaktifkan API di file manifes Anda

Terakhir, tambahkan elemen meta-data ke dalam node application file manifes Anda. Langkah ini memungkinkan sistem mengetahui bahwa Anda bermaksud menggunakan API ini dan mengaktifkan akses ke API tersebut:

<meta-data
    android:name="com.google.android.gms.wallet.api.enabled"
    android:value="true" />

5. Merencanakan antarmuka pengguna Anda dan tempat untuk menampilkan tombol Google Pay

Tata letak dan pengalaman keseluruhan dalam tampilan Anda merupakan aspek penting yang memengaruhi seberapa besar kemungkinan pengguna Anda menyelesaikan transaksi pembayaran yang berhasil. Kemampuan memilih metode pembayaran, hanya dalam beberapa ketukan menggunakan Google Pay, memungkinkan serangkaian opsi yang lebih luas tentang di mana dan kapan Anda dapat menawarkan cara membayar kepada pengguna di aplikasi Anda. Misalnya, Anda dapat menambahkan opsi checkout cepat di awal proses, di area seperti tampilan detail item, untuk memungkinkan pengguna membayar item yang mereka sukai dengan cepat.

Setelah Anda memutuskan cara mengatur UI dan navigasi Anda, langkah selanjutnya adalah menempatkan tombol yang memicu transaksi pembayaran menggunakan Google Pay. Gaya tombol ini diharapkan sesuai dengan rangkaian panduan yang memastikan konsistensi dan tombol mudah dikenali pengguna ketika mereka melihatnya di aplikasi Anda:

a18b3311d84d9dcc.png

Untuk mempermudah tugas ini bagi Anda, kami telah menggabungkan semua opsi yang tersedia, mempersiapkan resolusi dan lokalitas yang berbeda, serta membuatnya tersedia untuk didownload. Paket ini mencakup resource layout, drawable, dan values yang dapat Anda tempelkan langsung ke project Anda.

Anda dapat menemukan resource yang perlu Anda tambahkan ke definisi tampilan Anda, activity_checkout.xml, di bawah direktori layout. Untuk menambahkannya ke tampilan Anda, cukup tempatkan di posisi yang diinginkan menggunakan elemen include:

<include
    android:id="@+id/googlePayButton"
    layout="@layout/buy_with_googlepay_button"
    android:layout_width=<your_width_dimension>
    android:layout_height="@dimen/buy_button_height"
    android:visibility="gone"/>

6. Melakukan inisialisasi dan konfigurasi Google Pay API

Membuat instance klien API

Untuk mulai menggunakan API, Anda perlu membuat instance objek klien yang akan Anda gunakan untuk melakukan panggilan ke Google Pay API. Anda dapat melakukannya segera setelah aktivitas Anda dibuat:

private lateinit var paymentsClient: PaymentsClient

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_checkout)

    paymentsClient = createPaymentsClient(this)
}

fun createPaymentsClient(activity: Activity): PaymentsClient {
    val walletOptions = Wallet.WalletOptions.Builder()
            .setEnvironment(WalletConstants.ENVIRONMENT_TEST).build()
    return Wallet.getPaymentsClient(activity, walletOptions)
}

Klien pembayaran diinisialisasi dengan objek WalletOptions. Menetapkan lingkungan ke ENVIRONMENT_TEST memungkinkan Anda bereksperimen dengan informasi pembayaran tiruan di seluruh integrasi. Setelah siap membuat operasi yang mendukung transaksi sebenarnya, Anda dapat mengupdate properti lingkungan menjadi ENVIRONMENT_PRODUCTION.

Kerangka

Setiap kali Anda berkomunikasi dengan Google Pay API, ada sejumlah parameter konfigurasi yang perlu Anda sertakan dalam permintaan Anda, seperti versi API yang Anda targetkan. Untuk keperluan codelab ini, objek ini juga berisi informasi tentang metode pembayaran yang diterima dalam aplikasi Anda. Struktur akhirnya akan terlihat sebagai berikut:

{
    apiVersion: number,
    apiVersionMinor: number,
    allowedPaymentMethods: Array
}

Properti allowedPaymentMethods mengambil daftar metode pembayaran. Untuk setiap metode pembayaran, Anda diharuskan menyertakan properti berikut:

{
    type: 'CARD',
    parameters: {
        allowedCardNetworks: Array.<string>,
        allowedAuthMethods: Array.<string>
    }
}

Selain type dan parameters, Anda nanti akan menambahkan properti tokenizationSpecification, yang tidak diperlukan untuk menentukan apakah pengguna yang bersangkutan dapat membayar dengan Google Pay, tetapi digunakan oleh panggilan PaymentDataRequest untuk menentukan cara menangani data terkait metode pembayaran yang dipilih. Namun, mari kita ambil langkah satu per satu.

Konfigurasi metode pembayaran

Dalam contoh ini, Anda hanya akan menerima pembayaran kartu untuk Mastercard dan Visa, keduanya dalam formulir yang ditokenisasi dan nomor rekening utama (PAN). Berikut ini tampilan metode pembayaran Anda:

private val baseCardPaymentMethod = JSONObject().apply {
    put("type", "CARD")
    put("parameters", JSONObject().apply {
        put("allowedCardNetworks", JSONArray(listOf("VISA", "MASTERCARD")))
        put("allowedAuthMethods", JSONArray(listOf("PAN_ONLY", "CRYPTOGRAM_3DS")))
    })
}

Penutup

Mari kita ringkas.

Anda telah menentukan satu metode pembayaran yang akan diterima di aplikasi Anda, dan Anda akan bekerja dengan API versi 2.0. Berikut ini konfigurasi yang dihasilkan:

private val baseCardPaymentMethod = JSONObject().apply {
    put("type", "CARD")
    put("parameters", JSONObject().apply {
        put("allowedCardNetworks", JSONArray(listOf("VISA", "MASTERCARD")))
        put("allowedAuthMethods", JSONArray(listOf("PAN_ONLY", "CRYPTOGRAM_3DS")))
    })
}

private val googlePayBaseConfiguration = JSONObject().apply {
    put("apiVersion", 2)
    put("apiVersionMinor", 0)
    put("allowedPaymentMethods",  JSONArray().put(baseCardPaymentMethod))
}

Setelah konfigurasi dasar Anda siap, mari kita ke bagian yang menyenangkan.

7. Menentukan kesiapan membayar dengan Google Pay

Salah satu tujuan utama Google Pay ialah memberikan pengalaman pembayaran yang lebih cepat dan nyaman bagi pengguna Anda. Hal ini tidak hanya berlaku dalam situasi ketika pengguna Anda dapat memanfaatkan Google Pay untuk melakukan hal tersebut, tetapi juga dalam situasi ketika mereka tidak dapat melakukannya. Penggunaan permintaan isReadyToPay ini memungkinkan Anda menentukan kesiapan untuk membayar dengan Google Pay, dan peluang bagi Anda untuk mengubah pengalaman di situs Anda.

Apakah pengguna Anda dapat membayar dengan Google Pay?

Langkah pertama yang perlu Anda lakukan ialah memeriksa apakah pengguna tertentu yang akan membayar di aplikasi Anda dapat menggunakan Google Pay. Permintaan ini mengharuskan Anda menentukan versi Google Pay API dan metode pembayaran yang diizinkan di situs Anda. Inilah isi objek konfigurasi dasar yang ditentukan pada langkah sebelumnya:

val readyToPayRequest =
        IsReadyToPayRequest.fromJson(googlePayBaseConfiguration.toString())

val readyToPayTask = paymentsClient.isReadyToPay(readyToPayRequest)
task.addOnCompleteListener { task ->
    try {
        task.getResult(ApiException::class.java)?.let(::setGooglePayAvailable)
    } catch (exception: ApiException) {
        // Error determining readiness to use Google Pay.
        // Inspect the logs for more details.
    }
}

Seperti yang Anda lihat, jika panggilan ditampilkan dengan respons tidak berhasil, tidak ada tindakan lebih lanjut yang dapat diambil dalam konteks Google Pay. Dalam situasi ini, langkah selanjutnya yang paling tepat ialah menampilkan UI tambahan yang mendukung alat pembayaran lainnya.

Di sisi lain, jika respons berhasil, Anda kini telah siap untuk memungkinkan pengguna Anda mendapatkan manfaat dari penggunaan Google Pay sehingga Anda dapat melanjutkan dan menampilkan tombol Google Pay untuk memulai proses pembayaran pada aktivasi pengguna (misalnya: klik tombol).

Menampilkan tombol untuk membayar dengan Google Pay

Di tahap ini, Anda dapat melanjutkan dan menampilkan tombol Google Pay:

private fun setGooglePayAvailable(available: Boolean) {
    if (available) {
        googlePayButton.visibility = View.VISIBLE
        googlePayButton.setOnClickListener { requestPayment() }
    } else {
       // Unable to pay using Google Pay. Update your UI accordingly.
    }
}

private fun requestPayment() {
  // TODO: Perform transaction
}

Periksa apakah Anda juga mendefinisikan fungsi untuk menangani peristiwa klik tombol. Di bagian selanjutnya, Anda akan menggunakan fungsi ini untuk meminta metode pembayaran.

8. Waktunya pembayaran.

Menyiapkan permintaan pembayaran

Di tahap ini, Anda telah memuat Google Pay API dan menentukan bahwa pengguna di aplikasi Anda dapat menggunakan Google Pay untuk melakukan pembayaran. Karena itu, Anda dapat menampilkan tombol pembayaran Google Pay di UI dan kini pengguna Anda telah siap untuk memulai transaksi. Sekarang saatnya memuat halaman pembayaran berisi metode pembayaran yang tersedia untuk berbagai pengguna yang login.

Sama seperti yang Anda lakukan sebelumnya saat menentukan permintaan isReadyToPay, panggilan ini juga memerlukan properti di objek konfigurasi dasar yang ditentukan sebelumnya (apiVersion, apiVersionMinor, dan allowedPaymentMethods) selain beberapa yang baru. Kali ini ada properti baru bernama tokenizationSpecification, dan parameters tambahan dalam metode pembayaran Anda yang relevan untuk tujuan permintaan ini saja. Selain itu, transactionInfo dan merchantInfo juga perlu ditambahkan.

Menyertakan informasi tambahan yang diperlukan dalam metode pembayaran Anda

Mulailah dengan membuat salinan metode pembayaran kartu dasar yang digunakan sebelumnya. Metode pembayaran kartu ini sekarang memerlukan properti tokenizationSpecification untuk menentukan cara menangani data terkait metode pembayaran yang dipilih, serta persyaratan data lebih lanjut yang diperlukan untuk transaksi sebenarnya: dalam contoh ini, alamat penagihan lengkap dan nomor telepon diperlukan.

Properti tokenizationSpecification

Spesifikasi tokenisasi menentukan cara menangani dan menggunakan metode pembayaran yang dipilih oleh pengguna Anda untuk menyelesaikan transaksi.

Ada dua jenis strategi penanganan yang didukung. Jika Anda memproses transaksi pembayaran dari dalam server yang mendukung PCI DSS, gunakan jenis spesifikasi DIRECT. Dalam contoh ini, Anda menggunakan gateway pembayaran untuk memproses pembayaran sehingga Anda perlu menetapkan jenis spesifikasi PAYMENT_GATEWAY. Seperti inilah tampilan spesifikasi tokenisasi Anda:

private val tokenizationSpecification = JSONObject().apply {
    put("type", "PAYMENT_GATEWAY")
    put("parameters", JSONObject(mapOf(
            "gateway" to "example",
            "gatewayMerchantId" to "exampleGatewayMerchantId")))
}

Di bagian parameters, Anda dapat menentukan gateway dari daftar penyedia yang didukung Google Pay API, beserta konfigurasi tambahan yang diperlukan oleh setiap gateway. Untuk keperluan lab ini, cukup gunakan gateway example yang memberikan hasil pengujian untuk transaksi yang dijalankan.

Parameter tambahan

Demikian pula, kini Anda dapat memberikan detail lebih lanjut tentang informasi yang perlu Anda minta agar berhasil melakukan transaksi. Lihat bagaimana dalam contoh ini, Anda perlu menambahkan properti billingAddressRequired dan billingAddressParameters guna menunjukkan bahwa untuk transaksi ini, alamat penagihan pengguna diperlukan dalam format lengkap dan mencakup nomor telepon.

private val cardPaymentMethod = JSONObject().apply {
    put("type", "CARD")
    put("tokenizationSpecification", tokenizationSpecification)
    put("parameters", JSONObject().apply {
        put("allowedCardNetworks", JSONArray(listOf("VISA", "MASTERCARD")))
        put("allowedAuthMethods", JSONArray(listOf("PAN_ONLY", "CRYPTOGRAM_3DS")))
        put("billingAddressRequired", true)
        put("billingAddressParameters", JSONObject(mapOf("format" to "FULL")))
    })
}

Menambahkan informasi transaksi

Properti transactionInfo berisi objek dengan detail keuangan tentang transaksi, yaitu harga dan kode mata uang (format alfa ISO 4217) bersama dengan status harga, yang dapat bersifat final atau perkiraan, bergantung pada sifat transaksi (misalnya: harga dapat bervariasi bergantung pada alamat pengiriman yang ditentukan):

private val transactionInfo = JSONObject().apply {
    put("totalPrice", "123.45")
    put("totalPriceStatus", "FINAL")
    put("currencyCode", "USD")
}

Menambahkan informasi penjual

Permintaan pembayaran mengambil informasi tentang penjual yang melakukan permintaan berdasarkan properti merchantInfo. Dalam codelab ini Anda akan berfokus pada dua di antaranya:

  • merchantId mengharapkan ID dikaitkan dengan akun Anda setelah aplikasi Anda disetujui untuk dioperasikan dalam produksi oleh Google. Anda bisa mendapatkan ID penjual dengan akun Anda di Konsol Bisnis Google Pay. Perhatikan bahwa ID ini tidak dievaluasi ketika menggunakan lingkungan TEST.
  • merchantName adalah nama aplikasi atau organisasi Anda yang terlihat oleh pengguna. Nama ini mungkin ditampilkan di halaman pembayaran Google Pay untuk memberikan informasi lebih lanjut kepada pengguna tentang siapa yang meminta pengoperasian.

Setelah siap, cukup tambahkan informasi tentang penjual ke objek paymentDataRequest:

private val merchantInfo = JSONObject().apply {
    put("merchantName", "Example Merchant")
    put("merchantId", "01234567890123456789")
}

Meminta informasi pembayaran dan memproses hasilnya

Sekarang, gabungkan konfigurasi yang telah ditentukan sebelumnya ke objek akhir dan teruskan ke permintaan loadPaymentData:

private val paymentDataRequestJson = JSONObject(googlePayBaseConfiguration.toString()).apply {
    put("allowedPaymentMethods", JSONArray().put(cardPaymentMethod))
    put("transactionInfo", transactionInfo)
    put("merchantInfo", merchantInfo)
}

Di tahap ini, Anda telah memiliki semua yang Anda butuhkan untuk meminta Google Pay API guna memperoleh metode pembayaran yang valid. Untuk melakukannya, gunakan metode loadPaymentData pada objek PaymentsClient dengan meneruskan konfigurasi yang baru saja Anda tetapkan:

val paymentDataRequest =
        PaymentDataRequest.fromJson(paymentDataRequestJson.toString())

AutoResolveHelper.resolveTask(
        paymentsClient.loadPaymentData(paymentDataRequest),
        this, LOAD_PAYMENT_DATA_REQUEST_CODE)

Memanggil metode ini akan memicu tampilan halaman pembayaran Google Pay. Jika tidak ada error konfigurasi, Anda dapat melihat daftar metode pembayaran yang valid terkait dengan akun yang saat ini login.

Setelah dipilih, halaman akan ditutup, lalu hasilnya dikirim kembali ke aktivitas Anda dan diambil melalui metode onActivityResult:

public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
    when (requestCode) {
        LOAD_PAYMENT_DATA_REQUEST_CODE -> {
            when (resultCode) {
                Activity.RESULT_OK ->
                    PaymentData.getFromIntent(data)?.let(::handlePaymentSuccess)

                Activity.RESULT_CANCELED -> {
                    // The user cancelled without selecting a payment method.
                }

                AutoResolveHelper.RESULT_ERROR -> {
                    AutoResolveHelper.getStatusFromIntent(data)?.let {
                        handleError(it.statusCode)
                    }
                }
            }
        }
    }
}

Jika pemilihan berhasil, hasilnya akan dipenuhi dengan objek PaymentData, termasuk informasi yang relevan terkait metode pembayaran yang dipilih:

{
  "apiVersionMinor": 0,
  "apiVersion": 2,
  "paymentMethodData": {
    "description": "Visa •••• 1234",
    "tokenizationData": {
      "type": "PAYMENT_GATEWAY",
      "token": "examplePaymentMethodToken"
    },
    "type": "CARD",
    "info": {
      "cardNetwork": "VISA",
      "cardDetails": "1234",
      "billingAddress": {
        "phoneNumber": ...,
        ...
      }
    }
  }
}

Anda kini dapat menggunakan informasi metode pembayaran ini untuk melakukan transaksi yang sebenarnya.

private fun handlePaymentSuccess(paymentData: PaymentData) {
    val paymentMethodToken = paymentData
            .getJSONObject("tokenizationData")
            .getString("token")

    // Sample TODO: Use this token to perform a payment through your payment gateway
}

9. Selamat!

Anda telah berhasil mengintegrasikan Google Pay API ke aplikasi Anda sendiri.

Sekarang, untuk menerapkannya ke produksi, jangan lupa untuk melihat checklist integrasi. Setelah selesai dan ditinjau, Anda akan menerima ID penjual (merchantId) untuk ditambahkan ke konfigurasi klien Anda. Demikian pula, jika Anda berencana menggunakan (atau sudah menggunakan) pemroses pembayaran atau gateway pihak ketiga, lihat daftar penyedia yang didukung di Google Pay dan konfigurasikan penyedia Anda. Jika Anda berintegrasi secara langsung dengan Google Pay, lihat bagian dokumentasi tentang topik ini.

Yang telah kita bahas

  • Mengimpor dan mengonfigurasikan Google API di aplikasi Anda.
  • Menentukan dukungan untuk API dan memberikan reaksi yang sesuai.
  • Menambahkan tombol untuk memungkinkan pengguna membayar menggunakan Google Pay.
  • Memuat dan memproses informasi pembayaran pengguna yang disimpan sebelumnya.

Langkah berikutnya

  • Uji Google Pay di aplikasi sebenarnya jika Anda belum melakukannya.
  • Dapatkan ID penjual di Konsol Bisnis Google Pay.
  • Tinjau checklist integrasi.
  • Lihat dua jenis integrasi yang berbeda dan putuskan mana yang lebih cocok untuk Anda: mengintegrasikan secara langsung atau menggunakan gateway pembayaran atau pemroses.

Pelajari lebih lanjut

Apakah informasi ini berguna menurut Anda?

Sangat berguna Cukup memenuhi harapan. Tidak juga.

Apakah Anda ingin melihat codelab lain untuk membantu Anda dengan jenis integrasi lainnya (Integrasi langsung, API tiket dan item berharga)?

Ya, ide yang sangat bagus! Saya sudah cukup senang dengan apa yang saya dapatkan.