iOS 进阶开发— 原生APNS配置以及server实现(c++版本)

本文转自:http://blog.csdn.net/o_surface_o/article/details/9271631

关于iOS APNS的server provider 一直没有看到关于c++版本的,不过现在的各种第三方APNS已经很成熟了,比如百度的云推送SDK等等,这里简单总结一下如何实现iOS原生的APNS server provider.

第一步,生成证书,如何生成.p12证书这里就不细说了,如果不清楚的请查阅其他文档,或者评论里留言,如果问的多的话我再加上

  1. openssl pkcs12 -clcerts -nokeys -out cert.pem -in Certificate.p12   
  2. provide new password if asked.   
  3. openssl pkcs12 -nocerts -out key.pem -in Certificate.p12   
  4. provide new password if asked.   
  5. cat cert.pem key.unencrypted.pem > ck.pem  

测试版本要生成developer 证书,发布的要对应的生成发布版本的。

生成.pem证书之后,把pem证书放到你的server provider工程中去。

第二步:server provider实现(c++版本)

要实现server provider, 需要先编译安装openssl, 因为Apple 的APNS是基于openssl实现的。

先来看头文件实现

  1. /* 
  2.  * Auth The Croods 
  3.  */  
  4. #pragma once  
  5. #include   
  6. #include   
  7. #include   
  8. #include   
  9. #include   
  10. #include   
  11. #include   
  12. #include   
  13. #include   
  14.   
  15. // certificate  
  16. #define CERTFILE "./apns_dev.pem"  
  17. #define SSL_CTX_LOAD_VERIFY_LOCATIONS_FAILED  -1  
  18. #define BIO_DO_CONNECT_FAILED                 -2  
  19. #define SSL_GET_VERIFY_RESULT_FAILED          -3  
  20.   
  21. class APNS_Croods  
  22. {  
  23. private:  
  24.     SSL_CTX                *m_pctx;  
  25.     SSL                    *m_pssl;  
  26.     const SSL_METHOD       *m_pmeth;  
  27.     X509                   *m_pserver_cert;  
  28.     EVP_PKEY               *m_pkey;  
  29.     BIO *bio;  
  30.   
  31. public:  
  32.     APNS_Croods(void);  
  33.     ~APNS_Croods(void);  
  34.     int APNS_protal();  
  35.     void Reset();  
  36.     int pushmessage(const char *token, const char *payload);  
  37.     void token2bytes(const char *token, char *bytes);  
  38. };  
