Referensi klien JavaScript Login dengan Google

Referensi ini menjelaskan metode dan atribut klien JavaScript yang akan Anda gunakan untuk menerapkan Login dengan Google di aplikasi web Anda.

Jika Anda mengalami masalah saat menggunakan library, laporkan ke kami Repositori GitHub.

Penyiapan Auth

Muat library platform Google API untuk membuat objek gapi:

<script src="https://apis.google.com/js/platform.js?onload=init" async defer></script>

Setelah library platform dimuat, muat library auth2:

function init() {
  gapi.load('auth2', function() {
    /* Ready. Make a call to gapi.auth2.init or some other API */
  });
}

gapi.auth2.init(params)

Melakukan inisialisasi objek GoogleAuth. Anda harus memanggil metode ini sebelum memanggil metode gapi.auth2.GoogleAuth.

Saat melakukan inisialisasi objek GoogleAuth, Anda perlu mengonfigurasi objek tersebut dengan client ID OAuth 2.0 dan opsi tambahan apa pun yang ingin Anda tentukan. Kemudian, jika pengguna sudah login, objek GoogleAuth akan memulihkan status login pengguna dari sesi sebelumnya.

Argumen
params Objek yang berisi key-value pair data konfigurasi klien. Lihat gapi.auth2.ClientConfig untuk yang berbeda dapat dikonfigurasi. Contoh:
{
  client_id: 'CLIENT_ID.apps.googleusercontent.com'
}
Hasil
gapi.auth2.GoogleAuth Objek gapi.auth2.GoogleAuth. Gunakan then() untuk mendapatkan Promise yang terselesaikan saat objek gapi.auth2.GoogleAuth selesai melakukan inisialisasi.

GoogleAuth.then(onInit, onError)

Memanggil fungsi onInit saat objek GoogleAuth sepenuhnya diinisialisasi. Jika terjadi error saat melakukan inisialisasi (ini dapat terjadi di browser lama yang tidak didukung), sebagai gantinya, fungsi onError akan dipanggil.

Argumen
onInit Fungsi yang dipanggil dengan objek GoogleAuth saat sudah sepenuhnya diinisialisasi.
onError Fungsi yang dipanggil dengan objek yang berisi properti error, jika GoogleAuth gagal diinisialisasi.
Hasil
Promise Promise yang terpenuhi saat onInit telah selesai, atau ditolak jika terjadi error inisialisasi. Masalah ini teratasi dengan nilai yang ditampilkan dari fungsi onInit, jika ada.

Kode Error

idpiframe_initialization_failed
Gagal melakukan inisialisasi iframe yang diperlukan dari Google, misalnya, karena tidak didukung lingkungan fleksibel App Engine. Properti details akan memberikan informasi selengkapnya tentang error yang dilaporkan.

gapi.auth2.ClientConfig

Antarmuka yang mewakili parameter konfigurasi berbeda untuk Metode gapi.auth2.init.

Parameter
client_id string Wajib. Client ID aplikasi, ditemukan dan dibuat di Konsol API Google.
cookie_policy string Domain yang digunakan untuk membuat cookie login. Baik URI, single_host_origin, atau none. Default-nya adalah single_host_origin jika tidak ditentukan.
scope string Cakupan yang akan diminta, sebagai string yang dipisahkan spasi. Opsional jika fetch_basic_profile tidak ditetapkan ke salah.
fetch_basic_profile boolean Ambil data pengguna informasi profil dasar saat login. Menambahkan 'profil', 'email' dan 'openid' ke cakupan yang diminta. Benar jika tidak ditentukan.
hosted_domain string Domain G Suite tempat pengguna harus login. Ini rentan terhadap modifikasi oleh klien, jadi pastikan untuk memverifikasi properti domain yang dihosting dari pengguna yang ditampilkan. Gunakan GoogleUser.getHostedDomain() di klien, dan klaim hd dalam Token ID pada server untuk memverifikasi domain seperti yang Anda harapkan.
use_fedcm boolean Opsional, ditetapkan secara default ke True. Mengaktifkan atau menonaktifkan penggunaan FedCM API browser selama login.
ux_mode string Mode UX yang akan digunakan untuk alur login. Secara default, tindakan ini akan membuka alur izin di jendela pop-up. Nilai yang valid adalah popup dan redirect.
redirect_uri string Jika menggunakan ux_mode='redirect', parameter ini memungkinkan Anda mengganti redirect_uri default yang akan digunakan di akhir alur izin. Tujuan redirect_uri default adalah URL saat ini yang tidak menyertakan parameter kueri dan hash fragmen.
enable_granular_consent boolean Opsional. Apakah akan diaktifkan rincian izin akses. Jika ditetapkan ke false, layanan Google akan semakin terperinci Izin akun akan dinonaktifkan untuk client ID OAuth yang dibuat sebelum 2019. Tidak berlaku untuk Client ID OAuth yang dibuat selama atau setelah tahun 2019, karena izin akses yang lebih terperinci selalu diaktifkan untuk mereka.
plugin_name string Opsional. Jika nilai ini ditetapkan, Client-ID baru yang dibuat sebelum bulan Juli Tanggal 29 2022 dapat menggunakan Library Platform Google lama. Secara default, Client ID yang baru dibuat kini diblokir agar tidak menggunakan Library Platform dan harus menggunakan Identity Google yang lebih baru Library layanan. Anda dapat memilih nilai apa pun, nama deskriptif seperti nama produk atau plugin direkomendasikan untuk identifikasi. Contoh: plugin_name: 'YOUR_STRING_HERE'

