Join us for Firebase Summit on November 10, 2021. Tune in to learn how Firebase can help you accelerate app development, release with confidence, and scale with ease. Register

ฟังก์ชั่นการโทรจากแอพของคุณ

Cloud Functions for Firebase Client SDK ช่วยให้คุณเรียกใช้ฟังก์ชันต่างๆ ได้โดยตรงจากแอป Firebase ในการเรียกใช้ฟังก์ชันจากแอปของคุณในลักษณะนี้ ให้เขียนและปรับใช้ฟังก์ชัน HTTPS Callable ใน Cloud Functions แล้วเพิ่มตรรกะของไคลเอ็นต์เพื่อเรียกใช้ฟังก์ชันจากแอปของคุณ

มันเป็นสิ่งสำคัญที่จะเก็บไว้ในใจว่า HTTPS ฟังก์ชั่น callable จะคล้ายกัน แต่ไม่เหมือนกันกับฟังก์ชั่น HTTP ที่จะใช้ฟังก์ชั่น HTTPS callable คุณต้องใช้ SDK ลูกค้าสำหรับแพลตฟอร์มของคุณร่วมกับ functions.https แบ็กเอนด์ API (หรือใช้โปรโตคอล) Callables มีความแตกต่างที่สำคัญเหล่านี้จากฟังก์ชัน HTTP:

  • ด้วย callables, Firebase Authentication tokens, FCM tokens และ App Check tokens จะรวมอยู่ในคำขอโดยอัตโนมัติ
  • functions.https.onCall ทริกเกอร์โดยอัตโนมัติ deserializes ร่างกายคำขอและตรวจสอบโทเค็นการตรวจสอบสิทธิ์

Firebase SDK for Cloud Functions v0.9.1 ขึ้นไปทำงานร่วมกับเวอร์ชันขั้นต่ำของไคลเอ็นต์ Firebase SDK เหล่านี้เพื่อรองรับฟังก์ชัน HTTPS Callable:

  • Firebase SDK สำหรับ iOS 8.8.0
  • Firebase SDK สำหรับ Android 20.0.1
  • Firebase JavaScript SDK 8.10.0
  • Firebase Modular Web SDK เวอร์ชัน 9.0

หากคุณต้องการที่จะเพิ่มฟังก์ชันการทำงานคล้ายกับแอปที่สร้างขึ้นบนแพลตฟอร์มที่ได้รับการสนับสนุนให้ดู ข้อมูลจำเพาะ Protocol สำหรับ https.onCall ส่วนที่เหลือของคู่มือนี้จะให้คำแนะนำเกี่ยวกับวิธีการเขียน ปรับใช้ และเรียกใช้ฟังก์ชัน HTTPS callable สำหรับ iOS, Android, เว็บ, C++ และ Unity

เขียนและปรับใช้ฟังก์ชันที่เรียกได้

ใช้ functions.https.onCall การสร้างฟังก์ชั่น HTTPS callable วิธีการนี้จะใช้เวลาสองพารามิเตอร์: data และตัวเลือก context :

// Saves a message to the Firebase Realtime Database but sanitizes the text by removing swearwords.
exports.addMessage = functions.https.onCall((data, context) => {
  // ...
});

สำหรับฟังก์ชั่นที่ช่วยประหยัด callable ข้อความไปยังฐานข้อมูลเรียลไทม์ยกตัวอย่างเช่น data อาจมีข้อความในขณะที่ context พารามิเตอร์แสดงข้อมูลรับรองความถูกต้องของผู้ใช้:

// Message text passed from the client.
const text = data.text;
// Authentication / user information is automatically added to the request.
const uid = context.auth.uid;
const name = context.auth.token.name || null;
const picture = context.auth.token.picture || null;
const email = context.auth.token.email || null;

ระยะห่างระหว่างตำแหน่งของฟังก์ชันที่เรียกได้และตำแหน่งของไคลเอ็นต์ที่เรียกสามารถสร้างเวลาแฝงของเครือข่ายได้ เพื่อเพิ่มประสิทธิภาพการปฏิบัติงานให้พิจารณาระบุ ที่ตั้งของฟังก์ชั่น ที่ใช้บังคับและให้แน่ใจว่าในการจัดสถานที่ตั้ง callable ที่มีการตั้งค่าสถานที่เมื่อคุณ เริ่มต้นใช้ SDK บนฝั่งไคลเอ็นต์

