const {JWT} = require('google-auth-library');
const axios = require('axios');
function getAccessToken() {
return new Promise(function(resolve, reject) {
const key = require('./clubrubicone-firebase.json');
const SCOPES = ['https://www.googleapis.com/auth/firebase.messaging'];
const jwtClient = new JWT(
key.client_email,
null,
key.private_key,
SCOPES,
null
);
jwtClient.authorize(function(err, tokens) {
if (err) {
reject(err);
return;
}
resolve(tokens.access_token);
});
});
}
// FCM 令牌转换为 APN 令牌
const apnToken = 'a8f8c105414a59efe563a45801028a8e366d8307b5611146cdf07456681'; //apns令牌
const application = '你的软件包';
const sandbox = true;
const convertToFCMToken = async () => {
const accessToken = await getAccessToken();
const url = `https://iid.googleapis.com/iid/v1:batchImport`;
const headers = {
'Authorization': `Bearer ${accessToken}`,
'access_token_auth': 'true',
'Content-Type': 'application/json'
};
const data = {
application,
sandbox,
apns_tokens: [apnToken]
};
axios.post(url, data, {headers})
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error(error);
});
}
convertToFCMToken();
// getAccessToken().then(token => console.log(token));
package main
import (
"bytes"
"context"
"encoding/json"
firebase "firebase.google.com/go/v4"
"firebase.google.com/go/v4/messaging"
"fmt"
"golang.org/x/oauth2/google"
"google.golang.org/api/option"
"io"
"log"
"net/http"
)
// 获取Google认证令牌
func getGoogleAuthToken() (string, error) {
// 获取 Google 认证令牌
credentialData, err := getCredentialsData()
if err != nil {
return "", fmt.Errorf("获取凭证失败: %v", err)
}
// 从JSON创建配置
conf, err := google.JWTConfigFromJSON(credentialData,
"https://www.googleapis.com/auth/firebase.messaging",
"https://www.googleapis.com/auth/cloud-platform",
)
if err != nil {
return "", fmt.Errorf("创建配置失败: %v", err)
}
// 创建HTTP客户端
ctx := context.Background()
// 获取访问令牌
token, err := conf.TokenSource(ctx).Token()
if err != nil {
return "", fmt.Errorf("获取令牌失败: %v", err)
}
fmt.Printf("已获取 Google 令牌: %s\n", token.AccessToken)
return token.AccessToken, nil
}
// 获取 Firebase 凭证
func getCredentialsData() ([]byte, error) {
// 获取 Firebase 凭证
url := "https://xxxx.xxxx/files/club-rubicone-firebase-adminsdk.json"
resp, err := http.Get(url)
if err != nil {
return nil, err
}
defer resp.Body.Close()
// 读取JSON数据
credentialData, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return credentialData, nil
}
// 发送消息
func sendMessage(fcmToken string, title string, body string) {
// 获取 Google 认证令牌
credentialData, err := getCredentialsData()
if err != nil {
log.Fatalf("获取凭证失败: %v\n", err)
}
opt := option.WithCredentialsJSON(credentialData)
ctx := context.Background()
fcmApp, err := firebase.NewApp(ctx, nil, opt)
if err != nil {
log.Fatalf("初始化应用失败: %v\n", err)
}
// 获取消息客户端
fcmMsgClient, err := fcmApp.Messaging(ctx)
if err != nil {
log.Fatalf("初始化消息客户端失败: %v\n", err)
}
// 设置 APNS 配置
apns := &messaging.APNSConfig{
Payload: &messaging.APNSPayload{
Aps: &messaging.Aps{
Sound: "default",
},
},
}
zero := -1
apns.Payload.Aps.Badge = &zero
// 设置 FCM 消息
message := &messaging.Message{
Token: fcmToken,
Notification: &messaging.Notification{
Title: title,
Body: body,
},
Data: map[string]string{"ex": ""},
APNS: apns,
}
// 验证令牌是否为空
if message.Token == "" {
log.Fatalf("FCM消息发送失败: 令牌不能为空\n")
}
// 发送消息
response, err := fcmMsgClient.Send(ctx, message)
if err != nil {
log.Fatalf("发送FCM消息失败: %v\n", err)
}
// 打印成功响应
log.Printf("成功发送消息,消息ID: %s\n", response)
}
// 转换 APNS 令牌为 FCM 令牌
func convertApnsTokenToFcmToken(apnsToken string) (string, error) {
token, err := getGoogleAuthToken()
if err != nil {
return "", fmt.Errorf("获取令牌失败: %v", err)
}
// 构建请求数据
url := "https://iid.googleapis.com/iid/v1:batchImport"
headers := map[string]string{
"Authorization": fmt.Sprintf("Bearer %s", token),
"access_token_auth": "true",
"Content-Type": "application/json",
}
data := map[string]interface{}{
"application": "club.rubicone",
"sandbox": true,
"apns_tokens": []string{apnsToken},
}
jsonData, err := json.Marshal(data)
if err != nil {
return "", fmt.Errorf("序列化请求数据失败: %v", err)
}
// 发送请求
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
if err != nil {
return "", fmt.Errorf("创建请求失败: %v", err)
}
for key, value := range headers {
req.Header.Set(key, value)
}
// 发送请求
resp, err := http.DefaultClient.Do(req)
if err != nil {
return "", fmt.Errorf("发送请求失败: %v", err)
}
defer resp.Body.Close()
// 读取响应
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("读取响应失败: %v", err)
}
var responseData struct {
Results []struct {
RegistrationToken string `json:"registration_token"`
ApnsToken string `json:"apns_token"`
Status string `json:"status"`
} `json:"results"`
}
if err := json.Unmarshal(body, &responseData); err != nil {
return "", fmt.Errorf("解析响应失败: %v", err)
}
// 提取 FCM 令牌
fcmToken := responseData.Results[0].RegistrationToken
return fcmToken, nil
}
func main() {
token, err := convertApnsTokenToFcmToken("a8f8c105414a59efe563a45801028a8e366d8307b561114513ae66681")
if err != nil {
log.Fatalf("获取令牌失败: %v\n", err)
}
fmt.Println(token)
sendMessage(token, "新", "测试内容123131")
// 初始化 Firebase 应用
}
评论区