2017-02-21 7 views
9

मैंने अपनी वेबसाइट के लिए पुश अधिसूचना सेवा विकसित की है। सेवा कार्यकर्ता है:वेब पुष्नोटिफिकेशन 'अनधिकृत पंजीकरण' या 'गोन' या 'अनधिकृत' - सदस्यता समाप्त हो जाती है

'use strict'; 
    self.addEventListener('push', function (event) {  
    var msg = {}; 
    if (event.data) { 
     msg = event.data.json(); 
    }  
    let notificationTitle = msg.title; 
    const notificationOptions = { 
     body: msg.body,//body 
     dir:'rtl',//direction 
     icon: msg.icon,//image 
     data: { 
      url: msg.url,//click 
     }, 
    }; 
    event.waitUntil(
     Promise.all([ 
     self.registration.showNotification(
      notificationTitle, notificationOptions),  
     ]) 
    ); 
    }); 
    self.addEventListener('notificationclick', function (event) {  
     event.notification.close(); 

    let clickResponsePromise = Promise.resolve(); 
    if (event.notification.data && event.notification.data.url) { 
     clickResponsePromise = clients.openWindow(event.notification.data.url); 
    } 
    const fetchOptions = 
     { method: 'post'}; 
    fetch('http://localhost:5333/usrh.ashx?click=true', fetchOptions). 
    then(function (response) 
    { 
     if (response.status >= 400 && response.status < 500) 
     {   
      throw new Error('Failed to send push message via web push protocol'); 
     } 
    }).catch((err) => 
    { 
     this.showErrorMessage('Ooops Unable to Send a Click', err); 
    }); 
}); 

self.addEventListener('notificationclose', function (event) { 
    const fetchOptions = 
     { method: 'post'}; 
    fetch('http://localhost:5333/usrh.ashx?close=true', fetchOptions). 
    then(function (response) 
    { 
     if (response.status >= 400 && response.status < 500) 
     {   
      throw new Error('Failed to send push message via web push protocol'); 
     } 
    }).catch((err) => 
    { 
     this.showErrorMessage('Ooops Unable to Send a Click', err); 
    }); 
}); 
self.addEventListener('pushsubscriptionchange', function() { 
    const fetchOptions = { 
     method: 'post' 
     , 
    }; 

    fetch('http://localhost:5333/usru.ashx', fetchOptions) 
     .then(function (response) { 
      if (response.status >= 400 && response.status < 500) { 
       console.log('Failed web push response: ', response, response.status); 
       throw new Error('Failed to update users.'); 
      } 
     }) 
     .catch((err) => { 
      this.showErrorMessage('Ooops Unable to Send a user', err); 
     }); 
}); 

मैं सफलतापूर्वक निम्नलिखित कोड का उपयोग कर उपयोगकर्ताओं की सदस्यता ली है:

registerServiceWorker() { 
     if ('serviceWorker' in navigator) { 
      navigator.serviceWorker.register('http://localhost:5333/service-worker.js') 
       .catch((err) => { 
        this.showErrorMessage('Unable to Register SW', 'Sorry this demo requires a service worker to work and it ' + 'failed to install - sorry :('); 
        console.error(err); 
       }); 
     } else { 
      this.showErrorMessage('Service Worker Not Supported', 'Sorry this demo requires service worker support in your browser. ' + 
       'Please try this demo in Chrome or Firefox Nightly.'); 
     } 
    } 

और