หรือคุณสามารถแนบเอกสารรับรอง App Check เพื่อช่วยปกป้องทรัพยากรแบ็กเอนด์ของคุณจากการละเมิด เช่น การฉ้อโกงการเรียกเก็บเงินหรือฟิชชิง ดู เปิดใช้งานการตรวจสอบการบังคับใช้ App สำหรับฟังก์ชั่นคลาวด์

ส่งคืนผลลัพธ์

หากต้องการส่งข้อมูลกลับไปยังไคลเอ็นต์ ให้ส่งคืนข้อมูลที่สามารถเข้ารหัส JSON ได้ ตัวอย่างเช่น หากต้องการส่งคืนผลลัพธ์ของการดำเนินการเพิ่มเติม:

// returning result.
return {
  firstNumber: firstNumber,
  secondNumber: secondNumber,
  operator: '+',
  operationResult: firstNumber + secondNumber,
};

หากต้องการส่งคืนข้อมูลหลังการดำเนินการแบบอะซิงโครนัส ให้ส่งคืนสัญญา ข้อมูลที่ส่งกลับโดยสัญญาจะถูกส่งไปยังลูกค้า ตัวอย่างเช่น คุณสามารถส่งคืนข้อความที่ถูกฆ่าเชื้อซึ่งฟังก์ชันที่เรียกได้เขียนไปยังฐานข้อมูลเรียลไทม์:

// Saving the new message to the Realtime Database.
const sanitizedMessage = sanitizer.sanitizeText(text); // Sanitize the message.
return admin.database().ref('/messages').push({
  text: sanitizedMessage,
  author: { uid, name, picture, email },
}).then(() => {
  console.log('New Message written');
  // Returning the sanitized message to the client.
  return { text: sanitizedMessage };
})

จัดการข้อผิดพลาด

เพื่อให้แน่ใจว่าลูกค้าได้รับรายละเอียดข้อผิดพลาดที่มีประโยชน์, ข้อผิดพลาดกลับมาจาก callable โดยการขว้างปา (หรือกลับปฏิเสธสัญญาด้วย) ตัวอย่างของ functions.https.HttpsError ข้อผิดพลาดที่มี code แอตทริบิวต์ที่สามารถเป็นหนึ่งในค่าที่ระบุไว้ที่ functions.https.HttpsError ข้อผิดพลาดที่ยังมีสตริง message ที่เริ่มต้นเป็นสตริงว่าง พวกเขายังสามารถมีตัวเลือก details ข้อมูลที่มีค่าโดยพลการ หากมีข้อผิดพลาดอื่น ๆ กว่า HttpsError ถูกโยนลงมาจากฟังก์ชั่นของคุณลูกค้าของคุณแทนที่จะได้รับข้อผิดพลาดกับข้อความ INTERNAL และรหัสที่ internal

ตัวอย่างเช่น ฟังก์ชันอาจแสดงข้อผิดพลาดในการตรวจสอบความถูกต้องของข้อมูลและการรับรองความถูกต้องพร้อมข้อความแสดงข้อผิดพลาดเพื่อกลับไปยังไคลเอ็นต์ที่เรียก:

// Checking attribute.
if (!(typeof text === 'string') || text.length === 0) {
  // Throwing an HttpsError so that the client gets the error details.
  throw new functions.https.HttpsError('invalid-argument', 'The function must be called with ' +
      'one arguments "text" containing the message text to add.');
}
// Checking that the user is authenticated.
if (!context.auth) {
  // Throwing an HttpsError so that the client gets the error details.
  throw new functions.https.HttpsError('failed-precondition', 'The function must be called ' +
      'while authenticated.');
}

ปรับใช้ฟังก์ชันที่เรียกได้

หลังจากที่คุณบันทึกเสร็จภายในฟังก์ชั่น callable index.js ก็จะถูกนำไปใช้พร้อมกับฟังก์ชั่นอื่น ๆ ทั้งหมดเมื่อคุณเรียกใช้ firebase deploy ในการปรับใช้เฉพาะ callable ใช้ --only โต้แย้งดังแสดงในการดำเนินการ เลือกใช้บางส่วน :

