我尝试实施我在here找到的反馈服务代码。
这是我的代码:
private X509Certificate getServerCert(string certName)
{
var store = new X509Store(StoreLocation.LocalMachine);
try
{
store.Open(OpenFlags.ReadOnly);
var certs = store.Certificates.Find(X509FindType.FindBySubjectName, certName, false);
return certs.Count == 0 ? null : certs[0];
}
finally
{
store.Close();
}
}
public String CheckFeedbackService(string certaName)
{
System.Net.ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateServerCertificate);
KIREIP.Core.Manager.IphoneErrorLog errorLog = new KIREIP.Core.Manager.IphoneErrorLog();
// Create an empty collection of certs
X509Certificate2Collection certs = new X509Certificate2Collection();
// Add the Apple cert to our collection
certs.Add(getServerCert(certaName));
// Apple feedback server address
string apsHostF;
if (getServerCert(certaName).ToString().Contains("Production"))
apsHostF = "feedback.push.apple.com";
else
apsHostF = "feedback.sandbox.push.apple.com";
// Create a TCP socket connection to the Apple server on port 2196
TcpClient tcpClientF = new TcpClient(apsHostF, 2196);
//Set up
byte[] buffer = new byte[38];
int recd = 0;
DateTime minTimestamp = DateTime.Now.AddYears(-1);
string result = string.Empty;
// Create a new SSL stream over the connection
SslStream sslStreamF = new SslStream(tcpClientF.GetStream(), true, new RemoteCertificateValidationCallback(ValidateServerCertificate));
try
{
// Authenticate using the Apple cert
sslStreamF.AuthenticateAsClient(apsHostF, certs, SslProtocols.Default, false);
//TODO: Read in data and remove device tokens if any found.
errorLog.AddErrorLog("Stream Readable ::" + sslStreamF.CanRead);
//errorLog.AddErrorLog("Host Name ::" + hostName);
errorLog.AddErrorLog("Cert Name ::" + certs[0].FriendlyName);
if (sslStreamF != null)
{
errorLog.AddErrorLog("Connection Started");
//Get the first feedback
recd = sslStreamF.Read(buffer, 0, buffer.Length);
errorLog.AddErrorLog("Buffer length ::" + recd);
//Continue while we have results and are not disposing
while (recd > 0)
{
errorLog.AddErrorLog("Reading Started");
//Get our seconds since 1970 ?
byte[] bSeconds = new byte[4];
byte[] bDeviceToken = new byte[32];
Array.Copy(buffer, 0, bSeconds, 0, 4);
//Check endianness
if (BitConverter.IsLittleEndian)
Array.Reverse(bSeconds);
int tSeconds = BitConverter.ToInt32(bSeconds, 0);
//Add seconds since 1970 to that date, in UTC and then get it locally
var Timestamp = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(tSeconds).ToLocalTime();
//Now copy out the device token
Array.Copy(buffer, 6, bDeviceToken, 0, 32);
string deviceToken = BitConverter.ToString(bDeviceToken).Replace("-", "").ToLower().Trim();
//Make sure we have a good feedback tuple
if (deviceToken.Length == 64 && Timestamp > minTimestamp)
{
errorLog.AddErrorLog("Feedback " + deviceToken);
result = deviceToken;
errorLog.AddErrorLog(result);
}
//Clear array to reuse it
Array.Clear(buffer, 0, buffer.Length);
//Read the next feedback
recd = sslStreamF.Read(buffer, 0, buffer.Length);
}
errorLog.AddErrorLog("Reading Ended");
}
if (sslStreamF != null)
sslStreamF.Close();
if (tcpClientF != null)
tcpClientF.Close();
}
catch (AuthenticationException e)
{
errorLog.AddErrorLog("Authentication failed - closing the connection.");
sslStreamF.Close();
tcpClientF.Close();
return "NOAUTH";
}
finally
{
// The client stream will be closed with the sslStream
// because we specified this behavior when creating
// the sslStream.
sslStreamF.Close();
tcpClientF.Close();
}
return "";
}
每当我运行此代码时,我从getServerCert(certName)方法获取null值,因为这个空值我的进一步执行失败。
非常感谢任何帮助
答案 0 :(得分:0)
我使用JdSoft.Apns.Feedback.dll
我找到了here(或者您可以直接谷歌获取最新版本)。
使用此.dll
我已生成以下方法,包含2个代表
public string CheckFeedBack()
{
//Variables you may need to edit:
//---------------------------------
//Log.AddErrorLog("Start");
//True if you are using sandbox certificate, or false if using production
bool sandbox = Convert.ToBoolean(System.Configuration.ConfigurationManager.AppSettings["sandbox"].ToString());
//Put your PKCS12 .p12 or .pfx filename here.
// Assumes it is in the same directory as your app
string p12File = System.Configuration.ConfigurationManager.AppSettings["p12File"].ToString();
//This is the password that you protected your p12File
// If you did not use a password, set it as null or an empty string
string p12FilePassword = System.Configuration.ConfigurationManager.AppSettings["p12FilePassword"].ToString();
//Actual Code starts below:
//--------------------------------
//Get the filename assuming the file is in the same directory as this app
string p12Filename = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, p12File);
//errorLog.AddErrorLog(p12Filename);
//Create the feedback service consumer
FeedbackService service = new FeedbackService(sandbox, p12Filename, p12FilePassword);
//Wireup the events
service.Error += new FeedbackService.OnError(service_Error);
service.Feedback += new FeedbackService.OnFeedback(service_Feedback);
//Run it. This actually connects and receives the feedback
// the Feedback event will fire for each feedback object
// received from the server
service.Run();
Log.AddErrorLog("Done.");
Log.AddErrorLog("Cleaning up...");
//Clean up
service.Dispose();
return "Checked database table log..";
}
代表连接反馈和错误事件
static void service_Feedback(object sender, Feedback feedback)
{
Log.AddErrorLog(string.Format("Feedback - Timestamp: {0} - DeviceId: {1}", feedback.Timestamp, feedback.DeviceToken));
//DeviceToken retrive over here
}
static void service_Error(object sender, Exception ex)
{
Log.AddErrorLog(string.Format("Error: {0}", ex.Message));
//Error Message if failed
}