Autentikasi

GoogleAuth adalah class singleton yang menyediakan metode untuk memungkinkan pengguna login dengan Akun Google, mendapatkan status login pengguna saat ini, mendapatkan data tertentu dari profil Google pengguna, meminta cakupan tambahan, dan logout dari akun saat ini.

gapi.auth2.getAuthInstance()

Menampilkan objek GoogleAuth. Anda harus melakukan inisialisasi objek GoogleAuth dengan gapi.auth2.init() sebelum memanggil metode ini.

Hasil
gapi.auth2.GoogleAuth Objek gapi.auth2.GoogleAuth. Gunakan objek ini untuk memanggil Metode gapi.auth2.GoogleAuth.

GoogleAuth.isSignedIn.get()

Menampilkan apakah pengguna saat ini sedang login.

Hasil
Boolean true jika pengguna sudah login, atau false jika pengguna logout atau objek GoogleAuth tidak diinisialisasi.

GoogleAuth.isSignedIn.listen(listener)

Memproses perubahan status login pengguna saat ini.

Argumen
listener Fungsi yang menggunakan nilai boolean. listen() kartu true ke fungsi ini saat pengguna login, dan false saat pengguna logout.

GoogleAuth.signIn()

Membuat pengguna login dengan opsi yang ditentukan untuk gapi.auth2.init().

Hasil
Promise Promise yang dipenuhi dengan instance GoogleUser saat pengguna berhasil mengautentikasi dan memberikan cakupan yang diminta, atau ditolak dengan objek yang berisi properti error jika terjadi error. Lihat bagian berikutnya untuk kode error.

Kode error

Lihat GoogleAuth.signIn(options).

GoogleAuth.signIn(options)

Membuat pengguna login menggunakan opsi yang ditentukan.

Argumen
options Atau:
  • Objek gapi.auth2.SignInOptions yang berisi pasangan nilai kunci dari parameter login. Contoh:
    {
      scope: 'profile email'
    }
  • Instance gapi.auth2.SigninOptionsBuilder. Contoh:
    options = new gapi.auth2.SigninOptionsBuilder();
    options.setAppPackageName('com.example.app');
    options.setFetchBasicProfile(True);
    options.setPrompt('select_account');
    options.setScope('profile').setScope('email');
Hasil
Promise Promise yang dipenuhi dengan instance GoogleUser saat pengguna berhasil mengautentikasi dan memberikan cakupan yang diminta, atau ditolak dengan objek yang berisi properti error jika terjadi error (lihat kode error di bawah).

Kode error

popup_closed_by_user
Pengguna menutup pop-up sebelum menyelesaikan alur login.
access_denied
Pengguna menolak izin ke cakupan yang diperlukan.
immediate_failed
Tidak ada pengguna yang dapat dipilih secara otomatis tanpa meminta alur izin. Terjadi error saat menggunakan signIn dengan opsi prompt: 'none'. Opsi ini seharusnya tidak diperlukan, karena gapi.auth2.init akan membuat pengguna login secara otomatis jika sebelumnya, masuk dalam sesi sebelumnya.