$ firebase deploy --only functions:addMessage

หากคุณพบข้อผิดพลาดสิทธิ์เมื่อปรับใช้ฟังก์ชั่นตรวจสอบให้แน่ใจว่าเหมาะสม บทบาท IAM ได้รับมอบหมายให้ผู้ใช้ใช้คำสั่งการใช้งาน

ตั้งค่าสภาพแวดล้อมการพัฒนาไคลเอ็นต์ของคุณ

ตรวจสอบให้แน่ใจว่าคุณมีคุณสมบัติตรงตามข้อกำหนดเบื้องต้น จากนั้นเพิ่มการพึ่งพาและไลบรารีไคลเอ็นต์ที่จำเป็นลงในแอปของคุณ

iOS

  1. ตามคำแนะนำเพื่อ เพิ่ม Firebase ไปยังแอป iOS ของคุณ
  2. เพิ่มฟังก์ชั่นคลาวด์ฝักที่คุณ Podfile :
    pod 'Firebase/Functions'
  3. บันทึกไฟล์แล้วเรียก:
    pod install

เว็บรุ่น 9

  1. ตามคำแนะนำเพื่อ เพิ่ม Firebase เพื่อ app เว็บของคุณ ให้แน่ใจว่าจะเรียกใช้คำสั่งต่อไปนี้จาก terminal ของคุณ:
    npm install firebase@9.1.3 --save
    
  2. ต้องใช้ทั้ง Firebase core และ Cloud Functions ด้วยตนเอง:

     import { initializeApp } from 'firebase/app';
     import { getFunctions } from 'firebase/functions';
    
     const app = initializeApp({
         projectId: '### CLOUD FUNCTIONS PROJECT ID ###',
         apiKey: '### FIREBASE API KEY ###',
         authDomain: '### FIREBASE AUTH DOMAIN ###',
       });
     const functions = getFunctions(app);
    

เว็บรุ่น8

  1. ตามคำแนะนำเพื่อ เพิ่ม Firebase เพื่อ app เว็บของคุณ
  2. เพิ่มแกน Firebase และเมฆห้องสมุดลูกค้าฟังก์ชั่นของแอป:
    <script src="https://www.gstatic.com/firebasejs/8.10.0/firebase.js"></script>
    <script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-functions.js"></script>
    

Cloud Functions SDK ยังมีให้ใช้งานเป็นแพ็คเกจ npm

  1. เรียกใช้คำสั่งต่อไปนี้จาก terminal ของคุณ:
    npm install firebase@8.10.0 --save
    
  2. จำเป็นต้องใช้ด้วยตนเองทั้งหลัก Firebase และฟังก์ชั่นคลาวด์:
    const firebase = require("firebase");
    // Required for side-effects
    require("firebase/functions");
    

Java

  1. ตามคำแนะนำเพื่อ เพิ่ม Firebase ไปยังแอป Android ของคุณ

  2. ใช้ Firebase Android BoM ประกาศพึ่งพาสำหรับฟังก์ชั่นคลาวด์ห้องสมุด Android ในโมดูลของคุณ (app ระดับ) ไฟล์ Gradle (ปกติ app/build.gradle )

    dependencies {
        // Import the BoM for the Firebase platform
        implementation platform('com.google.firebase:firebase-bom:28.4.2')
    
        // Declare the dependency for the Cloud Functions library
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-functions'
    }
    

    โดยใช้ Firebase Android BoM แอปของคุณมักจะใช้รุ่นที่รองรับการห้องสมุด Firebase Android

    (ทางเลือก) ประกาศ Firebase อ้างอิงห้องสมุดโดยไม่ต้องใช้ BoM

    หากคุณเลือกที่จะไม่ใช้ Firebase BoM คุณต้องระบุเวอร์ชันไลบรารี Firebase แต่ละเวอร์ชันในบรรทัดการพึ่งพา

    โปรดทราบว่าถ้าคุณใช้ห้องสมุด Firebase หลายรายการในแอปของคุณเราขอแนะนำให้ใช้ BoM การจัดการเวอร์ชันห้องสมุดซึ่งทำให้มั่นใจได้ว่าทุกรุ่นที่เข้ากันได้

    dependencies {
        // Declare the dependency for the Cloud Functions library
        // When NOT using the BoM, you must specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-functions:20.0.1'
    }
    