接下来看类实现:

  1. #include "APNS_Croods.h"  
  2. APNS_Croods::APNS_Croods(void)  
  3. {  
  4.     m_pctx            = NULL;  
  5.     m_pssl            = NULL;  
  6.     m_pmeth            = NULL;  
  7.     m_pserver_cert    = NULL;  
  8.     m_pkey            = NULL;  
  9.     bio                = NULL;  
  10. }  
  11.   
  12. APNS_Croods::APNS_Croods(void)  
  13. {  
  14.     Reset();  
  15. }  
  16.   
  17. int APNS_Croods::pushmessage(const char *token, const char *payload){  
  18.     char tokenBytes[32];  
  19.     char message[293];  
  20.     int msgLength;  
  21.       
  22.     token2bytes(token, tokenBytes);  
  23.       
  24.     unsigned char command = 0;  
  25.     size_t payloadLength = strlen(payload);  
  26.     char *pointer = message;  
  27.     unsigned short networkTokenLength = htons((u_short)32);  
  28.     unsigned short networkPayloadLength = htons((unsigned short)payloadLength);  
  29.     memcpy(pointer, &command, sizeof(unsigned char));  
  30.     pointer +=sizeof(unsigned char);     
  31.     memcpy(pointer, &networkTokenLength, sizeof(unsigned short));   
  32.     pointer += sizeof(unsigned short);  
  33.     memcpy(pointer, tokenBytes, 32);  
  34.     pointer += 32;  
  35.     memcpy(pointer, &networkPayloadLength, sizeof(unsigned short));  
  36.     pointer += sizeof(unsigned short);  
  37.     memcpy(pointer, payload, payloadLength);  
  38.     pointer += payloadLength;  
  39.     msgLength = (int)(pointer - message);  
  40.     int ret = SSL_write(m_pssl, message, msgLength);  
  41.   
  42.     return ret;  
  43. }  
  44.   
  45. int APNS_Croods::APNS_protal()  
  46. {  
  47.     //  
  48.     char token[] = "8da412ec d60b4a8d ea08a8f5 31f0e832 ba87c072 8920cf7d 2e436f40 c367205b";  
  49.     char payload[] = "{\"aps\":{\"alert\":\"Hello world!!! message from c++\",\"badge\":1}}";      
  50.     char host[] = "gateway.sandbox.push.apple.com:2195";  
  51.   
  52.     /* 
  53.     * Lets get nice error messages 
  54.     */  
  55.     SSL_load_error_strings();  
  56.     ERR_load_BIO_strings();  
  57.     OpenSSL_add_all_algorithms();  
  58.   
  59.     /* 
  60.     * Setup all the global SSL stuff 
  61.     */  
  62.     SSL_library_init();  
  63.   
  64.     m_pctx = SSL_CTX_new(SSLv23_client_method());  
  65.     if (SSL_CTX_use_certificate_chain_file(m_pctx, CERTFILE) != 1) {   
  66.         printf("Error loading certificate from file\n");    
  67.         return -1;  
  68.     }      
  69.     if (SSL_CTX_use_PrivateKey_file(m_pctx, CERTFILE, SSL_FILETYPE_PEM) != 1) {     
  70.         printf("Error loading private key from file\n");     
  71.         return -2;  
  72.     }  
  73.     bio = BIO_new_connect(host);  
  74.     if (!bio) {    
  75.         printf("Error creating connection BIO\n");   
  76.         return -3;  
  77.     }  
  78.     if (BIO_do_connect(bio) <= 0) {     
  79.         printf("Error connection to remote machine\n");    
  80.         return -4;  
  81.     }  
  82.     if (!(m_pssl = SSL_new(m_pctx))) {    
  83.         printf("Error creating an SSL contexxt\n");     
  84.         return -5;  
  85.     }  
  86.   
  87.     SSL_set_bio(m_pssl, bio, bio);  
  88.     int slRc = SSL_connect(m_pssl);  
  89.     if (slRc <= 0) {  
  90.         printf("Error connecting SSL object>>%d\n", slRc);  
  91.         return -6;  
  92.     }  
  93.     int ret = pushmessage(token,payload);  
  94.     
  95.     printf("push ret[%d]\n", ret);  
  96.     Reset();  
  97.     return 0;  
  98. }  
  99.   
  100. // change deviceToken string to binary bytes  
  101. void APNS_Croods::token2bytes(const char *token, char *bytes){  
  102.     int val;  
  103.     while (*token) {  
  104.         sscanf_s(token, "%2x", &val);  
  105.         *(bytes++) = (char)val;  
  106.         token += 2;  
  107.         while (*token == ' ') {  
  108.             // skip space  
  109.             ++token;  
  110.         }  
  111.     }  
  112. }  
  113.   
  114. void APNS_Croods::Reset()  
  115. {  
  116.     if(m_pssl)  
  117.     {  
  118.         SSL_shutdown(m_pssl);  
  119.         SSL_free(m_pssl);  
  120.         m_pssl = NULL;  
  121.     }  
  122.     if(m_pctx)  
  123.     {  
  124.         SSL_CTX_free(m_pctx);  
  125.         m_pctx = NULL;  
  126.     }  
  127. }  

注意:
  1. char host[] = "gateway.sandbox.push.apple.com:2195";  
这是apple APNS的developer 接口,如果是发布的话,要改成相应的发布接口,具体官网查询一下吧


下边接着来看,iOS客户端应用如何实现程序启动时读取通知内容:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    

  1. NSDictionary * remoteNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];  
  2.     NSLog(@">>>>remoteNotification>>%@>>>>>launchOptions>>>%@", remoteNotification,launchOptions);  
  3.     if (remoteNotification!=nil) {  
  4.         NSLog(@">>>>remoteNotification.userInfo>>%@", [[remoteNotification objectForKey:@"aps"]objectForKey:@"alert"]);  
  5.         NSString *alertBody = [[remoteNotification objectForKey:@"aps"]objectForKey:@"alert"];  
  6.     }  

}


简单罗列了一下,但具体思路应该大家都能看懂了,如有不明白的,请留言



你可能感兴趣的:(IOS)