gapi.auth2.SignInOptions

Antarmuka yang mewakili parameter konfigurasi berbeda untuk Metode GoogleAuth.signIn(options).

Parameter
prompt string Memaksa mode tertentu untuk alur izin. Opsional.
Kemungkinan nilainya adalah:

  • consent Server otorisasi meminta izin pengguna sebelum kembali informasi tertentu ke aplikasi.

  • select_account Server otorisasi meminta pengguna untuk memilih Akun Google. Ini memungkinkan pengguna yang memiliki beberapa akun memilih di antara beberapa akun yang mungkin memiliki sesi saat ini.
  • none (tidak direkomendasikan)
    Server otorisasi tidak akan menampilkan autentikasi atau izin pengguna layar; maka akan menghasilkan pesan {i>error<i} jika pengguna belum diotentikasi dan belum pernah mengizinkan cakupan yang diminta.
    Karena gapi.auth2.init akan membuat pengguna login secara otomatis ke jika sebelumnya masuk, memanggil signIn({prompt: 'none'}) biasanya akan gagal.
scope string Cakupan yang diminta, sebagai string yang dipisahkan spasi, di atas cakupan yang ditentukan dalam gapi.auth2.init parameter. Opsional jika fetch_basic_profile tidak ditetapkan menjadi false (salah).
ux_mode string Mode UX yang akan digunakan untuk alur login. Secara default, tindakan ini akan membuka alur izin di jendela pop-up. Nilai yang valid adalah popup dan redirect.
redirect_uri string Jika menggunakan ux_mode='redirect', parameter ini memungkinkan Anda mengganti redirect_uri default yang akan digunakan di akhir izin alur kerja. redirect_uri default adalah URL saat ini yang dihapus dari kueri dan fragmen hash.

GoogleAuth.signOut()

Membuat akun saat ini logout dari aplikasi.

Hasil
Promise Promise yang terpenuhi saat pengguna telah login posisi-posisi ini.

GoogleAuth.disconnect()

Mencabut semua cakupan yang diberikan pengguna.

GoogleAuth.grantOfflineAccess(options)

Mendapatkan izin dari pengguna untuk mengakses cakupan yang ditentukan secara offline.

Argumen
options gapi.auth2.OfflineAccessOptions objek yang berisi pasangan nilai-kunci dari parameter. Contoh:
{
  scope: 'profile email'
}
Hasil
Promise Promise yang terpenuhi saat pengguna memberikan izin cakupan yang diminta, dengan meneruskan objek yang berisi kode otorisasi ke pengendali fulfillment Promise. Contoh:
auth2.grantOfflineAccess().then(function(resp) {
  var auth_code = resp.code;
});

Kode error

popup_closed_by_user
Pengguna menutup pop-up sebelum menyelesaikan alur izin.
access_denied
Pengguna menolak izin ke cakupan yang diperlukan.
immediate_failed
Tidak ada pengguna yang dapat dipilih secara otomatis tanpa meminta alur izin. Terjadi error saat menggunakan signIn dengan opsi prompt: 'none'. Opsi ini tidak boleh diperlukan, karena gapi.auth2.init akan membuat pengguna login secara otomatis jika sebelumnya, masuk dalam sesi sebelumnya.

gapi.auth2.OfflineAccessOptions

Antarmuka yang mewakili parameter konfigurasi berbeda untuk GoogleAuth.grantOfflineAccess(options) .

Parameter
prompt string Memaksa mode tertentu untuk alur izin. Opsional.
Kemungkinan nilainya adalah:

  • consent Server otorisasi meminta izin pengguna sebelum kembali informasi tertentu ke aplikasi.

  • select_account Server otorisasi meminta pengguna untuk memilih Akun Google. Ini memungkinkan pengguna yang memiliki beberapa akun memilih di antara beberapa akun yang mungkin memiliki sesi saat ini.
scope string Cakupan yang diminta, sebagai string yang dipisahkan spasi, di atas cakupan yang ditentukan dalam gapi.auth2.init parameter. Opsional jika fetch_basic_profile tidak ditetapkan menjadi false (salah).

GoogleAuth.attachClickHandler(container, options, onsuccess, onfailure)

Melampirkan alur login ke pengendali klik penampung yang ditentukan.

