iOS 進階開發— 原生APNS配置以及server實現(c++版本)
阿新 • • 發佈:2019-02-20
關於iOS APNS的server provider 一直沒有看到關於c++版本的,不過現在的各種第三方APNS已經很成熟了,比如百度的雲推送SDK等等,這裡簡單總結一下如何實現iOS原生的APNS server provider.
第一步,生成證書,如何生成.p12證書這裡就不細說了,如果不清楚的請查閱其他文件,或者評論裡留言,如果問的多的話我再加上
openssl pkcs12 -clcerts -nokeys -out cert.pem -in Certificate.p12 provide new password if asked. openssl pkcs12 -nocerts -out key.pem -in Certificate.p12 provide new password if asked. cat cert.pem key.unencrypted.pem > ck.pem
測試版本要生成developer 證書,釋出的要對應的生成釋出版本的。
生成.pem證書之後,把pem證書放到你的server provider工程中去。
第二步:server provider實現(c++版本)
要實現server provider, 需要先編譯安裝openssl, 因為Apple 的APNS是基於openssl實現的。
先來看標頭檔案實現
接下來看類實現:/* * Auth The Croods */ #pragma once #include <stdio.h> #include <tchar.h> #include <stdlib.h> #include <winsock.h> #include <openssl/ssl.h> #include <openssl/rand.h> #include <openssl/bio.h> #include <openssl/err.h> #include <openssl/x509.h> // certificate #define CERTFILE "./apns_dev.pem" #define SSL_CTX_LOAD_VERIFY_LOCATIONS_FAILED -1 #define BIO_DO_CONNECT_FAILED -2 #define SSL_GET_VERIFY_RESULT_FAILED -3 class APNS_Croods { private: SSL_CTX *m_pctx; SSL *m_pssl; const SSL_METHOD *m_pmeth; X509 *m_pserver_cert; EVP_PKEY *m_pkey; BIO *bio; public: APNS_Croods(void); ~APNS_Croods(void); int APNS_protal(); void Reset(); int pushmessage(const char *token, const char *payload); void token2bytes(const char *token, char *bytes); };
#include "APNS_Croods.h" APNS_Croods::APNS_Croods(void) { m_pctx = NULL; m_pssl = NULL; m_pmeth = NULL; m_pserver_cert = NULL; m_pkey = NULL; bio = NULL; } APNS_Croods::APNS_Croods(void) { Reset(); } int APNS_Croods::pushmessage(const char *token, const char *payload){ char tokenBytes[32]; char message[293]; int msgLength; token2bytes(token, tokenBytes); unsigned char command = 0; size_t payloadLength = strlen(payload); char *pointer = message; unsigned short networkTokenLength = htons((u_short)32); unsigned short networkPayloadLength = htons((unsigned short)payloadLength); memcpy(pointer, &command, sizeof(unsigned char)); pointer +=sizeof(unsigned char); memcpy(pointer, &networkTokenLength, sizeof(unsigned short)); pointer += sizeof(unsigned short); memcpy(pointer, tokenBytes, 32); pointer += 32; memcpy(pointer, &networkPayloadLength, sizeof(unsigned short)); pointer += sizeof(unsigned short); memcpy(pointer, payload, payloadLength); pointer += payloadLength; msgLength = (int)(pointer - message); int ret = SSL_write(m_pssl, message, msgLength); return ret; } int APNS_Croods::APNS_protal() { // char token[] = "8da412ec d60b4a8d ea08a8f5 31f0e832 ba87c072 8920cf7d 2e436f40 c367205b"; char payload[] = "{\"aps\":{\"alert\":\"Hello world!!! message from c++\",\"badge\":1}}"; char host[] = "gateway.sandbox.push.apple.com:2195"; /* * Lets get nice error messages */ SSL_load_error_strings(); ERR_load_BIO_strings(); OpenSSL_add_all_algorithms(); /* * Setup all the global SSL stuff */ SSL_library_init(); m_pctx = SSL_CTX_new(SSLv23_client_method()); if (SSL_CTX_use_certificate_chain_file(m_pctx, CERTFILE) != 1) { printf("Error loading certificate from file\n"); return -1; } if (SSL_CTX_use_PrivateKey_file(m_pctx, CERTFILE, SSL_FILETYPE_PEM) != 1) { printf("Error loading private key from file\n"); return -2; } bio = BIO_new_connect(host); if (!bio) { printf("Error creating connection BIO\n"); return -3; } if (BIO_do_connect(bio) <= 0) { printf("Error connection to remote machine\n"); return -4; } if (!(m_pssl = SSL_new(m_pctx))) { printf("Error creating an SSL contexxt\n"); return -5; } SSL_set_bio(m_pssl, bio, bio); int slRc = SSL_connect(m_pssl); if (slRc <= 0) { printf("Error connecting SSL object>>%d\n", slRc); return -6; } int ret = pushmessage(token,payload); printf("push ret[%d]\n", ret); Reset(); return 0; } // change deviceToken string to binary bytes void APNS_Croods::token2bytes(const char *token, char *bytes){ int val; while (*token) { sscanf_s(token, "%2x", &val); *(bytes++) = (char)val; token += 2; while (*token == ' ') { // skip space ++token; } } } void APNS_Croods::Reset() { if(m_pssl) { SSL_shutdown(m_pssl); SSL_free(m_pssl); m_pssl = NULL; } if(m_pctx) { SSL_CTX_free(m_pctx); m_pctx = NULL; } }
注意:
char host[] = "gateway.sandbox.push.apple.com:2195";
這是apple APNS的developer 介面,如果是釋出的話,要改成相應的釋出介面,具體官網查詢一下吧
下邊接著來看,iOS客戶端應用如何實現程式啟動時讀取通知內容:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSDictionary * remoteNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
NSLog(@">>>>remoteNotification>>%@>>>>>launchOptions>>>%@", remoteNotification,launchOptions);
if (remoteNotification!=nil) {
NSLog(@">>>>remoteNotification.userInfo>>%@", [[remoteNotification objectForKey:@"aps"]objectForKey:@"alert"]);
NSString *alertBody = [[remoteNotification objectForKey:@"aps"]objectForKey:@"alert"];
}
}
簡單羅列了一下,但具體思路應該大家都能看懂了,如有不明白的,請留言