class PushClient { 
    constructor(subscriptionUpdate, appkeys) { 
     this._subscriptionUpdate = subscriptionUpdate; 
     this._publicApplicationKey = appkeys; 
     if (!('serviceWorker' in navigator)) { 
      return; 
     } 
     if (!('PushManager' in window)) { 
      return; 
     } 
     if (!('showNotification' in ServiceWorkerRegistration.prototype)) { 
      return; 
     } 
     navigator.serviceWorker.ready.then(() => { 
      this.setUpPushPermission(); 
     }); 
    } 
    setUpPushPermission() { 
     return navigator.serviceWorker.ready.then((serviceWorkerRegistration) => { 
      return serviceWorkerRegistration.pushManager.getSubscription(); 
     }) 
      .then((subscription) => { 
       if (!subscription) { 
        return; 
       } 
       this._subscriptionUpdate(subscription); 
      }) 
      .catch((err) => { 
       console.log('setUpPushPermission() ', err); 
      }); 
    } 
    subscribeDevice() { 
     return new Promise((resolve, reject) => { 
      if (Notification.permission === 'denied') { 
       sc(3); 
       return reject(new Error('Push messages are blocked.')); 
      } 
      if (Notification.permission === 'granted') { 
       sc(3); 
       return resolve(); 
      } 
      if (Notification.permission === 'default') { 
       Notification.requestPermission((result) => { 
        if (result === 'denied') { 
         sc(0); 
        } else if (result === 'granted') { 
         sc(1); 
        } else { 
         sc(2); 
        } 
        if (result !== 'granted') { 
         reject(new Error('Bad permission result')); 
        } 
        resolve(); 
       }); 
      } 
     }) 
      .then(() => { 
       return navigator.serviceWorker.ready.then((serviceWorkerRegistration) => { 
        return serviceWorkerRegistration.pushManager.subscribe({ 
         userVisibleOnly: true 
         , applicationServerKey: this._publicApplicationKey.publicKey 
        , 
        }); 
       }) 
        .then((subscription) => { 
         this._subscriptionUpdate(subscription); 
         if (subscription) { 
          this.sendPushMessage(subscription); 
         } 
        }) 
        .catch((subscriptionErr) => { }); 
      }) 
      .catch(() => { }); 
    } 
    toBase64(arrayBuffer, start, end) { 
     start = start || 0; 
     end = end || arrayBuffer.byteLength; 
     const partialBuffer = new Uint8Array(arrayBuffer.slice(start, end)); 
     return btoa(String.fromCharCode.apply(null, partialBuffer)); 
    } 
    unsubscribeDevice() { 
     navigator.serviceWorker.ready.then((serviceWorkerRegistration) => { 
      return serviceWorkerRegistration.pushManager.getSubscription(); 
     }) 
      .then((pushSubscription) => { 
       if (!pushSubscription) { 
        this._subscriptionUpdate(null); 
        return; 
       } 
       return pushSubscription.unsubscribe() 
        .then(function (successful) { 
         if (!successful) { 
          console.error('We were unable to unregister from push'); 
         } 
        }); 
      }) 
      .then(() => { 
       this._subscriptionUpdate(null); 
      }) 
      .catch((err) => { 
       console.error('Error thrown while revoking push notifications. ' + 'Most likely because push was never registered', err); 
      }); 
    } 
    sendPushMessage(subscription) { 
     let payloadPromise = Promise.resolve(null); 
     payloadPromise = JSON.parse(JSON.stringify(subscription)); 
     const vapidPromise = EncryptionHelperFactory.createVapidAuthHeader(this._publicApplicationKey, subscription.endpoint, 'http://localhost:5333/'); 
     return Promise.all([payloadPromise, vapidPromise, ]) 
      .then((results) => { 
       const payload = results[0]; 
       const vapidHeaders = results[1]; 
       let infoFunction = this.getWebPushInfo; 
       infoFunction =() => { 
        return this.getWebPushInfo(subscription, payload, vapidHeaders); 
       }; 
       const requestInfo = infoFunction(); 
       this.sendRequestToProxyServer(requestInfo); 
      }); 
    } 
    getWebPushInfo(subscription, payload, vapidHeaders) { 
     let body = null; 
     const headers = {}; 
     headers.TTL = 60; 
     if (payload) { 
      headers.Encryption = `auth=${payload.keys.auth}`; 
      headers['Crypto-Key'] = `p256dh=${payload.keys.p256dh}`; 
      headers['Content-Encoding'] = 'aesgcm'; 
     } else { 
      headers['Content-Length'] = 0; 
     } 
     if (vapidHeaders) { 
      headers.Authorization = `WebPush ${vapidHeaders.authorization}`; 
      if (headers['Crypto-Key']) { 
       headers['Crypto-Key'] = `${headers['Crypto-Key']}; ` + `p256ecdsa=${vapidHeaders.p256ecdsa}`; 
      } else { 
       headers['Crypto-Key'] = `p256ecdsa=${vapidHeaders.p256ecdsa}`; 
      } 
     } 
     const response = { 
      headers: headers 
      , endpoint: subscription.endpoint 
     , 
     }; 
     if (body) { 
      response.body = body; 
     } 
     return response; 
    } 
    sendRequestToProxyServer(requestInfo) { 
     const fetchOptions = { 
      method: 'post' 
     , 
     }; 
     if (requestInfo.body && requestInfo.body instanceof ArrayBuffer) { 
      requestInfo.body = this.toBase64(requestInfo.body); 
      fetchOptions.body = requestInfo; 
     } 
     fetchOptions.body = JSON.stringify(requestInfo); 
     fetch('http://localhost:5333/usrh.ashx', fetchOptions) 
      .then(function (response) { 
       if (response.status >= 400 && response.status < 500) { 
        console.log('Failed web push response: ', response, response.status); 
        throw new Error('Failed to send push message via web push protocol'); 
       } 
      }) 
      .catch((err) => { 
       this.showErrorMessage('Ooops Unable to Send a Push', err); 
      }); 
    } 
} 

