Di chuyển từ API FCM cũ sang HTTP v1

Các ứng dụng dùng API cũ FCM đã ngừng hoạt động dành cho HTTP và Payoneer cần phải di chuyển sang API HTTP v1 trong thời gian sớm nhất có thể. Tính năng gửi thông báo (bao gồm cả thông báo ngược dòng) bằng các API đó đã ngừng hoạt động từ ngày 20 tháng 6 năm 2023 và sẽ bị xoá vào ngày 21 tháng 6 năm 2024.

Tìm hiểu thêm về các tính năng cụ thể bị ảnh hưởng.

Ngoài dịch vụ hỗ trợ liên tục và các tính năng mới, API HTTP v1 có các ưu điểm sau so với các API cũ:

  • Bảo mật tốt hơn qua mã truy cập API HTTP v1 sử dụng mã truy cập ngắn hạn theo mô hình bảo mật OAuth2. Trong trường hợp một mã truy cập được công khai, mã truy cập đó chỉ có thể được dùng với mục đích độc hại trong vòng một giờ trước khi hết hạn. Mã làm mới không được truyền thường xuyên như các khoá bảo mật dùng trong API cũ, vì vậy, khả năng các khoá này bị ghi lại sẽ ít hơn.

  • Tuỳ chỉnh thông báo hiệu quả hơn trên các nền tảng Đối với nội dung thông báo, API HTTP v1 có các khoá phổ biến cho tất cả các thực thể được nhắm mục tiêu, cùng với các khoá dành riêng cho nền tảng cho phép bạn tuỳ chỉnh thông báo trên các nền tảng. Điều này cho phép bạn tạo "ghi đè" để gửi các tải trọng hơi khác nhau đến các nền tảng ứng dụng khác nhau trong một thông báo duy nhất.

  • Khả năng mở rộng cao hơn và phù hợp với tương lai hơn cho các phiên bản nền tảng ứng dụng mới API HTTP v1 hỗ trợ đầy đủ các lựa chọn nhắn tin có trên các nền tảng của Apple, Android và Web. Vì mỗi nền tảng có khối được xác định riêng trong tải trọng JSON, FCM có thể mở rộng API cho các phiên bản và nền tảng mới nếu cần.

Cập nhật điểm cuối máy chủ

URL điểm cuối của API HTTP v1 khác với điểm cuối cũ theo những cách sau:

  • Phiên bản này đã được tạo phiên bản, với /v1 trong đường dẫn.
  • Đường dẫn chứa mã dự án của dự án Firebase cho ứng dụng của bạn, ở định dạng /projects/myproject-ID/. Mã này có trong thẻ Cài đặt dự án chung của bảng điều khiển của Firebase.
  • Đoạn mã này chỉ định rõ phương thức send:send.

Để cập nhật điểm cuối của máy chủ cho HTTP v1, hãy thêm các phần tử này vào điểm cuối trong tiêu đề của yêu cầu gửi đi.

Yêu cầu HTTP trước đó

POST https://fcm.googleapis.com/fcm/send

Yêu cầu SAML trước đó

Thông báo RCS cũ được gửi qua một kết nối đến điểm cuối sau:

fcm-xmpp.googleapis.com:5235

Sau

POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send

Cập nhật uỷ quyền gửi yêu cầu

Thay vì chuỗi khoá máy chủ được dùng trong các yêu cầu cũ, các yêu cầu gửi HTTP v1 đòi hỏi bạn phải có mã truy cập OAuth 2.0. Nếu bạn đang sử dụng SDK dành cho quản trị viên để gửi thông báo, thì thư viện sẽ xử lý mã thông báo cho bạn. Nếu bạn đang sử dụng giao thức thô, hãy lấy mã thông báo như mô tả trong phần này rồi thêm vào tiêu đề dưới dạng Authorization: Bearer <valid Oauth 2.0 token>.

Trước

Authorization: key=AIzaSyZ-1u...0GBYzPu7Udno5aA

Sau

Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA

Tuỳ thuộc vào thông tin chi tiết về môi trường máy chủ của bạn, hãy sử dụng kết hợp các chiến lược sau để uỷ quyền các yêu cầu máy chủ cho các dịch vụ Firebase:

  • Thông tin xác thực mặc định của ứng dụng trên Google (ADC)
  • Tệp JSON của tài khoản dịch vụ
  • Mã truy cập OAuth 2.0 ngắn hạn bắt nguồn từ tài khoản dịch vụ