คอตลิน+KTX

  1. ตามคำแนะนำเพื่อ เพิ่ม Firebase ไปยังแอป Android ของคุณ

  2. ใช้ Firebase Android BoM ประกาศพึ่งพาสำหรับฟังก์ชั่นคลาวด์ห้องสมุด Android ในโมดูลของคุณ (app ระดับ) ไฟล์ Gradle (ปกติ app/build.gradle )

    dependencies {
        // Import the BoM for the Firebase platform
        implementation platform('com.google.firebase:firebase-bom:28.4.2')
    
        // Declare the dependency for the Cloud Functions library
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-functions-ktx'
    }
    

    โดยใช้ Firebase Android BoM แอปของคุณมักจะใช้รุ่นที่รองรับการห้องสมุด Firebase Android

    (ทางเลือก) ประกาศ Firebase อ้างอิงห้องสมุดโดยไม่ต้องใช้ BoM

    หากคุณเลือกที่จะไม่ใช้ Firebase BoM คุณต้องระบุเวอร์ชันไลบรารี Firebase แต่ละเวอร์ชันในบรรทัดการพึ่งพา

    โปรดทราบว่าถ้าคุณใช้ห้องสมุด Firebase หลายรายการในแอปของคุณเราขอแนะนำให้ใช้ BoM การจัดการเวอร์ชันห้องสมุดซึ่งทำให้มั่นใจได้ว่าทุกรุ่นที่เข้ากันได้

    dependencies {
        // Declare the dependency for the Cloud Functions library
        // When NOT using the BoM, you must specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-functions-ktx:20.0.1'
    }
    

C++

สำหรับ C ++ กับ Android:

  1. ตามคำแนะนำเพื่อ เพิ่ม Firebase กับ C ++ โครงการของคุณ
  2. เพิ่ม firebase_functions ห้องสมุดที่คุณ CMakeLists.txt ไฟล์

สำหรับ C ++ กับ iOS:

  1. ตามคำแนะนำเพื่อ เพิ่ม Firebase กับ C ++ โครงการของคุณ
  2. เพิ่มฟังก์ชั่นคลาวด์ฝักที่คุณ Podfile :
    pod 'Firebase/Functions'
  3. บันทึกไฟล์แล้วเรียก:
    pod install
  4. เพิ่มแกน Firebase และฟังก์ชั่นคลาวด์กรอบจาก Firebase c ++ SDK กับโครงการ Xcode ของคุณ
    • firebase.framework
    • firebase_functions.framework

ความสามัคคี

  1. ตามคำแนะนำเพื่อ เพิ่ม Firebase กับโครงการความสามัคคีของคุณ
  2. เพิ่ม FirebaseFunctions.unitypackage จาก Firebase สามัคคี SDK กับโครงการความสามัคคีของคุณ

เริ่มต้นไคลเอ็นต์ SDK

เริ่มต้นอินสแตนซ์ของ Cloud Functions:

Swift

lazy var functions = Functions.functions()

วัตถุประสงค์-C

@property(strong, nonatomic) FIRFunctions *functions;
// ...
self.functions = [FIRFunctions functions];

เว็บรุ่น8

firebase.initializeApp({
  apiKey: '### FIREBASE API KEY ###',
  authDomain: '### FIREBASE AUTH DOMAIN ###',
  projectId: '### CLOUD FUNCTIONS PROJECT ID ###'
  databaseURL: 'https://### YOUR DATABASE NAME ###.firebaseio.com',
});

// Initialize Cloud Functions through Firebase
var functions = firebase.functions();

เว็บรุ่น 9

const app = initializeApp({
  projectId: '### CLOUD FUNCTIONS PROJECT ID ###',
  apiKey: '### FIREBASE API KEY ###',
  authDomain: '### FIREBASE AUTH DOMAIN ###',
});
const functions = getFunctions(app);

Java

private FirebaseFunctions mFunctions;
// ...
mFunctions = FirebaseFunctions.getInstance();

คอตลิน+KTX

private lateinit var functions: FirebaseFunctions
// ...
functions = Firebase.functions

C++

firebase::functions::Functions* functions;
// ...
functions = firebase::functions::Functions::GetInstance(app);

ความสามัคคี