इन सभी कोड जावास्क्रिप्ट में हैं। मैं तरह मेरे सर्वर पर सफलतापूर्वक recieve उपयोगकर्ता सदस्यता infromarion कर सकते हैं:

Authorization: WebPush eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJhdWQiOiJodHRwcxxxxx 
Crypto-Key: p256dh=BBp90dwDWxxxxc1TfdBjFPqxxxxxwjO9fCip-K_Eebmg=; p256ecdsa=BDd3_hVL9fZi9Yboxxxxxxo 
endpoint: https://fcm.googleapis.com/fcm/send/cxxxxxxxxxxxxxxJRorOMHKLQ3gtT7 
Encryption: auth=9PzQZ1mut99qxxxxxxxxxxyw== 
Content-Encoding: aesgcm 

इसके अलावा, मैं सफलतापूर्वक एक धक्का इस उपयोगकर्ता के लिए कोड का उपयोग कर bellow सी # में भेज सकते हैं:

public static async Task<bool> SendNotificationByte(string endpoint, string[] Keys, byte[] userSecret, byte[] data = null, 
             int ttl = 0, ushort padding = 0, bool randomisePadding = false, string auth="") 
     { 
      #region send 
      HttpRequestMessage Request = new HttpRequestMessage(HttpMethod.Post, endpoint);     
       Request.Headers.TryAddWithoutValidation("Authorization", auth); 
      Request.Headers.Add("TTL", ttl.ToString()); 
      if (data != null && Keys[1] != null && userSecret != null) 
      { 
       EncryptionResult Package = EncryptMessage(Decode(Keys[1]), userSecret, data, padding, randomisePadding); 
       Request.Content = new ByteArrayContent(Package.Payload); 
       Request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); 
       Request.Content.Headers.ContentLength = Package.Payload.Length; 
       Request.Content.Headers.ContentEncoding.Add("aesgcm"); 
       Request.Headers.Add("Crypto-Key", "dh=" + Encode(Package.PublicKey)+" ;"+Keys[2]+"="+Keys[3]); 
       Request.Headers.Add("Encryption", "salt=" + Encode(Package.Salt)); 
      } 
      using (HttpClient HC = new HttpClient()) 
      { 
       HttpResponseMessage res = await HC.SendAsync(Request).ConfigureAwait(false); 
       if (res.StatusCode == HttpStatusCode.Created) 
        return true; 
       else return false; 
      } 
      #endregion 
     } 

समस्या यह है कि एक अवधि के बाद समय की (लगभग 20 घंटे या उससे कम), जब मैं इस उपयोगकर्ता मैं निम्न त्रुटियों मिला करने के लिए एक धक्का भेजना चाहते हैं:

फ़ायरफ़ॉक्स सदस्यता:

{StatusCode: 410, ReasonPhrase: 'Gone', Version: 1.1, Content: System.Net.Http.StreamContent, Headers: 
{ 
    Access-Control-Allow-Headers: content-encoding,encryption,crypto-key,ttl,encryption-key,content-type,authorization 
    Access-Control-Allow-Methods: POST 
    Access-Control-Allow-Origin: * 
    Access-Control-Expose-Headers: location,www-authenticate 
    Connection: keep-alive 
    Cache-Control: max-age=86400 
    Date: Tue, 21 Feb 2017 08:19:03 GMT 
    Server: nginx 
    Content-Length: 179 
    Content-Type: application/json 
}} 

क्रोम सदस्यता:

{StatusCode: 400, ReasonPhrase: 'UnauthorizedRegistration', Version: 1.1, Content: System.Net.Http.StreamContent, Headers: 
{ 
    X-Content-Type-Options: nosniff 
    X-Frame-Options: SAMEORIGIN 
    X-XSS-Protection: 1; mode=block 
    Alt-Svc: quic=":443"; ma=2592000; v="35,34" 
    Vary: Accept-Encoding 
    Transfer-Encoding: chunked 
    Accept-Ranges: none 
    Cache-Control: max-age=0, private 
    Date: Tue, 21 Feb 2017 08:18:35 GMT 
    Server: GSE 
    Content-Type: text/html; charset=UTF-8 
    Expires: Tue, 21 Feb 2017 08:18:35 GMT 
}} 

मुझे लगता है कि मैं कुछ याद किया, कि बनाता सदस्यता समाप्त होने पर, या जब अपनी सदस्यता जानकारी बदल गया है या समाप्त हो गई है उन पुन: सदस्यता के लिए बनाने के लिए है, लेकिन मैं पता नहीं कैसे ?! !

उत्तर

1

