我正在尝试使用 Codeigniter 向 Safari 实现 Web 推送通知,我正在关注 Apple Guide
我创建了一个库来创建基于此 connorlacombe 的推送包github项目。
这是我的图书馆:
<?php if ( ! defined('BASEPATH')) exit("No direct script access allowed");class Apple_utils {
var $certificate_path;
var $certificate_password;
var $dir;
var $raw_files = array(
"icon.iconset/icon_16x16.png",
"icon.iconset/icon_16x16@2x.png",
"icon.iconset/icon_32x32.png",
"icon.iconset/icon_32x32@2x.png",
"icon.iconset/icon_128x128.png",
"icon.iconset/icon_128x128@2x.png",
"website.json"
);
public function __construct($config = array())
{
if (count($config) != 0){
$this->initialize($config);
}
log_message("debug", "Apple Class Initialized");
}
public function initialize($config = array())
{
if (empty($config["certificate_path"]) || empty($config["certificate_password"]) || empty($config["dir"])) return FALSE;
$this->certificate_path = $config["certificate_path"];
$this->certificate_password = $config["certificate_password"];
$this->dir = $config["dir"];
return $this;
}
// Creates the push package, and returns the path to the archive.
public function create_push_package($id)
{
list($usec, $sec) = explode(" ", microtime());
$now = ((float)$usec + (float)$sec);
//DELETING OLD DIR
$this->_delete_old_files($this->dir . "tmp/", $now);
$package_dir = $this->dir . "tmp/" . $now;
if (!mkdir($package_dir)) return FALSE;
@chmod($package_dir, 0755);
$this->_copy_raw_push_package_files($package_dir, $id);
if (!$this->_create_manifest($package_dir)) return FALSE;
if (!$this->_create_signature($package_dir)) return FALSE;
$package_path = $this->_package_raw_data($package_dir);
return $package_path;
}
private function _copy_raw_push_package_files($package_dir, $id)
{
mkdir($package_dir . "/icon.iconset");
foreach ($this->raw_files as $raw_file) {
copy($this->dir . "pushPackage/" . $raw_file, $package_dir . "/" . $raw_file);
if ($raw_file == "website.json") {
$wjson = file_get_contents($package_dir . "/". $raw_file);
unlink($package_dir . "/". $raw_file);
$ff = fopen($package_dir . "/". $raw_file, "x");
fwrite($ff, str_replace(array("{BASE_URL}", "{AUTHTOKEN}"), array(rtrim(base_url(), "/"), "authenticationToken_".$id), $wjson));
fclose($ff);
}
}
}
private function _create_manifest($package_dir)
{
// Obtain SHA1 hashes of all the files in the push package
$manifest_data = array();
foreach ($this->raw_files as $raw_file) {
$manifest_data[$raw_file] = sha1(file_get_contents($package_dir . "/" . $raw_file));
}
file_put_contents($package_dir . "/manifest.json", json_encode( (object)$manifest_data ));
return TRUE;
}
private function _create_signature($package_dir)
{
// Load the push notification certificate
$pkcs12 = file_get_contents($this->certificate_path);
$certs = array();
if(!openssl_pkcs12_read($pkcs12, $certs, $this->certificate_password)){
return FALSE;
}
$signature_path = $package_dir . "/signature";
// Sign the manifest.json file with the private key from the certificate
$cert_data = openssl_x509_read($certs["cert"]);
$private_key = openssl_pkey_get_private($certs["pkey"], $this->certificate_password);
openssl_pkcs7_sign($package_dir . "/manifest.json", $signature_path, $cert_data, $private_key, array(), PKCS7_BINARY | PKCS7_DETACHED);
// Convert the signature from PEM to DER
$signature_pem = file_get_contents($signature_path);
$matches = array();
if (!preg_match("~Content-Disposition:[^\n]+\s*?([A-Za-z0-9+=/\r\n]+)\s*?-----~", $signature_pem, $matches)){
return FALSE;
}
$signature_der = base64_decode($matches[1]);
file_put_contents($signature_path, $signature_der);
return TRUE;
}
private function _package_raw_data($package_dir)
{
$CI = &get_instance();
$CI->load->library("zip");
$raw_files = $this->raw_files;
$raw_files[] = "manifest.json";
$raw_files[] = "signature";
foreach ($raw_files as $raw_file) {
$CI->zip->add_data($raw_file, file_get_contents($package_dir . "/" .$raw_file));
}
ob_end_clean(); //I HAVE TO PUT THIS HERE BECAUSE IF NOT THE ZIP CAN NOT BE OPENED
$CI->zip->download( "Website.pushpackage.zip" );
}
function _delete_old_files($dir, $now)
{
$expiration = 300; //seconds
$current_dir = @opendir($dir);
while ($filename = @readdir($current_dir)){
if ($filename != "." && $filename != ".." && $filename != "index.html"){
$name = str_replace(".zip", "", $filename);
if (($name + $expiration) < $now) $this->_delete_file($this->dir . "tmp/" . $filename);
}
}
@closedir($current_dir);
}
function _delete_file($file)
{
@chmod($file, 0755);
if (is_dir($file)){
$dir = @opendir($file);
while ($filename = @readdir($dir)){
if ($filename != "." && $filename != ".."){
$this->_delete_file($file . "/" . $filename);
}
}
@closedir($dir);
@rmdir($file);
}else{
@unlink($file);
}
}}
图书馆工作,创建一个 .zip,带有 website.json,签名等,直到昨天工作完美,然后不再工作,当我检查日志时总是说“推送包的签名验证失败”并且我已经创建了不止一次证书,但仍然是同样的错误。
请帮忙。
最佳答案
openssl_pkcs7_sign("$package_dir/manifest.json", $signature_path, $cert_data, $private_key, array(), PKCS7_BINARY | PKCS7_DETACHED,"/path/to/certificate/AppleWWDRCA.pem");
要创建 AppleWWDRCA.pem,您需要:
1 - 下载 AppleWWDRCA.cer
2 - 执行以下命令:
openssl x509 -inform der -in AppleWWDRCA.cer -out AppleWWDRCA.pem
关于php - 苹果官网推送: Signature verification of push package failed, 但是苹果证书没问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35430205/
为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返
我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“
当我刚刚运行middleman时服务,all.css编译得很好,只包含对+box-shadow(none)的调用:/*line1,/home/yang/asdf/source/stylesheets/content.css.sass*/div{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}但是当我构建网站时,我得到了这个Sass/Compass错误:$middlemanbuildSlim::EmbeddedEngineisdeprecated,itiscalledSlim::EmbeddedinSlim2.0
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。我来自C、php和bash背景,很容易学习,因为它们都有相同的C结构,我可以将其与我已经知道的联系起来。然后2年前我学了Python并且学得很好,Python对我来说比Ruby更容易学。然后从去年开始,我一直在尝试学习Ruby,然后是Rails,我承认,直到现在我还是学不会,讽刺的是那些打着简单易学的烙印,但是对于我这样一个老练的程序员来说,我只是无法将它
我正在尝试将我更新的gem推送到rubygems.com并得到以下结果。~/dev/V2/V2GPTI(master)$gembuildv2gpti.gemspecSuccessfullybuiltRubyGemName:v2gptiVersion:0.2File:v2gpti-0.2-universal-darwin-13.gem~/dev/V2/V2GPTI(master)$gempushv2gpti.gemspecERROR:Whileexecutinggem...(Gem::Package::FormatError)packagemetadataismissinginv2g
我们正在开发一个需要推送通知的WP8应用程序。为了测试它,我们使用CURL命令行运行推送通知POST请求,确保它实际连接,使用客户端SSL证书进行身份验证并发送正确的数据。我们确实知道,当我们收到对设备的推送时,这项工作是有效的。这是我们一直用于测试目的的CURL命令:curl--certclient_cert.pem-v-H"Content-Type:text/xml"-H"X-WindowsPhone-Target:Toast"-H"X-NotificationClass:2"-XPOST-d"MytitleMysubtitle"https://db3.notify.live.ne
我知道我们可以做到:sidekiq_optionsqueue:"Foo"但在这种情况下,Worker只分配给一个队列:“Foo”。我需要在特定队列中分配作业(而不是worker)。使用Resque很容易:Resque.enqueue_to(queue_name,my_job)另外,为了并发问题,我需要限制每个队列的Worker数量为1。我该怎么做? 最佳答案 您可能会使用https://github.com/brainopia/sidekiq-limit_fetch然后:Sidekiq::Client.push({'class'=>
如何生成指向javascript文件的绝对链接。我想应该有类似下面的东西(不幸的是它似乎不可用):javascript_url'main'#->'http://localhost:3000/javascripts/main.js'代替:javascript_path'main'#->'/javascripts/main.js'我需要绝对URL,因为该javascript文件将用于书签。另外我需要相同的css文件。谢谢,德米特里。 最佳答案 javascript和css文件的绝对URL现在在Rails4中可用ActionView::H
我今天遇到了同样的问题,有一个建议:在您的命令前添加bundleexec可能会解决此问题。前置bundleexec没有帮助(我已经这样做了)。springstop和springrestart没有帮助。我需要做的:bundleupdatespring这对我有用。在之前的gemlock文件中使用spring版本是否有更好的解决方案? 最佳答案 我删除gemfile.lock并运行bundle通常会清除一切。否则只需从Gemfile中删除gem"spring"并运行bundle 关于ruby-
我正在使用带有Pow、Ruby、Rails和一堆有用的gem的Mac。每当我尝试打开我的应用程序时,我最近都会遇到此错误。Bundler::RubyVersionMismatch:您的Ruby版本为1.9.3,但您的Gemfile指定为2.0.0我明白这个错误,但我找不到为什么它没有在这里使用正确的版本。一些有用的信息:堆栈跟踪Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0~/.rvm/gems/ruby-2.0.0-p247/gems/bundler-1.3.5/lib/