functions = Firebase.Functions.DefaultInstance;

เรียกใช้ฟังก์ชัน

Swift

functions.httpsCallable("addMessage").call(["text": inputField.text]) { result, error in
  if let error = error as NSError? {
    if error.domain == FunctionsErrorDomain {
      let code = FunctionsErrorCode(rawValue: error.code)
      let message = error.localizedDescription
      let details = error.userInfo[FunctionsErrorDetailsKey]
    }
    // ...
  }
  if let data = result?.data as? [String: Any], let text = data["text"] as? String {
    self.resultField.text = text
  }
}

วัตถุประสงค์-C

[[_functions HTTPSCallableWithName:@"addMessage"] callWithObject:@{@"text": _inputField.text}
                                                      completion:^(FIRHTTPSCallableResult * _Nullable result, NSError * _Nullable error) {
  if (error) {
    if (error.domain == FIRFunctionsErrorDomain) {
      FIRFunctionsErrorCode code = error.code;
      NSString *message = error.localizedDescription;
      NSObject *details = error.userInfo[FIRFunctionsErrorDetailsKey];
    }
    // ...
  }
  self->_resultField.text = result.data[@"text"];
}];

เว็บรุ่น8

var addMessage = firebase.functions().httpsCallable('addMessage');
addMessage({ text: messageText })
  .then((result) => {
    // Read result of the Cloud Function.
    var sanitizedMessage = result.data.text;
  });

เว็บรุ่น 9

import { getFunctions, httpsCallable } from "firebase/functions";

const functions = getFunctions();
const addMessage = httpsCallable(functions, 'addMessage');
addMessage({ text: messageText })
  .then((result) => {
    // Read result of the Cloud Function.
    /** @type {any} */
    const data = result.data;
    const sanitizedMessage = data.text;
  });

Java

private Task<String> addMessage(String text) {
    // Create the arguments to the callable function.
    Map<String, Object> data = new HashMap<>();
    data.put("text", text);
    data.put("push", true);

    return mFunctions
            .getHttpsCallable("addMessage")
            .call(data)
            .continueWith(new Continuation<HttpsCallableResult, String>() {
                @Override
                public String then(@NonNull Task<HttpsCallableResult> task) throws Exception {
                    // This continuation runs on either success or failure, but if the task
                    // has failed then getResult() will throw an Exception which will be
                    // propagated down.
                    String result = (String) task.getResult().getData();
                    return result;
                }
            });
}

คอตลิน+KTX

private fun addMessage(text: String): Task<String> {
    // Create the arguments to the callable function.
    val data = hashMapOf(
        "text" to text,
        "push" to true
    )

    return functions
            .getHttpsCallable("addMessage")
            .call(data)
            .continueWith { task ->
                // This continuation runs on either success or failure, but if the task
                // has failed then result will throw an Exception which will be
                // propagated down.
                val result = task.result?.data as String
                result
            }
}

C++

firebase::Future<firebase::functions::HttpsCallableResult> AddMessage(
    const std::string& text) {
  // Create the arguments to the callable function.
  firebase::Variant data = firebase::Variant::EmptyMap();
  data.map()["text"] = firebase::Variant(text);
  data.map()["push"] = true;

  // Call the function and add a callback for the result.
  firebase::functions::HttpsCallableReference doSomething =
      functions->GetHttpsCallable("addMessage");
  return doSomething.Call(data);
}

ความสามัคคี

private Task<string> addMessage(string text) {
  // Create the arguments to the callable function.
  var data = new Dictionary<string, object>();
  data["text"] = text;
  data["push"] = true;

  // Call the function and extract the operation from the result.
  var function = functions.GetHttpsCallable("addMessage");
  return function.CallAsync(data).ContinueWith((task) => {
    return (string) task.Result.Data;
  });
}

จัดการข้อผิดพลาดในไคลเอนต์

ไคลเอนต์ได้รับข้อผิดพลาดหากเซิร์ฟเวอร์ส่งข้อผิดพลาดหรือหากสัญญาผลลัพธ์ถูกปฏิเสธ