Nếu ứng dụng của bạn đang chạy trên Compute Engine, Google Kubernetes Engine, App Engine hoặc Cloud Functions (bao gồm cả Cloud Functions cho Firebase), hãy sử dụng Thông tin xác thực mặc định của ứng dụng (ADC). ADC sử dụng tài khoản dịch vụ mặc định hiện có của bạn để lấy thông tin xác thực để cấp phép cho các yêu cầu, đồng thời ADC cho phép thử nghiệm cục bộ linh hoạt thông qua biến môi trường GOOGLE_APPLICATION_CREDENTIALS. Để quy trình uỷ quyền được tự động hoá một cách tối đa, hãy sử dụng ADC cùng với các thư viện máy chủ SDK dành cho quản trị viên.

Nếu ứng dụng của bạn đang chạy trên môi trường máy chủ không phải của Google, bạn sẽ cần tải tệp JSON của tài khoản dịch vụ xuống từ dự án Firebase của mình. Miễn là có quyền truy cập vào một hệ thống tệp có chứa tệp khoá riêng tư, bạn có thể sử dụng biến môi trường GOOGLE_APPLICATION_CREDENTIALS để cho phép các yêu cầu có thông tin đăng nhập thu được theo cách thủ công này. Nếu không có quyền truy cập vào tệp như vậy, bạn phải tham chiếu tệp tài khoản dịch vụ trong mã của mình. Bạn cần phải cực kỳ cẩn thận do có nguy cơ để lộ thông tin đăng nhập.

Cung cấp thông tin xác thực bằng cách sử dụng ADC

Thông tin xác thực mặc định của ứng dụng (ADC) của Google sẽ kiểm tra thông tin xác thực của bạn theo thứ tự sau:

  1. ADC kiểm tra xem biến môi trường GOOGLE_APPLICATION_CREDENTIALS có được đặt hay không. Nếu bạn đặt biến này, ADC sẽ sử dụng tệp tài khoản dịch vụ mà biến trỏ đến.

  2. Nếu bạn không đặt biến môi trường, ADC sẽ sử dụng tài khoản dịch vụ mặc định mà Compute Engine, Google Kubernetes Engine, App Engine và Cloud Functions cung cấp cho các ứng dụng chạy trên các dịch vụ đó.

  3. Nếu ADC không thể sử dụng một trong hai thông tin xác thực ở trên, hệ thống sẽ gửi lỗi.

Ví dụ về mã SDK dành cho quản trị viên sau đây minh hoạ chiến lược này. Ví dụ này không chỉ định rõ ràng thông tin đăng nhập của ứng dụng. Tuy nhiên, ADC có thể ngầm tìm thấy thông tin xác thực miễn là biến môi trường đã được đặt, hoặc miễn là ứng dụng đang chạy trên Compute Engine, Google Kubernetes Engine, App Engine hoặc Cloud Functions.

Node.js

admin.initializeApp({
  credential: admin.credential.applicationDefault(),
});

Java

FirebaseOptions options = FirebaseOptions.builder()
    .setCredentials(GoogleCredentials.getApplicationDefault())
    .setDatabaseUrl("https://<DATABASE_NAME>.firebaseio.com/")
    .build();

FirebaseApp.initializeApp(options);

Python

default_app = firebase_admin.initialize_app()

Tiến hành

app, err := firebase.NewApp(context.Background(), nil)
if err != nil {
	log.Fatalf("error initializing app: %v\n", err)
}

C#

FirebaseApp.Create(new AppOptions()
{
    Credential = GoogleCredential.GetApplicationDefault(),
});

Cung cấp thông tin đăng nhập theo cách thủ công

Các dự án Firebase hỗ trợ tài khoản dịch vụ của Google. Bạn có thể sử dụng các tài khoản này để gọi API máy chủ Firebase từ máy chủ ứng dụng hoặc môi trường đáng tin cậy. Nếu đang phát triển mã cục bộ hoặc triển khai ứng dụng tại chỗ, bạn có thể sử dụng thông tin xác thực thu được qua tài khoản dịch vụ này để cho phép các yêu cầu máy chủ.

Để xác thực một tài khoản dịch vụ và cho phép tài khoản đó truy cập vào các dịch vụ Firebase, bạn phải tạo một tệp khoá riêng tư ở định dạng JSON.

Cách tạo tệp khoá riêng tư cho tài khoản dịch vụ:

  1. Trong bảng điều khiển của Firebase, hãy mở phần Cài đặt > Tài khoản dịch vụ.

  2. Nhấp vào Tạo khoá riêng tư mới, sau đó xác nhận bằng cách nhấp vào Tạo khoá.

  3. Lưu trữ an toàn tệp JSON chứa khoá.