Argumen
container ID, atau referensi ke, elemen div yang menjadi memasang pengendali klik.
options Objek yang berisi pasangan nilai kunci parameter. Lihat GoogleAuth.signIn().
onsuccess Fungsi yang akan dipanggil setelah login selesai.
onfailure Fungsi yang akan dipanggil jika login gagal.

Pengguna

Objek GoogleUser mewakili satu akun pengguna. Objek GoogleUser biasanya diperoleh dengan memanggil GoogleAuth.currentUser.get().

GoogleAuth.currentUser.get()

Menampilkan objek GoogleUser yang mewakili pengguna saat ini. Perhatikan bahwa dalam file yang baru diinisialisasi GoogleAuth, pengguna saat ini belum ditetapkan. Gunakan Metode currentUser.listen() atau GoogleAuth.then() untuk mendapatkan instance GoogleAuth yang diinisialisasi.

Hasil
GoogleUser Pengguna saat ini

GoogleAuth.currentUser.listen(listener)

Memproses perubahan pada currentUser.

Argumen
listener Fungsi yang menggunakan parameter GoogleUser. listen meneruskan GoogleUser ke fungsi ini setiap perubahan yang mengubah currentUser.

GoogleUser.getId()

Mendapatkan string ID unik pengguna.

Hasil
String ID unik pengguna

GoogleUser.isSignedIn()

Menampilkan true (benar) jika pengguna login.

Hasil
Boolean True jika pengguna login

GoogleUser.getHostedDomain()

Mendapatkan domain G Suite pengguna jika pengguna login dengan akun G Suite.

Hasil
String Domain G Suite pengguna

GoogleUser.getGrantedScopes()

Dapatkan cakupan yang diberikan pengguna sebagai string yang dipisahkan spasi.

Hasil
String Cakupan yang diberikan oleh pengguna

GoogleUser.getBasicProfile()

Mendapatkan informasi profil dasar pengguna.

Hasil
gapi.auth2.BasicProfile Anda dapat mengambil properti gapi.auth2.BasicProfile dengan metode berikut:
  • BasicProfile.getId()
  • BasicProfile.getName()
  • BasicProfile.getGivenName()
  • BasicProfile.getFamilyName()
  • BasicProfile.getImageUrl()
  • BasicProfile.getEmail()

GoogleUser.getAuthResponse(includeAuthorizationData)

Dapatkan objek respons dari sesi autentikasi pengguna.

Argumen
includeAuthorizationData Opsional: Boolean yang menentukan apakah akan selalu menampilkan token akses dan cakupan. Secara default, token akses dan cakupan yang diminta tidak ditampilkan saat fetch_basic_profile bernilai benar (true) (nilai default) dan tidak ada cakupan tambahan yang diminta.
Hasil
gapi.auth2.AuthResponse Objek gapi.auth2.AuthResponse.

GoogleUser.reloadAuthResponse()

Memaksa refresh token akses, lalu menampilkan Promise untuk AuthResponse baru.

Hasil
Promise Promise yang terpenuhi dengan pemuatan ulang gapi.auth2.AuthResponse saat memuat ulang Token OAuth selesai.

gapi.auth2.AuthResponse

Respons yang ditampilkan saat memanggil GoogleUser.getAuthResponse(includeAuthorizationData) atau GoogleUser.reloadAuthResponse() metode.

Properti
access_token string Token Akses yang diberikan.
id_token string Token ID yang diberikan.
scope string Cakupan yang diberikan dalam Token Akses.
expires_in number Jumlah detik hingga Token Akses kedaluwarsa.
first_issued_at number Stempel waktu saat pengguna pertama kali memberikan cakupan yang diminta.
expires_at number Stempel waktu saat Token Akses akan kedaluwarsa.

GoogleUser.hasGrantedScopes(scopes)

Menampilkan true (benar) jika pengguna diberi cakupan yang ditentukan.

Argumen
scopes String cakupan yang dipisahkan spasi.
Hasil
Boolean True jika cakupan diberikan

GoogleUser.grant(options)

Minta cakupan tambahan kepada pengguna.

Lihat GoogleAuth.signIn() untuk mengetahui daftar parameter dan kode error.

GoogleUser.grantOfflineAccess(options)

Mendapatkan izin dari pengguna untuk mengakses cakupan yang ditentukan secara offline.