सब्सक्राइब किए गए उपयोगकर्ताओं को पुन: सदस्यता लेने के लिए पुश इको अधिसूचना भेजकर समस्या हल हो जाती है। मैंने एक नौकरी लिखी है जिसमें मैं समय-समय पर पुश गूंज भेजता हूं और उपयोगकर्ताओं की सदस्यता लेता हूं और उनकी जानकारी अपडेट करता हूं।

ऐसा करने के लिए मैं एक विशेष संदेश को "धक्का गूंज" bellow कोड का उपयोग कर भेजें:

self.addEventListener('push', function (event) { 
lastEventName = 'push'; 
var msg = {}; 
if (event.data) { 
    msg = event.data.json(); 
    if (!!msg.isEcho) { 
     self.registration.pushManager.getSubscription() 
      .then(function (subscription) { 
       if (!subscription) { 
       } else { 
        subscription.unsubscribe().then(function() { 
         self.registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: base64UrlToUint8Array('xxxxxxxxxxxxxxxx') }) 
          .then(function (subscription) { 
           resubscription(subscription); 
          }); 
        }); 
        } 
      }); 
     return; 
    } 
} 
if (!!msg.isEcho) 
    return; 
let notificationTitle = msg.title; 
const notificationOptions = { 
    body: msg.body, 
    dir: 'rtl', 
    icon: msg.icon, 
    data: { 
     url: msg.url, 
     id: msg.id, 
     key: msg.key 
    }, 
}; 
event.waitUntil(
    Promise.all([ 
    self.registration.showNotification(
     notificationTitle, notificationOptions), 
    ]) 
); 

const fetchOptions = 
    { method: 'post', mode: 'no-cors' }; 
fetch('http://example.com', fetchOptions). 
    then(function (response) { 
     if (response.status >= 400 && response.status < 500) { 
      throw new Error('Failed to send push message via web push protocol'); 
     } 
     lastEventName = 'view'; 
    }).catch((err) => { 
     this.showErrorMessage('Ooops Unable to Send a Click', err); 
    }); 
}); 

resubscription विधि आप unsubscribe कर सकते हैं और फिर subscribe उपयोगकर्ता और अद्यतन सर्वर डेटा में।

1

कुछ सुराग:

sw पंजीकृत होने के लिए और सक्रिय है, समय धक्का घटना आता है पर जरूरत है। इसका मतलब है कि आप सत्र को साफ नहीं कर सकते हैं, निजी ब्राउज़िंग मोड का उपयोग कर सकते हैं, कंप्यूटर के बीच कैश साफ़ कर सकते हैं।

धक्का घटना एक ही उत्पत्ति से आनी चाहिए।

1

मुझे लगता है कि समस्या यह है कि आप अपना applicationServerKey कैसे भेजते हैं। मैं तो बस आप क्या करना चाहते हैं का एक उदाहरण किया है और मुझे लगता है कि कुंजी इस समारोह के साथ इनकोडिंग भेजने के लिए किया था:

function urlBase64ToUint8Array(base64String) { 
    const padding = '='.repeat((4 - base64String.length % 4) % 4); 
    const base64 = (base64String + padding) 
     .replace(/\-/g, '+') 
     .replace(/_/g, '/'); 

    const rawData = window.atob(base64); 
    const outputArray = new Uint8Array(rawData.length); 

    for (let i = 0; i < rawData.length; ++i) { 
     outputArray[i] = rawData.charCodeAt(i); 
    } 
    return outputArray; 
    } 

तो आप इस तरह से अपनी सदस्यता वस्तु बनाने के लिए है:

registration.pushManager 
    .subscribe({ 
     userVisibleOnly: true, 
     applicationServerKey: urlBase64ToUint8Array(this._publicApplicationKey.publicKey), 
    }) 

मुख्य रूप से मैंने जो किया वह this tutorial का पालन करता था। मेरे पास this github repo में उस कामकाजी उदाहरण है। रीडमे फ़ाइल स्पेनिश में है, लेकिन मुझे लगता है कि यह आपकी मदद कर सकता है।

+0

मुझे ऐसा नहीं लगता! अगर यह समाधान था तो मैं कभी भी पुश अधिसूचना नहीं भेज सकता था। जैसा कि मैंने बताया है कि मैं लगभग 20 घंटे तक उपयोगकर्ता को भेज सकता हूं! उसके बाद ऐसा लगता है कि सदस्यता समाप्त हो गई है! – Alex

+0

इस कोड को पहले से हटाए जाने से पहले मैंने पहले ही अपनी चाबियाँ एन्कोड कर दी हैं। – Alex

2

मुझे लगता है कि उपयोगकर्ताओं को पुन: सदस्यता करके समस्या हल हो सकती है।

संबंधित मुद्दे