Khi uỷ quyền thông qua một tài khoản dịch vụ, bạn có 2 lựa chọn để cung cấp thông tin đăng nhập cho ứng dụng của mình. Bạn có thể đặt biến môi trường GOOGLE_APPLICATION_CREDENTIALS hoặc có thể truyền đường dẫn đến khoá tài khoản dịch vụ trong mã một cách rõ ràng. Lựa chọn đầu tiên an toàn hơn và được khuyên dùng.

Cách đặt biến môi trường:

Đặt biến môi trường GOOGLE_APPLICATION_CREDENTIALS thành đường dẫn tệp của tệp JSON chứa khoá tài khoản dịch vụ của bạn. Biến này chỉ áp dụng cho phiên shell hiện tại của bạn. Vì vậy, nếu bạn mở một phiên mới, hãy đặt lại biến.

Linux hoặc macOS

export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/service-account-file.json"

Windows

Với PowerShell:

$env:GOOGLE_APPLICATION_CREDENTIALS="C:\Users\username\Downloads\service-account-file.json"

Sau khi bạn hoàn tất các bước trên, Thông tin xác thực mặc định của ứng dụng (ADC) có thể ngầm xác định thông tin đăng nhập của bạn, cho phép bạn sử dụng thông tin đăng nhập tài khoản dịch vụ khi kiểm thử hoặc chạy trong môi trường không phải của Google.

Sử dụng thông tin đăng nhập để đúc mã truy cập

Sử dụng thông tin đăng nhập Firebase cùng với Thư viện xác thực của Google cho ngôn ngữ ưu tiên của bạn để truy xuất mã truy cập OAuth 2.0 ngắn hạn:

nút.js

 function getAccessToken() {
  return new Promise(function(resolve, reject) {
    const key = require('../placeholders/service-account.json');
    const jwtClient = new google.auth.JWT(
      key.client_email,
      null,
      key.private_key,
      SCOPES,
      null
    );
    jwtClient.authorize(function(err, tokens) {
      if (err) {
        reject(err);
        return;
      }
      resolve(tokens.access_token);
    });
  });
}

Trong ví dụ này, thư viện ứng dụng API của Google sẽ xác thực yêu cầu bằng mã thông báo web JSON hay JWT. Để biết thêm thông tin, hãy xem bài viết Mã thông báo web JSON.

Python

def _get_access_token():
  """Retrieve a valid access token that can be used to authorize requests.

  :return: Access token.
  """
  credentials = service_account.Credentials.from_service_account_file(
    'service-account.json', scopes=SCOPES)
  request = google.auth.transport.requests.Request()
  credentials.refresh(request)
  return credentials.token

Java

private static String getAccessToken() throws IOException {
  GoogleCredentials googleCredentials = GoogleCredentials
          .fromStream(new FileInputStream("service-account.json"))
          .createScoped(Arrays.asList(SCOPES));
  googleCredentials.refresh();
  return googleCredentials.getAccessToken().getTokenValue();
}

Sau khi mã truy cập hết hạn, phương thức làm mới mã thông báo sẽ tự động được gọi để truy xuất mã truy cập đã cập nhật.

Để cho phép truy cập vào FCM, hãy yêu cầu phạm vi https://www.googleapis.com/auth/firebase.messaging.

Cách thêm mã truy cập vào tiêu đề của yêu cầu HTTP:

Thêm mã thông báo dưới dạng giá trị của tiêu đề Authorization ở định dạng Authorization: Bearer <access_token>:

nút.js

headers: {
  'Authorization': 'Bearer ' + accessToken
}

Python

headers = {
  'Authorization': 'Bearer ' + _get_access_token(),
  'Content-Type': 'application/json; UTF-8',
}

Java

URL url = new URL(BASE_URL + FCM_SEND_ENDPOINT);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestProperty("Authorization", "Bearer " + getServiceAccountAccessToken());
httpURLConnection.setRequestProperty("Content-Type", "application/json; UTF-8");
return httpURLConnection;

Cập nhật tải trọng của yêu cầu gửi

FCM HTTP v1 mang đến một thay đổi đáng kể trong cấu trúc tải trọng thông báo JSON. Chủ yếu, những thay đổi này đảm bảo rằng thông báo được xử lý đúng cách khi nhận được trên nhiều nền tảng ứng dụng. Ngoài ra, các thay đổi này cho phép bạn linh hoạt hơn trong việc tuỳ chỉnh hoặc "ghi đè" các trường thông báo trên mỗi nền tảng.

