電話SMS認証(上手くいかない)(Firebase Authentication)
Firebase Authentication
無料。(Twilioの場合は1階につき$0.0079ドルかかる)
Firebaseコンソールでプロジェクトを作成し、
「Authentication」>「電話番号」を有効化
「プロジェクトの設定」>「アプリを追加」>「Androidアプリ」
google-services.jsonをAndroidアプリのappフォルダ直下に配置します
app/build.gradle
dependencies {
implementation 'com.google.firebase:firebase-auth:22.1.2'
implementation 'com.google.android.gms:play-services-auth:20.7.0'
}
MyApp.kt(MainActivity.ktと同階層)
package com.example.application0326
import android.app.Application
import com.google.firebase.FirebaseApp
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
FirebaseApp.initializeApp(this)
}
}
AndroidManifest.xml
<application
android:name=".MyApp" <!-- ここを追加 -->
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.App">
PhoneActivity.kt
class LoginActivity : AppCompatActivity() {
private lateinit var auth: FirebaseAuth
private lateinit var storedVerificationId: String
private lateinit var resendToken: PhoneAuthProvider.ForceResendingToken
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
auth = FirebaseAuth.getInstance()
val btnSendCode = findViewById<Button>(R.id.btnSendCode)
val etPhone = findViewById<EditText>(R.id.etPhone)
btnSendCode.setOnClickListener {
val phoneNumber = etPhone.text.toString().trim()
if (phoneNumber.isNotEmpty()) {
sendVerificationCode(phoneNumber)
} else {
Toast.makeText(this, "電話番号を入力してください", Toast.LENGTH_SHORT).show()
}
}
}
private fun sendVerificationCode(phoneNumber: String) {
val options = PhoneAuthOptions.newBuilder(auth)
.setPhoneNumber(phoneNumber)
.setTimeout(60L, TimeUnit.SECONDS)
.setActivity(this)
.setCallbacks(object : PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
override fun onVerificationCompleted(credential: PhoneAuthCredential) {
signInWithPhoneAuthCredential(credential)
}
override fun onVerificationFailed(e: FirebaseException) {
Toast.makeText(applicationContext, "認証失敗: ${e.message}", Toast.LENGTH_LONG).show()
}
override fun onCodeSent(verificationId: String, token: PhoneAuthProvider.ForceResendingToken) {
storedVerificationId = verificationId
resendToken = token
Toast.makeText(applicationContext, "認証コードが送信されました", Toast.LENGTH_LONG).show()
}
})
.build()
PhoneAuthProvider.verifyPhoneNumber(options)
}
}
ユーザーが認証コードを入力してログインします
val btnVerify = findViewById<Button>(R.id.btnVerify)
val etCode = findViewById<EditText>(R.id.etCode)
btnVerify.setOnClickListener {
val code = etCode.text.toString().trim()
if (code.isNotEmpty()) {
val credential = PhoneAuthProvider.getCredential(storedVerificationId, code)
signInWithPhoneAuthCredential(credential)
} else {
Toast.makeText(this, "認証コードを入力してください", Toast.LENGTH_SHORT).show()
}
}
private fun signInWithPhoneAuthCredential(credential: PhoneAuthCredential) {
auth.signInWithCredential(credential)
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
val user = auth.currentUser
Toast.makeText(this, "ログイン成功: ${user?.phoneNumber}", Toast.LENGTH_LONG).show()
// WordPressに登録する場合はここでAPIを呼ぶ
registerUserToWordPress(user?.uid, user?.phoneNumber)
} else {
Toast.makeText(this, "ログイン失敗", Toast.LENGTH_SHORT).show()
}
}
}
WordPressにFirebaseユーザーを登録します
fun registerUserToWordPress(uid: String?, phone: String?) {
val url = "https://example.com/wp-admin/admin-ajax.php?action=register_firebase_user"
val requestBody = "uid=$uid&phone=$phone"
val request = Request.Builder()
.url(url)
.post(requestBody.toRequestBody("application/x-www-form-urlencoded".toMediaType()))
.build()
val client = OkHttpClient()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
runOnUiThread {
Toast.makeText(this@LoginActivity, "エラー: ${e.message}", Toast.LENGTH_SHORT).show()
}
}
override fun onResponse(call: Call, response: Response) {
runOnUiThread {
Toast.makeText(this@LoginActivity, "WordPressに登録しました", Toast.LENGTH_SHORT).show()
}
}
})
}
Functions.php
function register_firebase_user() {
global $wpdb;
$uid = $_POST['uid'];
$phone = $_POST['phone'];
if (empty($uid) || empty($phone)) {
echo json_encode(["status" => "error", "message" => "UIDまたは電話番号が空です"]);
wp_die();
}
// 既存ユーザーをチェック
if ($wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM wp_users WHERE user_login = %s", $phone))) {
echo json_encode(["status" => "error", "message" => "既に登録されています"]);
wp_die();
}
// WordPressに登録
$user_id = wp_insert_user([
'user_login' => $phone,
'user_pass' => wp_generate_password(),
'role' => 'subscriber',
'meta_input' => ['firebase_uid' => $uid]
]);
if (is_wp_error($user_id)) {
echo json_encode(["status" => "error", "message" => "登録失敗"]);
} else {
echo json_encode(["status" => "success", "message" => "登録成功"]);
}
wp_die();
}
add_action("wp_ajax_register_firebase_user", "register_firebase_user");
add_action("wp_ajax_nopriv_register_firebase_user", "register_firebase_user");