ถ้าข้อผิดพลาดที่ส่งกลับโดยฟังก์ชั่นเป็นประเภท function.https.HttpsError แล้วลูกค้าจะได้รับข้อผิดพลาด code , message และ details จากความผิดพลาดของเซิร์ฟเวอร์ มิฉะนั้นข้อผิดพลาดประกอบด้วยข้อความ INTERNAL และรหัสที่ INTERNAL ดูคำแนะนำสำหรับวิธีการ จัดการข้อผิดพลาด ในการทำงานของคุณ callable

Swift

if let error = error as NSError? {
  if error.domain == FunctionsErrorDomain {
    let code = FunctionsErrorCode(rawValue: error.code)
    let message = error.localizedDescription
    let details = error.userInfo[FunctionsErrorDetailsKey]
  }
  // ...
}

วัตถุประสงค์-C

if (error) {
  if (error.domain == FIRFunctionsErrorDomain) {
    FIRFunctionsErrorCode code = error.code;
    NSString *message = error.localizedDescription;
    NSObject *details = error.userInfo[FIRFunctionsErrorDetailsKey];
  }
  // ...
}

เว็บรุ่น8

var addMessage = firebase.functions().httpsCallable('addMessage');
addMessage({ text: messageText })
  .then((result) => {
    // Read result of the Cloud Function.
    var sanitizedMessage = result.data.text;
  })
  .catch((error) => {
    // Getting the Error details.
    var code = error.code;
    var message = error.message;
    var details = error.details;
    // ...
  });

เว็บรุ่น 9

import { getFunctions, httpsCallable } from "firebase/functions";

const functions = getFunctions();
const addMessage = httpsCallable(functions, 'addMessage');
addMessage({ text: messageText })
  .then((result) => {
    // Read result of the Cloud Function.
    /** @type {any} */
    const data = result.data;
    const sanitizedMessage = data.text;
  })
  .catch((error) => {
    // Getting the Error details.
    const code = error.code;
    const message = error.message;
    const details = error.details;
    // ...
  });

Java

addMessage(inputMessage)
        .addOnCompleteListener(new OnCompleteListener<String>() {
            @Override
            public void onComplete(@NonNull Task<String> task) {
                if (!task.isSuccessful()) {
                    Exception e = task.getException();
                    if (e instanceof FirebaseFunctionsException) {
                        FirebaseFunctionsException ffe = (FirebaseFunctionsException) e;
                        FirebaseFunctionsException.Code code = ffe.getCode();
                        Object details = ffe.getDetails();
                    }

                    // ...
                }

                // ...
            }
        });

คอตลิน+KTX

addMessage(inputMessage)
        .addOnCompleteListener(OnCompleteListener { task ->
            if (!task.isSuccessful) {
                val e = task.exception
                if (e is FirebaseFunctionsException) {
                    val code = e.code
                    val details = e.details
                }

                // ...
            }

            // ...
        })

C++

void OnAddMessageCallback(
    const firebase::Future<firebase::functions::HttpsCallableResult>& future) {
  if (future.error() != firebase::functions::kErrorNone) {
    // Function error code, will be kErrorInternal if the failure was not
    // handled properly in the function call.
    auto code = static_cast<firebase::functions::Error>(future.error());

    // Display the error in the UI.
    DisplayError(code, future.error_message());
    return;
  }

  const firebase::functions::HttpsCallableResult *result = future.result();
  firebase::Variant data = result->data();
  // This will assert if the result returned from the function wasn't a string.
  std::string message = data.string_value();
  // Display the result in the UI.
  DisplayResult(message);
}

// ...

// ...
  auto future = AddMessage(message);
  future.OnCompletion(OnAddMessageCallback);
// ...

ความสามัคคี

 addMessage(text).ContinueWith((task) => {
  if (task.IsFaulted) {
    foreach (var inner in task.Exception.InnerExceptions) {
      if (inner is FunctionsException) {
        var e = (FunctionsException) inner;
        // Function error code, will be INTERNAL if the failure
        // was not handled properly in the function call.
        var code = e.ErrorCode;
        var message = e.ErrorMessage;
      }
    }
  } else {
    string result = task.Result;
  }
});

ก่อนที่คุณจะเปิด app ของคุณคุณควรเปิดใช้งานการ ตรวจสอบ App เพื่อช่วยให้มั่นใจว่ามีเพียงปพลิเคชันของคุณสามารถเข้าถึงฟังก์ชั่นปลายทาง callable ของคุณ