2013-10-31 18 views
5

Chciałbym zaimplementować powiadomienia push dla mojej witryny (oczywiście tylko w zgodnej przeglądarce Safari 7). Przeczytałem dokumentację Apple i pomyślnie utworzyłem mój pakiet zawierający moje icon.iconset, moje certificate.p12, manifest.json i website.json. Teraz chciałbym poprosić użytkownika o pozwolenie podczas pierwszej wizyty na stronie. Jeśli na to pozwoli, powinienem wysłać paczkę. Wszystko jest całkiem jasne, ale nie wiem, jak iść dalej.Powiadomienia Safari Push

Jak utworzyć pakiet push z moich plików? Jak dokładnie to podpisać? Pakiet powinien być zawsze taki sam, aby móc go podpisać na moim macu i przesłać na mój serwer tylko jedną paczkę.

Jeśli masz doświadczenie w tej technologii, proszę dać mi znać :)

Odpowiedz

2

Jabłko zawiera plik php, który można wykorzystać do tworzenia pakietu Push tym podpisem. https://developer.apple.com/library/mac/documentation/NetworkingInternet/Conceptual/NotificationProgrammingGuideForWebsites/CompanionFile.zip

Można również użyć klejnotu push_package, https://github.com/SymmetricInfinity/push_package, który opracowaliśmy podczas wdrażania powiadomień push dla Safari dla zeropush.com. Więcej szczegółów jest dostępnych pod adresem https://zeropush.com/blog/implementing-safari-push-notifications-in-osx-mavericks.

3

Udało mi się utworzyć pakiet wypychania, aby uzyskać zgodę na wysyłanie powiadomień w Safari w Internecie za pomocą interfejsu REST API w języku Java. Mam również kroki, które zapewniają urzędnicy Apple na tych stronach.

Proszę wykonać poniższe czynności, aby utworzyć pakiet wypychania.

  1. Utwórz swój certyfikat P12 z powiadomień internetowych z konta Apple.

  2. Utwórz interfejs REST API przy użyciu protokołu HTTPS dla pakietu pushPackage, który zawiera ikony.iconset, certyfikat certificate.p12, manifest.json i witrynę website.json. Certyfikat p12 musi być certyfikatem powiadomień internetowych.

  3. Jak utworzyć pakiet push: - Proszę odnieść się poniżej kodu Java. Mam utworzyć pakiet push za pomocą serwletu java. które zapewniają 2 punkty końcowe usługi internetowej.

  4. v1/pushpackage/webpushID

  5. v1/log

serwletu, które przetwarzają żądania wysłania pakietu Push który przez safari metody Push powiadomień

SafariPushPakageAPI.java /* push Package REST API handler */

import java.io.IOException; 
import java.io.OutputStream; 
import java.util.ArrayList; 
import java.util.Map; 

import javax.servlet.ServletException; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 

import org.apache.commons.io.IOUtils; 
import org.apache.commons.lang.StringUtils; 

import com.safari.Packager; 

public class SafariPushPakageAPI extends HttpServlet{ 

    /** 
    * 
    */ 
    private static final long serialVersionUID = 1L; 
    public static String ServerPath = null; 
    private static final String REQUEST_PERMISSION = "/v1/pushPackages/YOUR_WEB_PUSH_ID"; 
    private static final String REQUEST_ERRORLOG = "/v1/log"; 

    @Override 
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
     doRequest(request, response); 
    } 
// /v1/pushPackages/webpushID 
// /v1/log 
    @Override 
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
     doRequest(request, response); 
    } 

    private void doRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
     System.out.println("===>> SAFARI PUSH NOTIFICATION REQUEST"); 
     String path = request.getPathInfo(); 
     System.out.println("PATH ===>> "+path); 
     if(path == null){ 
      doRequestPermission(request, response); 
     }else if (path.equalsIgnoreCase(REQUEST_PERMISSION)){ 
      doRequestPermission(request, response); 
     }else if (path.equalsIgnoreCase(REQUEST_ERRORLOG)){ 
      doRequestShowErrorLog(request, response); 
     }else{ 
      doRequestPermission(request, response); 
     } 
    } 

    private void doRequestPermission(HttpServletRequest request,HttpServletResponse response) { 
     try{ 
      System.out.println("INSIDE REQUEST PERMISSION ==>>>"); 
      System.out.println(IOUtils.toString(request.getReader())); 
      String authToken = StringUtils.isBlank(request.getParameter("token")) ? "UserTokenRT124DFGH" : StringUtils.trimToEmpty(request.getParameter("token")); 
      System.out.println("=>>>>>>>>>> USER TOKEN =>>>>>>>>>> "+authToken); 
      @SuppressWarnings("deprecation") 
      String packagePath =request.getRealPath("pushPackage.raw/icon.iconset/"); // LOCATION WHERE YOUR PUSH PACKAGE FOLDER CONTAIN LOGOS AND website.json file 
      response.setContentType("application/zip"); 
      response.setHeader("Content-Disposition", "attachment;filename=\"pushpackage.zip\""); 
      OutputStream out = response.getOutputStream(); 
      out.write(Packager.createPackageFile(authToken,packagePath)); 
      response.flushBuffer(); 
     }catch(IOException ioe){ 
      ioe.printStackTrace(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    private void doRequestShowErrorLog(HttpServletRequest request,HttpServletResponse response) { 
     try{ 
      System.out.println("ERROR LOG STARTED"); 
      System.out.println(IOUtils.toString(request.getReader())); 
      System.out.println("END"); 
     }catch(Exception e){ 
      e.printStackTrace(); 
     } 
    } 

} 

Packager.java

import java.io.DataInputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.IOException; 
import java.io.InputStream; 

import org.apache.commons.io.IOUtils; 
import org.json.JSONArray; 
import org.json.JSONObject; 

/** 
* 
* @author Ritesh 
*/ 
public class Packager { 

    final static String CERTIFICATE_PATH="PATH TO YOUR 12 CERTIFICATE"; 
    final static String CERTIFICATE_PASS="PASSWORD"; 

    static String getJSON(String authenticationToken) throws Exception { 
     JSONObject obj = new JSONObject(); 
     obj.put("websiteName", "WEB SITE NAME"); 
     obj.put("websitePushID", "WEB PUSH ID"); 
     obj.put("allowedDomains", new JSONArray()); 

     obj.getJSONArray("allowedDomains").put("https://TEST.EXAMPLE.net");//LIST OF DOMAINS ALLOW 

     obj.put("urlFormatString", "https://TEST.EXAMPLE.net/%@"); 
     obj.put("authenticationToken", authenticationToken); 
     obj.put("webServiceURL", "https://API.EXAMPLE.COM");//callback URL WITHOUT WEB SERVICE ENDPOINT NAME 

     return obj.toString(); 
    } 

    public static byte[] createPackageFile(String authenticationToken, String path) throws Exception { 

     System.out.println("packaging safari file with token: " + authenticationToken); 
     ZipHandler zip = new ZipHandler(); 
     File dir = new File(path); 

     for (File file : dir.listFiles()) {   
      InputStream is = new FileInputStream(file); 
      byte[] bytes = IOUtils.toByteArray(is); 
      zip.addFile("icon.iconset", file.getName(),bytes); 
     }  

     zip.addFile("", "website.json", getJSON(authenticationToken).getBytes()); 

     byte[] manifest = zip.manifest(); 
     zip.addFile("", "manifest.json", manifest); 

     zip.addFile("", "signature", sign(manifest)); 

     return zip.getBytes(); 

    } 

    static byte[] sign(byte bytesToSign[]) throws Exception { 
     return new PKCS7Signer().sign(CERTIFICATE_PATH,CERTIFICATE_PASS, bytesToSign); 
    } 

    /** 
    * Servlet handler , should listen on the callback URL (as in webServiceURL) 
    * @param requestPath 
    * @param req 
    * @param servletRequest 
    * @param servletResponse 
    * @throws Exception 
    */ 


    public static void main(String[] args) throws Exception { 
     Packager.createPackageFile("SafriNotifcation",""); 
    }    

} 

PKCS7Signer.java które utworzyć plik podpisu.

import java.io.FileInputStream; 
import java.security.KeyStore; 
import java.security.PrivateKey; 
import java.security.Security; 
import java.util.ArrayList; 
import java.util.Enumeration; 
import java.util.List; 

import org.bouncycastle.cert.X509CertificateHolder; 
import org.bouncycastle.cert.jcajce.JcaCertStore; 
import org.bouncycastle.cms.CMSProcessableByteArray; 
import org.bouncycastle.cms.CMSSignedData; 
import org.bouncycastle.cms.CMSSignedDataGenerator; 
import org.bouncycastle.cms.CMSTypedData; 
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder; 
import org.bouncycastle.jce.provider.BouncyCastleProvider; 
import org.bouncycastle.operator.ContentSigner; 
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; 
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; 
import org.bouncycastle.util.Store; 

public final class PKCS7Signer { 

    static { 
     try{ 
      Security.addProvider(new BouncyCastleProvider()); 
     }catch(Exception e){ 
      e.printStackTrace(); 
     } 
    } 

    private KeyStore getKeystore(String storeLocation, String storePasswd) throws Exception { 
     if (storeLocation == null) { 
      System.out.println("Could not find store file (.p12)"); 
      return null; 
     } 
     // First load the keystore object by providing the p12 file path 
     KeyStore clientStore = KeyStore.getInstance("PKCS12"); 
     // replace testPass with the p12 password/pin 
     clientStore.load(new FileInputStream(storeLocation), storePasswd.toCharArray()); 
     return clientStore; 
    } 

    private X509CertificateHolder getCert(KeyStore keystore, String alias) throws Exception { 
     java.security.cert.Certificate c = keystore.getCertificate(alias); 
     return new X509CertificateHolder(c.getEncoded()); 
    } 

    private PrivateKey getPrivateKey(KeyStore keystore, String alias, String storePasswd) throws Exception { 
     return (PrivateKey) keystore.getKey(alias, storePasswd.toCharArray()); 
    } 

    public byte[] sign(String storeLocation, String storePasswd, byte[] dataToSign) throws Exception { 
     KeyStore clientStore = getKeystore(storeLocation, storePasswd); 

     if (clientStore == null) { 
      return null; 
     } 
     Enumeration aliases = clientStore.aliases(); 
     String alias = ""; 
     while (aliases.hasMoreElements()) { 
      alias = (String) aliases.nextElement(); 
      if (clientStore.isKeyEntry(alias)) { 
       break; 
      } 
     } 

     CMSTypedData msg = new CMSProcessableByteArray(dataToSign); // Data to sign 

     X509CertificateHolder x509Certificate = getCert(clientStore, alias); 
     List certList = new ArrayList(); 
     certList.add(x509Certificate); // Adding the X509 Certificate 

     Store certs = new JcaCertStore(certList); 

     CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); 
     // Initializing the the BC's Signer 
     ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC").build(
       getPrivateKey(clientStore, alias, storePasswd)); 

     gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder() 
       .setProvider("BC").build()).build(sha1Signer, x509Certificate)); 
     // adding the certificate 
     gen.addCertificates(certs); 
     // Getting the signed data 
     CMSSignedData sigData = gen.generate(msg, false); 
     return sigData.getEncoded(); 
    } 
} 

pamiętać używane najnowszy bouncy słoiki zamek dla utworzyć plik podpisu bcprov-jdk15on-157.jar bcpkix-jdk15on-157.jar

  1. Wpisz swój JavaScript na stronie klienta.it zawiera prosty skrypt java, aby uzyskać uprawnienia.

///

// Na safari domenie var = "Your Web PUSH ID";

function safariIniti() { 

    var pResult = window.safari.pushNotification.permission(domain); 

    if(pResult.permission === 'default') { 
     //request permission 
     requestPermissions(); 
    } else if (pResult.permission === 'granted') { 
     console.log("Permission for " + domain + " is " + pResult.permission); 
     var token = pResult.deviceToken; 
     // Show subscription for debug 
     console.log('Subscription details:'+token); 
    } else if(pResult.permission === 'denied') { 
     console.log("Permission for " + domain + " is " + pResult.permission); 
    } 
} 

function getToken(){ 

    // always start with a letter (for DOM friendlyness) 
    var idstr=String.fromCharCode(Math.floor((Math.random()*25)+65)); 
    do {     
     // between numbers and characters (48 is 0 and 90 is Z (42-48 = 90) 
     var ascicode=Math.floor((Math.random()*42)+48); 
     if (ascicode<58 || ascicode>64){ 
      // exclude all chars between : (58) and @ (64) 
      idstr+=String.fromCharCode(ascicode);  
     }     
    } while (idstr.length<32); 

    return (idstr); 
} 


function requestPermissions() { 

    var tokenVal = getToken(); 
    window.safari.pushNotification.requestPermission('WEb service url without end points',domain,{token:tokenVal}, 
function(subscription) { 


     console.log(subscription.permission); 
     console.log("PERMISSION ====>> "+subscription.permission); 
     if(subscription.permission === 'granted') { 
      //TODO 
     } 
     else if(subscription.permission === 'denied') { 
      // TODO: 
     } 
    }); 

} 
Powiązane problemy