복붙노트

PHP가 포함 된 GCM (Google 클라우드 메시징)

PHP

PHP가 포함 된 GCM (Google 클라우드 메시징)

새 Google Cloud Messaging을 PHP 백엔드에 통합하려면 어떻게해야합니까?

해결법

  1. ==============================

    1.이 코드는 PHP CURL을 통해 여러 등록 ID로 GCM 메시지를 보냅니다.

    이 코드는 PHP CURL을 통해 여러 등록 ID로 GCM 메시지를 보냅니다.

    // Payload data you want to send to Android device(s)
    // (it will be accessible via intent extras)    
    $data = array('message' => 'Hello World!');
    
    // The recipient registration tokens for this notification
    // https://developer.android.com/google/gcm/    
    $ids = array('abc', 'def');
    
    // Send push notification via Google Cloud Messaging
    sendPushNotification($data, $ids);
    
    function sendPushNotification($data, $ids) {
        // Insert real GCM API key from the Google APIs Console
        // https://code.google.com/apis/console/        
        $apiKey = 'abc';
    
        // Set POST request body
        $post = array(
                        'registration_ids'  => $ids,
                        'data'              => $data,
                     );
    
        // Set CURL request headers 
        $headers = array( 
                            'Authorization: key=' . $apiKey,
                            'Content-Type: application/json'
                        );
    
        // Initialize curl handle       
        $ch = curl_init();
    
        // Set URL to GCM push endpoint     
        curl_setopt($ch, CURLOPT_URL, 'https://gcm-http.googleapis.com/gcm/send');
    
        // Set request method to POST       
        curl_setopt($ch, CURLOPT_POST, true);
    
        // Set custom request headers       
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    
        // Get the response back as string instead of printing it       
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    
        // Set JSON post data
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post));
    
        // Actually send the request    
        $result = curl_exec($ch);
    
        // Handle errors
        if (curl_errno($ch)) {
            echo 'GCM error: ' . curl_error($ch);
        }
    
        // Close curl handle
        curl_close($ch);
    
        // Debug GCM response       
        echo $result;
    }
    
  2. ==============================

    2.

    <?php
        // Replace with the real server API key from Google APIs
        $apiKey = "your api key";
    
        // Replace with the real client registration IDs
        $registrationIDs = array( "reg id1","reg id2");
    
        // Message to be sent
        $message = "hi Shailesh";
    
        // Set POST variables
        $url = 'https://android.googleapis.com/gcm/send';
    
        $fields = array(
            'registration_ids' => $registrationIDs,
            'data' => array( "message" => $message ),
        );
        $headers = array(
            'Authorization: key=' . $apiKey,
            'Content-Type: application/json'
        );
    
        // Open connection
        $ch = curl_init();
    
        // Set the URL, number of POST vars, POST data
        curl_setopt( $ch, CURLOPT_URL, $url);
        curl_setopt( $ch, CURLOPT_POST, true);
        curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true);
        //curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( $fields));
    
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        // curl_setopt($ch, CURLOPT_POST, true);
        // curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode( $fields));
    
        // Execute post
        $result = curl_exec($ch);
    
        // Close connection
        curl_close($ch);
        echo $result;
        //print_r($result);
        //var_dump($result);
    ?>
    
  3. ==============================

    3.쉽게 할 수 있습니다. Elad Nava가 여기에 넣은 페이지의 cURL 코드가 작동합니다. Elad는 그가받는 오류에 대해 언급했습니다.

    쉽게 할 수 있습니다. Elad Nava가 여기에 넣은 페이지의 cURL 코드가 작동합니다. Elad는 그가받는 오류에 대해 언급했습니다.

    해당받는 사람의 메시지를 처리하는 동안 발생한 오류를 설명하는 문자열입니다. 가능한 값은 위의 표에 설명 된 것과 동일하며 '사용할 수 없음'(GCM 서버가 사용 중이었고 특정 수신자에 대해 메시지를 처리 ​​할 수 ​​없어 다시 시도 할 수 있음을 나타냄)입니다.

    나는 이미 작동하고있는 것으로 보이는 서비스를 가지고 있으며, 지금까지 내가 가지고있는 것은 모두 Google에서 얻을 수없는 반품입니다. 더 많은 가능성이 곧 바뀔 것입니다.

    질문에 대답하려면 PHP를 사용하고 Zend Framework가 포함 경로에 있는지 확인한 후 다음 코드를 사용하십시오.

    <?php
        ini_set('display_errors',1);
        include"Zend/Loader/Autoloader.php";
        Zend_Loader_Autoloader::getInstance();
    
        $url = 'https://android.googleapis.com/gcm/send';
        $serverApiKey = "YOUR API KEY AS GENERATED IN API CONSOLE";
        $reg = "DEVICE REGISTRATION ID";
    
        $data = array(
                'registration_ids' => array($reg),
                'data' => array('yourname' => 'Joe Bloggs')
        );
    
        print(json_encode($data));
    
        $client = new Zend_Http_Client($url);
        $client->setMethod('POST');
        $client->setHeaders(array("Content-Type" => "application/json", "Authorization" => "key=" . $serverApiKey));
        $client->setRawData(json_encode($data));
        $request = $client->request('POST');
        $body = $request->getBody();
        $headers = $request->getHeaders();
        print("<xmp>");
        var_dump($body);
        var_dump($headers);
    

    그리고 거기에 우리가 가지고 있습니다. Zend Framework PHP에서 Googles의 새로운 GCM을 사용하는 예 (곧 작동합니다).

  4. ==============================

    4.마지막으로 오랜 시간을 검색 한 후 정확히 필요한 부분을 파악할 수있었습니다. PHP를 서버 측 스크립팅 언어로 사용하여 GCM에 연결 다음 튜토리얼은 우리가 시작하기 위해 필요한 모든 것을 설정하는 방법에 대한 분명한 아이디어를 제공합니다 GCM

    마지막으로 오랜 시간을 검색 한 후 정확히 필요한 부분을 파악할 수있었습니다. PHP를 서버 측 스크립팅 언어로 사용하여 GCM에 연결 다음 튜토리얼은 우리가 시작하기 위해 필요한 모든 것을 설정하는 방법에 대한 분명한 아이디어를 제공합니다 GCM

    Google 클라우드 메시징 (GCM), PHP 및 MySQL을 사용하는 Android 푸시 알림

  5. ==============================

    5.사실 내 Zend_Mobile 트리의 한 지점에서이 작업을하고 있습니다. https://github.com/mwillbanks/Zend_Mobile/tree/feature/gcm

    사실 내 Zend_Mobile 트리의 한 지점에서이 작업을하고 있습니다. https://github.com/mwillbanks/Zend_Mobile/tree/feature/gcm

    이것은 ZF 1.12와 함께 출시 될 예정이지만,이를 수행하는 방법에 대한 훌륭한 예제를 제공해야합니다.

    작동 방식에 대한 간단한 데모가 있습니다 ....

    <?php
    require_once 'Zend/Mobile/Push/Gcm.php';
    require_once 'Zend/Mobile/Push/Message/Gcm.php';
    
    $message = new Zend_Mobile_Push_Message_Gcm();
    $message->setId(time());
    $message->addToken('ABCDEF0123456789');
    $message->setData(array(
        'foo' => 'bar',
        'bar' => 'foo',
    ));
    
    $gcm = new Zend_Mobile_Push_Gcm();
    $gcm->setApiKey('MYAPIKEY');
    
    $response = false;
    
    try {
        $response = $gcm->send($message);
    } catch (Zend_Mobile_Push_Exception $e) {
        // all other exceptions only require action to be sent or implementation of exponential backoff.
        die($e->getMessage());
    }
    
    // handle all errors and registration_id's
    foreach ($response->getResults() as $k => $v) {
        if ($v['registration_id']) {
            printf("%s has a new registration id of: %s\r\n", $k, $v['registration_id']);
        }
        if ($v['error']) {
            printf("%s had an error of: %s\r\n", $k, $v['error']);
        }
        if ($v['message_id']) {
            printf("%s was successfully sent the message, message id is: %s", $k, $v['message_id']);
        }
    }
    
  6. ==============================

    6.많은 자습서는 시대에 뒤떨 롭고 심지어 현재 코드는 장치 registration_ids가 업데이트되거나 장치가 등록 해제되는시기를 고려하지 않습니다. 이러한 항목을 선택하지 않으면 메시지가 수신되지 않도록하는 문제가 발생할 수 있습니다. http://forum.loungekatt.com/viewtopic.php?t=63#p181

    많은 자습서는 시대에 뒤떨 롭고 심지어 현재 코드는 장치 registration_ids가 업데이트되거나 장치가 등록 해제되는시기를 고려하지 않습니다. 이러한 항목을 선택하지 않으면 메시지가 수신되지 않도록하는 문제가 발생할 수 있습니다. http://forum.loungekatt.com/viewtopic.php?t=63#p181

  7. ==============================

    7.또한이 코드 조각을 소스로 사용해 볼 수도 있습니다.

    또한이 코드 조각을 소스로 사용해 볼 수도 있습니다.

    <?php
        define("GOOGLE_API_KEY", "AIzaSyCJiVkatisdQ44rEM353PFGbia29mBVscA");
        define("GOOGLE_GCM_URL", "https://android.googleapis.com/gcm/send");
    
        function send_gcm_notify($reg_id, $message) {
            $fields = array(
                'registration_ids'  => array( $reg_id ),
                'data'              => array( "message" => $message ),
            );
    
            $headers = array(
                'Authorization: key=' . GOOGLE_API_KEY,
                'Content-Type: application/json'
            );
    
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, GOOGLE_GCM_URL);
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
    
            $result = curl_exec($ch);
            if ($result === FALSE) {
                die('Problem occurred: ' . curl_error($ch));
            }
    
            curl_close($ch);
            echo $result;
        }
    
        $reg_id = "APA91bHuSGES.....nn5pWrrSz0dV63pg";
        $msg = "Google Cloud Messaging working well";
    
        send_gcm_notify($reg_id, $msg);
    
  8. ==============================

    8.

    <?php
    
    function sendMessageToPhone($deviceToken, $collapseKey, $messageText, $yourKey) {    
        echo "DeviceToken:".$deviceToken."Key:".$collapseKey."Message:".$messageText
                ."API Key:".$yourKey."Response"."<br/>";
    
        $headers = array('Authorization:key=' . $yourKey);    
        $data = array(    
            'registration_id' => $deviceToken,          
            'collapse_key' => $collapseKey,
            'data.message' => $messageText);  
        $ch = curl_init();    
    
        curl_setopt($ch, CURLOPT_URL, "https://android.googleapis.com/gcm/send");    
        if ($headers)    
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);    
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);    
        curl_setopt($ch, CURLOPT_POST, true);    
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);    
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);    
    
        $response = curl_exec($ch);    
        var_dump($response);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);    
        if (curl_errno($ch)) {
            return false;
        }    
        if ($httpCode != 200) {
            return false;
        }    
        curl_close($ch);    
        return $response;    
    }  
    
    $yourKey = "YOURKEY";
    $deviceToken = "REGISTERED_ID";
    $collapseKey = "COLLAPSE_KEY";
    $messageText = "MESSAGE";
    echo sendMessageToPhone($deviceToken, $collapseKey, $messageText, $yourKey);
    ?>
    

    위의 스크립트에서 변경하십시오.

    이 문제에 어떤 문제가 발생하는 경우 알려주십시오. 동일한 스크립트를 사용하여 성공적으로 알림을받을 수 있습니다.

  9. ==============================

    9.packagist에서이 PHP 라이브러리를 사용할 수 있습니다 :

    packagist에서이 PHP 라이브러리를 사용할 수 있습니다 :

    https://github.com/CoreProc/gcm-php

    그것을 설치 한 후에 이것을 할 수 있습니다 :

    $gcmClient = new GcmClient('your-gcm-api-key-here');
    
    $message = new Message($gcmClient);
    
    $message->addRegistrationId('xxxxxxxxxx');
    $message->setData([
        'title' => 'Sample Push Notification',
        'message' => 'This is a test push notification using Google Cloud Messaging'
    ]);
    
    try {
    
        $response = $message->send();
    
        // The send() method returns a Response object
        print_r($response);
    
    } catch (Exception $exception) {
    
        echo 'uh-oh: ' . $exception->getMessage();
    
    }
    
  10. ==============================

    10.다음은 CodeMonkeysRU에서 포크 라이브러리입니다.

    다음은 CodeMonkeysRU에서 포크 라이브러리입니다.

    내가 포크로 쓴 이유는 Google이 기하 급수적 인 백 오프를 필요로하기 때문입니다. 나는 메시지를 대기열에 넣고 정해진 시간 후에 다시 보내려면 redis 서버를 사용한다.

    또한 iOS를 지원하도록 업데이트했습니다.

    https://github.com/stevetauber/php-gcm-queue

  11. ==============================

    11.여기에 @Elad Nava가 게시 한 PHP 코드의 안드로이드 코드가 있습니다.

    여기에 @Elad Nava가 게시 한 PHP 코드의 안드로이드 코드가 있습니다.

    MainActivity.java (실행 프로그램 활동)

    public class MainActivity extends AppCompatActivity {
        String PROJECT_NUMBER="your project number/sender id";
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
    
    
            GCMClientManager pushClientManager = new GCMClientManager(this, PROJECT_NUMBER);
            pushClientManager.registerIfNeeded(new GCMClientManager.RegistrationCompletedHandler() {
                @Override
                public void onSuccess(String registrationId, boolean isNewRegistration) {
    
                    Log.d("Registration id", registrationId);
                    //send this registrationId to your server
                }
    
                @Override
                public void onFailure(String ex) {
                    super.onFailure(ex);
                }
            });
        }
    }
    

    GCMClientManager.java

    public class GCMClientManager {
        // Constants
        public static final String TAG = "GCMClientManager";
        public static final String EXTRA_MESSAGE = "message";
        public static final String PROPERTY_REG_ID = "your sender id";
        private static final String PROPERTY_APP_VERSION = "appVersion";
        private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
        // Member variables
        private GoogleCloudMessaging gcm;
        private String regid;
        private String projectNumber;
        private Activity activity;
        public GCMClientManager(Activity activity, String projectNumber) {
            this.activity = activity;
            this.projectNumber = projectNumber;
            this.gcm = GoogleCloudMessaging.getInstance(activity);
        }
        /**
         * @return Application's version code from the {@code PackageManager}.
         */
        private static int getAppVersion(Context context) {
            try {
                PackageInfo packageInfo = context.getPackageManager()
                        .getPackageInfo(context.getPackageName(), 0);
                return packageInfo.versionCode;
            } catch (NameNotFoundException e) {
                // should never happen
                throw new RuntimeException("Could not get package name: " + e);
            }
        }
        // Register if needed or fetch from local store
        public void registerIfNeeded(final RegistrationCompletedHandler handler) {
            if (checkPlayServices()) {
                regid = getRegistrationId(getContext());
                if (regid.isEmpty()) {
                    registerInBackground(handler);
                } else { // got id from cache
                    Log.i(TAG, regid);
                    handler.onSuccess(regid, false);
                }
            } else { // no play services
                Log.i(TAG, "No valid Google Play Services APK found.");
            }
        }
        /**
         * Registers the application with GCM servers asynchronously.
         * <p>
         * Stores the registration ID and app versionCode in the application's
         * shared preferences.
         */
        private void registerInBackground(final RegistrationCompletedHandler handler) {
            new AsyncTask<Void, Void, String>() {
                @Override
                protected String doInBackground(Void... params) {
                    try {
                        if (gcm == null) {
                            gcm = GoogleCloudMessaging.getInstance(getContext());
                        }
                        InstanceID instanceID = InstanceID.getInstance(getContext());
                        regid = instanceID.getToken(projectNumber, GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
                        Log.i(TAG, regid);
                        // Persist the regID - no need to register again.
                        storeRegistrationId(getContext(), regid);
                    } catch (IOException ex) {
                        // If there is an error, don't just keep trying to register.
                        // Require the user to click a button again, or perform
                        // exponential back-off.
                        handler.onFailure("Error :" + ex.getMessage());
                    }
                    return regid;
                }
                @Override
                protected void onPostExecute(String regId) {
                    if (regId != null) {
                        handler.onSuccess(regId, true);
                    }
                }
            }.execute(null, null, null);
        }
        /**
         * Gets the current registration ID for application on GCM service.
         * <p>
         * If result is empty, the app needs to register.
         *
         * @return registration ID, or empty string if there is no existing
         *     registration ID.
         */
        private String getRegistrationId(Context context) {
            final SharedPreferences prefs = getGCMPreferences(context);
            String registrationId = prefs.getString(PROPERTY_REG_ID, "");
            if (registrationId.isEmpty()) {
                Log.i(TAG, "Registration not found.");
                return "";
            }
            // Check if app was updated; if so, it must clear the registration ID
            // since the existing regID is not guaranteed to work with the new
            // app version.
            int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
            int currentVersion = getAppVersion(context);
            if (registeredVersion != currentVersion) {
                Log.i(TAG, "App version changed.");
                return "";
            }
            return registrationId;
        }
        /**
         * Stores the registration ID and app versionCode in the application's
         * {@code SharedPreferences}.
         *
         * @param context application's context.
         * @param regId registration ID
         */
        private void storeRegistrationId(Context context, String regId) {
            final SharedPreferences prefs = getGCMPreferences(context);
            int appVersion = getAppVersion(context);
            Log.i(TAG, "Saving regId on app version " + appVersion);
            SharedPreferences.Editor editor = prefs.edit();
            editor.putString(PROPERTY_REG_ID, regId);
            editor.putInt(PROPERTY_APP_VERSION, appVersion);
            editor.commit();
        }
        private SharedPreferences getGCMPreferences(Context context) {
            // This sample app persists the registration ID in shared preferences, but
            // how you store the regID in your app is up to you.
            return getContext().getSharedPreferences(context.getPackageName(),
                    Context.MODE_PRIVATE);
        }
        /**
         * Check the device to make sure it has the Google Play Services APK. If
         * it doesn't, display a dialog that allows users to download the APK from
         * the Google Play Store or enable it in the device's system settings.
         */
        private boolean checkPlayServices() {
            int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getContext());
            if (resultCode != ConnectionResult.SUCCESS) {
                if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
                    GooglePlayServicesUtil.getErrorDialog(resultCode, getActivity(),
                            PLAY_SERVICES_RESOLUTION_REQUEST).show();
                } else {
                    Log.i(TAG, "This device is not supported.");
                }
                return false;
            }
            return true;
        }
        private Context getContext() {
            return activity;
        }
        private Activity getActivity() {
            return activity;
        }
        public static abstract class RegistrationCompletedHandler {
            public abstract void onSuccess(String registrationId, boolean isNewRegistration);
            public void onFailure(String ex) {
                // If there is an error, don't just keep trying to register.
                // Require the user to click a button again, or perform
                // exponential back-off.
                Log.e(TAG, ex);
            }
        }
    }
    

    PushNotificationService.java (알림 생성기)

    public class PushNotificationService extends GcmListenerService{
    
        public static int MESSAGE_NOTIFICATION_ID = 100;
    
        @Override
        public void onMessageReceived(String from, Bundle data) {
            String message = data.getString("message");
            sendNotification("Hi-"+message, "My App sent you a message");
        }
    
        private void sendNotification(String title, String body) {
            Context context = getBaseContext();
            NotificationCompat.Builder mBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(context)
                    .setSmallIcon(R.mipmap.ic_launcher).setContentTitle(title)
                    .setContentText(body);
            NotificationManager mNotificationManager = (NotificationManager) context
                    .getSystemService(Context.NOTIFICATION_SERVICE);
            mNotificationManager.notify(MESSAGE_NOTIFICATION_ID, mBuilder.build());
        }
    }
    

    AndroidManifest.xml

    <?xml version="1.0" encoding="utf-8"?>
    

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
    <permission android:name="com.example.gcm.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />
    <uses-permission android:name="com.example.gcm.permission.C2D_MESSAGE" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme" >
        <activity android:name=".MainActivity" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
    
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    
        <service
            android:name=".PushNotificationService"
            android:exported="false">
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            </intent-filter>
        </service>
    
        <receiver
            android:name="com.google.android.gms.gcm.GcmReceiver"
            android:exported="true"
            android:permission="com.google.android.c2dm.permission.SEND">
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                <category android:name="package.gcmdemo" />
            </intent-filter>
        </receiver>
    </application>
    

  12. ==============================

    12.이것을 사용하십시오.

    이것을 사용하십시오.

     function pnstest(){
    
                    $data = array('post_id'=>'12345','title'=>'A Blog post', 'message' =>'test msg');
    
                    $url = 'https://fcm.googleapis.com/fcm/send';
    
                    $server_key = 'AIzaSyDVpDdS7EyNgMUpoZV6sI2p-cG';
    
                    $target ='fO3JGJw4CXI:APA91bFKvHv8wzZ05w2JQSor6D8lFvEGE_jHZGDAKzFmKWc73LABnumtRosWuJx--I4SoyF1XQ4w01P77MKft33grAPhA8g-wuBPZTgmgttaC9U4S3uCHjdDn5c3YHAnBF3H';
    
                    $fields = array();
                    $fields['data'] = $data;
                    if(is_array($target)){
                        $fields['registration_ids'] = $target;
                    }else{
                        $fields['to'] = $target;
                    }
    
                    //header with content_type api key
                    $headers = array(
                        'Content-Type:application/json',
                      'Authorization:key='.$server_key
                    );
    
                    $ch = curl_init();
                    curl_setopt($ch, CURLOPT_URL, $url);
                    curl_setopt($ch, CURLOPT_POST, true);
                    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
                    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
                    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
                    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
                    $result = curl_exec($ch);
                    if ($result === FALSE) {
                        die('FCM Send Error: ' . curl_error($ch));
                    }
                    curl_close($ch);
                    return $result;
    
    }
    
  13. from https://stackoverflow.com/questions/11242743/gcm-with-php-google-cloud-messaging by cc-by-sa and MIT license