Argumen
options gapi.auth2.OfflineAccessOptions objek yang berisi pasangan nilai-kunci dari parameter. Contoh:
{
  scope: 'profile email'
}

GoogleUser.disconnect()

Mencabut semua cakupan yang diberikan pengguna untuk aplikasi.

Elemen UI

gapi.signin2.render(id, options)

Merender tombol login di elemen dengan ID yang diberikan, menggunakan setelan yang ditentukan oleh objek options.

Argumen
id ID elemen tempat merender tombol login.
options Objek yang berisi setelan yang akan digunakan untuk merender tombol. Contoh:
{
  scope: 'email',
  width: 200,
  height: 50,
  longtitle: true,
  theme: 'dark',
  onsuccess: handleSuccess,
  onfailure: handleFailure
}
Anda dapat menentukan opsi berikut:
Parameter
cakupan Cakupan yang akan diminta saat pengguna login (default: profile).
lebar Lebar tombol dalam piksel (default: 120).
tinggi Tinggi tombol dalam piksel (default: 36).
{i>longtitle<i} Menampilkan label panjang seperti "Login dengan Google" bukannya "Login" (default: false). Ketika Anda menggunakan judul yang panjang, Anda harus menambah lebar tombol dari {i>default<i}-nya.
tema Tema warna tombol: light atau dark (default: light).
keberhasilan Fungsi callback yang akan dipanggil saat pengguna berhasil login. Fungsi ini harus mengambil satu argumen: sebuah instance dari gapi.auth2.GoogleUser (default: tidak ada).
onfailure Fungsi callback yang akan dipanggil saat login gagal. Fungsi ini tidak membutuhkan argumen (default: none).

Lanjutan

gapi.auth2.Authorize(params, callback)

Melakukan otorisasi OAuth 2.0 satu kali. Tergantung pada parameter yang digunakan, ini akan membuka pop-up ke alur login dengan Google atau coba muat respons yang diminta secara otomatis, tanpa interaksi pengguna.

Beberapa kasus penggunaan yang dapat memanfaatkan metode ini antara lain:

  • Aplikasi Anda hanya perlu meminta endpoint Google API satu kali, misalnya, untuk memuat video YouTube favorit pengguna saat pertama kali mereka masuk.
  • Aplikasi Anda memiliki infrastruktur pengelolaan sesinya sendiri, dan hanya memerlukan Token ID sekali untuk mengidentifikasi pengguna di backend Anda.
  • Beberapa Client-ID digunakan di halaman yang sama.
Argumen
params Objek yang berisi pasangan nilai kunci data konfigurasi. Lihat gapi.auth2.AuthorizeConfig untuk dan properti lain dapat dikonfigurasi. Contoh:
{
  client_id: 'CLIENT_ID.apps.googleusercontent.com',
  scope: 'email profile openid',
  response_type: 'id_token permission'
}
callback Sebuah {i>function<i} yang dipanggil dengan gapi.auth2.AuthorizeResponse objek setelah permintaan diselesaikan (baik berhasil maupun gagal).

Contoh

gapi.auth2.authorize({
  client_id: 'CLIENT_ID.apps.googleusercontent.com',
  scope: 'email profile openid',
  response_type: 'id_token permission'
}, function(response) {
  if (response.error) {
    // An error happened!
    return;
  }
  // The user authorized the application for the scopes requested.
  var accessToken = response.access_token;
  var idToken = response.id_token;
  // You can also now use gapi.client to perform authenticated requests.
});

Kode error

idpiframe_initialization_failed
Gagal melakukan inisialisasi iframe yang diperlukan dari Google, misalnya, karena tidak didukung lingkungan fleksibel App Engine. Properti details akan memberikan informasi selengkapnya tentang error yang dilaporkan.
popup_closed_by_user
Pengguna menutup pop-up sebelum menyelesaikan alur login.
access_denied
Pengguna menolak izin ke cakupan yang diperlukan.
immediate_failed
Tidak ada pengguna yang dapat dipilih secara otomatis tanpa meminta alur izin. Terjadi error saat menggunakan signIn dengan opsi prompt: 'none'.

gapi.auth2.AuthorizeConfig

Antarmuka yang mewakili parameter konfigurasi berbeda untuk Metode gapi.auth2.authorize.

Properti
client_id string Wajib diisi. Client ID aplikasi, ditemukan dan dibuat di Konsol API Google.
scope string Wajib diisi. Cakupan yang akan diminta, sebagai string yang dipisahkan spasi.
response_type string Daftar jenis respons yang dipisahkan spasi. Default-nya adalah 'permission'. Kemungkinan nilainya adalah:
  • id_token, untuk mengambil Token ID
  • permission (atau token), untuk mengambil Token Akses
  • code, untuk mengambil Kode Otorisasi
prompt string Memaksa mode tertentu untuk alur izin. Kemungkinan nilainya adalah:

  • consent Server otorisasi meminta izin pengguna sebelum kembali informasi tertentu ke aplikasi.

  • select_account Server otorisasi meminta pengguna untuk memilih Akun Google. Ini memungkinkan pengguna yang memiliki beberapa akun memilih di antara beberapa akun yang mungkin memiliki sesi saat ini.

  • none Server otorisasi tidak akan menampilkan autentikasi atau izin pengguna layar; maka akan menghasilkan pesan {i>error<i} jika pengguna belum diotentikasi dan belum pernah mengizinkan cakupan yang diminta.
    Jika code diminta sebagai jenis respons, kode yang ditampilkan hanya akan dapat ditukar dengan access_token, bukan refresh_token.
cookie_policy string Domain yang digunakan untuk membuat cookie login. Baik URI, single_host_origin, atau none. Default-nya adalah single_host_origin jika tidak ditentukan.
hosted_domain string Domain G Suite tempat pengguna harus login. Hal ini rentan terhadap modifikasi oleh klien, jadi pastikan untuk memverifikasi properti domain yang dihosting dari pengguna yang kembali.
login_hint string Email, atau ID Pengguna, pengguna yang harus dipilih sebelumnya dalam alur login. Hal ini rentan terhadap dimodifikasi oleh pengguna, kecuali jika prompt: "none" digunakan.
include_granted_scopes boolean Apakah akan meminta Token Akses yang menyertakan semua cakupan yang sebelumnya diberikan oleh pengguna ke aplikasi, atau hanya cakupan yang diminta dalam panggilan saat ini. Default-nya adalah true.
enable_granular_consent boolean Opsional. Apakah akan diaktifkan rincian izin akses. Jika ditetapkan ke false, layanan Google akan semakin terperinci Izin akun akan dinonaktifkan untuk client ID OAuth yang dibuat sebelum 2019. Tidak berlaku untuk Client ID OAuth yang dibuat selama atau setelah tahun 2019, karena izin akses yang lebih terperinci selalu diaktifkan untuk mereka.
plugin_name string Opsional. Jika ditetapkan, Client-ID yang dibuat sebelum 29 Juli 2022 dapat menggunakan Library Platform Google. Secara default, Client-ID yang baru dibuat akan diblokir menggunakan Library Platform dan harus menggunakan API Identity Services. Anda dapat memilih nilai apa pun, nama deskriptif seperti nama produk atau plugin disarankan untuk memudahkan identifikasi. Contoh: plugin_name: 'YOUR_STRING_HERE'

gapi.auth2.AuthorizeResponse

Respons yang ditampilkan ke callback Metode gapi.auth2.authorize.

Properti
access_token string Token Akses yang diberikan. Hanya ada jika permission atau token ada yang ditentukan dalam response_type.
id_token string Token ID yang diberikan. Hanya ada jika id_token ditentukan dalam response_type.
code string Kode Otorisasi yang diberikan. Hanya ada jika code ditentukan dalam response_type.
scope string Cakupan yang diberikan dalam Token Akses. Hanya ada jika permission atau token telah ditentukan dalam response_type.
expires_in number Jumlah detik hingga Token Akses kedaluwarsa. Hanya ada jika permission atau token telah ditentukan dalam response_type.
first_issued_at number Stempel waktu saat pengguna pertama kali memberikan cakupan yang diminta. Hanya ada jika permission atau token telah ditentukan dalam response_type.
expires_at number Stempel waktu saat Token Akses akan kedaluwarsa. Hanya ada jika permission atau token telah ditentukan dalam response_type.
error string Jika permintaan gagal, ini berisi kode error.
error_subtype string Jika permintaan gagal, hal ini juga dapat berisi informasi tambahan ke kode error. dikembalikan.