Ngoài việc kiểm tra các ví dụ trong phần này, hãy xem Tuỳ chỉnh thông báo trên các nền tảng và xem Tài liệu tham khảo API để làm quen với HTTP phiên bản 1.

Ví dụ: tin nhắn thông báo đơn giản

Dưới đây là so sánh tải trọng thông báo rất đơn giản (chỉ chứa các trường title, bodydata) thể hiện những khác biệt cơ bản trong tải trọng thông báo cũ và tải trọng HTTP v1.

Trước

{
  "to": "/topics/news",
  "notification": {
    "title": "Breaking News",
    "body": "New news story available."
  },
  "data": {
    "story_id": "story_12345"
  }
}

Sau

{
  "message": {
    "topic": "news",
    "notification": {
      "title": "Breaking News",
      "body": "New news story available."
    },
    "data": {
      "story_id": "story_12345"
    }
  }
}

Ví dụ: nhắm mục tiêu nhiều nền tảng

Để cho phép nhắm mục tiêu nhiều nền tảng, API cũ đã thực hiện ghi đè trong phần phụ trợ. Ngược lại, HTTP v1 cung cấp các khối khoá dành riêng cho nền tảng, giúp nhà phát triển thấy rõ mọi điểm khác biệt giữa các nền tảng. Điều này cho phép bạn luôn nhắm đến nhiều nền tảng bằng một yêu cầu duy nhất, như được minh hoạ trong mẫu sau.

Trước

// Android
{
  "to": "/topics/news",
  "notification": {
    "title": "Breaking News",
    "body": "New news story available.",
    "click_action": "TOP_STORY_ACTIVITY"
  },
  "data": {
    "story_id": "story_12345"
  }
}
// Apple
{
  "to": "/topics/news",
  "notification": {
    "title": "Breaking News",
    "body": "New news story available.",
    "click_action": "HANDLE_BREAKING_NEWS"
  },
  "data": {
    "story_id": "story_12345"
  }
}

Sau

{
  "message": {
    "topic": "news",
    "notification": {
      "title": "Breaking News",
      "body": "New news story available."
    },
    "data": {
      "story_id": "story_12345"
    },
    "android": {
      "notification": {
        "click_action": "TOP_STORY_ACTIVITY"
      }
    },
    "apns": {
      "payload": {
        "aps": {
          "category" : "NEW_MESSAGE_CATEGORY"
        }
      }
    }
  }
}

Ví dụ: tuỳ chỉnh bằng cơ chế ghi đè nền tảng

Ngoài việc đơn giản hoá việc nhắm mục tiêu thông báo trên nhiều nền tảng, API HTTP v1 còn cho phép bạn linh hoạt tuỳ chỉnh thông báo trên từng nền tảng.

Trước

// Android
{
  "to": "/topics/news",
  "notification": {
    "title": "Breaking News",
    "body": "Check out the Top Story.",
    "click_action": "TOP_STORY_ACTIVITY"
  },
  "data": {
    "story_id": "story_12345"
  }
}
// Apple
{
  "to": "/topics/news",
  "notification": {
    "title": "Breaking News",
    "body": "New news story available.",
    "click_action": "HANDLE_BREAKING_NEWS"
  },
  "data": {
    "story_id": "story_12345"
  }
}

Sau

{
  "message": {
    "topic": "news",
    "notification": {
      "title": "Breaking News",
      "body": "New news story available."
    },
    "data": {
      "story_id": "story_12345"
    },
    "android": {
      "notification": {
        "click_action": "TOP_STORY_ACTIVITY",
        "body": "Check out the Top Story"
      }
    },
    "apns": {
      "payload": {
        "aps": {
          "category" : "NEW_MESSAGE_CATEGORY"
        }
      }
    }
  }
}

Ví dụ: nhắm mục tiêu đến các thiết bị cụ thể

Để nhắm đến các thiết bị cụ thể bằng API HTTP v1, hãy cung cấp mã thông báo đăng ký hiện tại của thiết bị trong khoá token thay vì khoá to.

Trước

  { "notification": {
      "body": "This is an FCM notification message!",
      "time": "FCM Message"
    },
    "to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1..."
  }

Sau

{
   "message":{
      "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
      "notification":{
        "body":"This is an FCM notification message!",
        "title":"FCM Message"
      }
   }
}

Để biết thêm mẫu và thông tin về API FCM HTTP v1, hãy xem các mục sau: