fcm

package module
v1.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 7, 2024 License: MIT Imports: 13 Imported by: 71

README

go-fcm

GoDoc Lint and Testing Go Report Card

This project was forked from github.com/edganiukov/fcm.

More information on Firebase Cloud Messaging

Feature

  • Send messages to a single device
  • Send messages to a multiple devices
  • Send messages to a topic
  • Supports condition attribute

Getting Started

To install fcm, use go get:

go get github.com/appleboy/go-fcm

Provide credentials using ADC

Google Application Default Credentials (ADC) for Firebase projects support Google service accounts, which you can use to call Firebase server APIs from your app server or trusted environment. If you're developing code locally or deploying your application on-premises, you can use credentials obtained via this service account to authorize server requests.

To authenticate a service account and authorize it to access Firebase services, you must generate a private key file in JSON format.

To generate a private key file for your service account:

  1. In the Firebase console, open Settings > Service Accounts.
  2. Click Generate New Private Key, then confirm by clicking Generate Key.
  3. Securely store the JSON file containing the key.

When authorizing via a service account, you have two choices for providing the credentials to your application. You can either set the GOOGLE_APPLICATION_CREDENTIALS environment variable, or you can explicitly pass the path to the service account key in code. The first option is more secure and is strongly recommended.

See the more detail information here.

Usage

Here is a simple example illustrating how to use FCM library:

package main

import (
  "context"
  "fmt"
  "log"

  "firebase.google.com/go/v4/messaging"
  fcm "github.com/appleboy/go-fcm"
)

func main() {
  ctx := context.Background()
  client, err := fcm.NewClient(
    ctx,
    fcm.WithCredentialsFile("path/to/serviceAccountKey.json"),
    // initial with service account
    // fcm.WithServiceAccount("my-client-id@my-project-id.iam.gserviceaccount.com"),
  )
  if err != nil {
    log.Fatal(err)
  }

  // Send to a single device
  token := "test"
  resp, err := client.Send(
    ctx,
    &messaging.Message{
      Token: token,
      Data: map[string]string{
        "foo": "bar",
      },
    },
  )
  if err != nil {
    log.Fatal(err)
  }

  fmt.Println("success count:", resp.SuccessCount)
  fmt.Println("failure count:", resp.FailureCount)
  fmt.Println("message id:", resp.Responses[0].MessageID)
  fmt.Println("error msg:", resp.Responses[0].Error)

  // Send to topic
  resp, err = client.Send(
    ctx,
    &messaging.Message{
      Data: map[string]string{
        "foo": "bar",
      },
      Topic: "highScores",
    },
  )
  if err != nil {
    log.Fatal(err)
  }

  // Send with condition
  // Define a condition which will send to devices which are subscribed
  // to either the Google stock or the tech industry topics.
  condition := "'stock-GOOG' in topics || 'industry-tech' in topics"

  // See documentation on defining a message payload.
  message := &messaging.Message{
    Data: map[string]string{
      "score": "850",
      "time":  "2:45",
    },
    Condition: condition,
  }

  resp, err = client.Send(
    ctx,
    message,
  )
  if err != nil {
    log.Fatal(err)
  }

  // Send multiple messages to device
  // Create a list containing up to 500 messages.
  registrationToken := "YOUR_REGISTRATION_TOKEN"
  messages := []*messaging.Message{
    {
      Notification: &messaging.Notification{
        Title: "Price drop",
        Body:  "5% off all electronics",
      },
      Token: registrationToken,
    },
    {
      Notification: &messaging.Notification{
        Title: "Price drop",
        Body:  "2% off all books",
      },
      Topic: "readers-club",
    },
  }
  resp, err = client.Send(
    ctx,
    messages...,
  )
  if err != nil {
    log.Fatal(err)
  }

  // Send multicast message
  // Create a list containing up to 500 registration tokens.
  // This registration tokens come from the client FCM SDKs.
  registrationTokens := []string{
    "YOUR_REGISTRATION_TOKEN_1",
    // ...
    "YOUR_REGISTRATION_TOKEN_n",
  }
  msg := &messaging.MulticastMessage{
    Data: map[string]string{
      "score": "850",
      "time":  "2:45",
    },
    Tokens: registrationTokens,
  }
  resp, err = client.SendMulticast(
    ctx,
    msg,
  )
  if err != nil {
    log.Fatal(err)
  }

  fmt.Printf("%d messages were sent successfully\n", resp.SuccessCount)
  if resp.FailureCount > 0 {
    var failedTokens []string
    for idx, resp := range resp.Responses {
      if !resp.Success {
        // The order of responses corresponds to the order of the registration tokens.
        failedTokens = append(failedTokens, registrationTokens[idx])
      }
    }

    fmt.Printf("List of tokens that caused failures: %v\n", failedTokens)
  }
}
Custom HTTP Client

You can use a custom HTTP client by passing it to the NewClient function:

func main() {
  httpTimeout := time.Duration(5) * time.Second
  tlsTimeout := time.Duration(5) * time.Second

  transport := &http2.Transport{
    DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
      return tls.DialWithDialer(&net.Dialer{Timeout: tlsTimeout}, network, addr, cfg)
    },
  }

  httpClient := &http.Client{
    Transport: transport,
    Timeout:   httpTimeout,
  }

  ctx := context.Background()
  client, err := fcm.NewClient(
    ctx,
    fcm.WithCredentialsFile("path/to/serviceAccountKey.json"),
    fcm.WithHTTPClient(httpClient),
  )
}
Custom Proxy Server

You can use a custom proxy server by passing it to the NewClient function:

func main() {
  ctx := context.Background()
  client, err := fcm.NewClient(
    ctx,
    fcm.WithCredentialsFile("path/to/serviceAccountKey.json"),
    fcm.WithHTTPProxy("http://localhost:8088"),
  )
}
Mock Client for Testing

You can use a mock client for Unit Testing by initializing your NewClient with the following:

  • fcm.WithEndpoint with a local httptest.NewServer URL
  • fcm.WithProjectID any string
  • fcm.WithServiceAccount any string
  • fcm.WithCustomClientOption with option option.WithoutAuthentication()
package main

import (
  "context"
  "net/http"
  "net/http/httptest"
  "testing"

  "firebase.google.com/go/v4/messaging"
  fcm "github.com/appleboy/go-fcm"
  "google.golang.org/api/option"
)

func TestMockClient(t *testing.T) {
  server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(http.StatusOK)
    w.Header().Set("Content-Type", "application/json")
    _, _ = w.Write([]byte(`{
      "name": "q1w2e3r4"
    }`))
  }))
  defer server.Close()

  client, err := fcm.NewClient(
    context.Background(),
    fcm.WithEndpoint(server.URL),
    fcm.WithProjectID("test"),
    fcm.WithCustomClientOption(option.WithoutAuthentication()),
  )
  if err != nil {
    t.Fatalf("unexpected error: %v", err)
  }
  resp, err := client.Send(
    context.Background(),
    &messaging.Message{
      Token: "test",
      Data: map[string]string{
        "foo": "bar",
      },
    })
  if err != nil {
    t.Fatalf("unexpected error: %v", err)
  }
  checkSuccessfulBatchResponseForSendEach(t, resp)
}

func checkSuccessfulBatchResponseForSendEach(t *testing.T, resp *messaging.BatchResponse) {
  if resp.SuccessCount != 1 {
    t.Fatalf("expected 1 successes\ngot: %d sucesses", resp.SuccessCount)
  }
  if resp.FailureCount != 0 {
    t.Fatalf("expected 0 failures\ngot: %d failures", resp.FailureCount)
  }
}

Documentation

Overview

Package fcm provides Firebase Cloud Messaging functionality for Golang

Here is a simple example illustrating how to use FCM library:

func main() {
	ctx := context.Background()
	client, err := fcm.NewClient(
		ctx,
		fcm.WithCredentialsFile("path/to/serviceAccountKey.json"),
	)
	if err != nil {
		log.Fatal(err)
	}

// Send to a single device
token := "test"
resp, err := client.Send(

ctx,
&messaging.Message{
	Token: token,
	Data: map[string]string{
		"foo": "bar",
	},
},

)

	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("success count:", resp.SuccessCount)
	fmt.Println("failure count:", resp.FailureCount)
	fmt.Println("message id:", resp.Responses[0].MessageID)
	fmt.Println("error msg:", resp.Responses[0].Error)
}

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client abstracts the interaction between the application server and the FCM server via HTTP protocol. The developer must obtain an API key from the Google APIs Console page and pass it to the `Client` so that it can perform authorized requests on the application server's behalf. To send a message to one or more devices use the Client's Send.

If the `HTTP` field is nil, a zeroed http.Client will be allocated and used to send messages.

Authorization Scopes Requires one of the following OAuth scopes: - https://www.googleapis.com/auth/firebase.messaging

func NewClient

func NewClient(ctx context.Context, opts ...Option) (*Client, error)

NewClient creates new Firebase Cloud Messaging Client based on API key and with default endpoint and http client.

func (*Client) Send

func (c *Client) Send(ctx context.Context, message ...*messaging.Message) (*messaging.BatchResponse, error)

SendWithContext sends a message to the FCM server without retrying in case of service unavailability. A non-nil error is returned if a non-recoverable error occurs (i.e. if the response status is not "200 OK"). Behaves just like regular send, but uses external context.

func (*Client) SendDryRun added in v1.0.0

func (c *Client) SendDryRun(ctx context.Context, message ...*messaging.Message) (*messaging.BatchResponse, error)

SendDryRun sends the messages in the given array via Firebase Cloud Messaging in the dry run (validation only) mode.

func (*Client) SendMulticast added in v1.0.0

func (c *Client) SendMulticast(ctx context.Context, message *messaging.MulticastMessage) (*messaging.BatchResponse, error)

SendEachForMulticast sends the given multicast message to all the FCM registration tokens specified.

func (*Client) SendMulticastDryRun added in v1.0.0

func (c *Client) SendMulticastDryRun(ctx context.Context, message *messaging.MulticastMessage) (*messaging.BatchResponse, error)

SendEachForMulticastDryRun sends the given multicast message to all the specified FCM registration tokens in the dry run (validation only) mode.

func (*Client) SubscribeTopic added in v1.0.0

func (c *Client) SubscribeTopic(ctx context.Context, tokens []string, topic string) (*messaging.TopicManagementResponse, error)

SubscribeToTopic subscribes a list of registration tokens to a topic.

The tokens list must not be empty, and have at most 1000 tokens.

func (*Client) UnsubscribeTopic added in v1.0.0

func (c *Client) UnsubscribeTopic(ctx context.Context, tokens []string, topic string) (*messaging.TopicManagementResponse, error)

UnsubscribeFromTopic unsubscribes a list of registration tokens from a topic.

The tokens list must not be empty, and have at most 1000 tokens.

type Option

type Option func(*Client) error

Option configurates Client with defined option.

func WithCredentialsFile added in v1.0.0

func WithCredentialsFile(filename string) Option

WithCredentialsFile returns a ClientOption that authenticates API calls with the given service account or refresh token JSON credentials file.

func WithCredentialsJSON added in v1.0.0

func WithCredentialsJSON(data []byte) Option

WithCredentialsJSON returns a ClientOption that authenticates API calls with the given service account or refresh token JSON credentials.

func WithCustomClientOption added in v1.2.0

func WithCustomClientOption(opts ...option.ClientOption) Option

WithCustomClientOption is an option function that allows you to provide custom client options. It appends the provided custom options to the client's options list. The custom options are applied when sending requests to the FCM server. If no custom options are provided, this function does nothing.

Parameters:

  • opts: The custom client options to be appended to the client's options list.

Returns:

  • An error if there was an issue appending the custom options to the client's options list, or nil otherwise.

func WithDebug added in v1.1.0

func WithDebug(debug bool) Option

WithDebug returns Option to configure debug mode.

func WithEndpoint

func WithEndpoint(endpoint string) Option

WithEndpoint returns Option to configure endpoint.

func WithHTTPClient

func WithHTTPClient(httpClient *http.Client) Option

WithHTTPClient returns Option to configure HTTP Client.

func WithHTTPProxy added in v0.1.6

func WithHTTPProxy(proxyURL string) Option

WithHTTPProxy returns Option to configure HTTP Client proxy.

func WithProjectID added in v1.0.0

func WithProjectID(projectID string) Option

WithProjectID returns Option to configure project ID.

func WithServiceAccount added in v1.0.0

func WithServiceAccount(serviceAccount string) Option

WithServiceAccount returns Option to configure service account.

func WithTokenSource added in v1.0.0

func WithTokenSource(s oauth2.TokenSource) Option

WithTokenSource returns a ClientOption that specifies an OAuth2 token source to be used as the basis for authentication.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL