- 2016.02.02 / 김두민 : NotiFlag, MktFlag 설명 추가
- 2016.01.26 / 김두민 : 에티켓 시간 설정 추가
- 2015.10.08 / 김두민 : 마케팅 수신 동의 추가
- 2015.09.17 / 김두민 : iOS9 ATS내용 추가
- 2015.08.20 / 김두민 : Xcode7(iOS 9) 대응
- 2015.07.24 / 김두민 : 오탈자 수정, 잘못된 함수명 수정
- 2015.07.23 / 김두민 : 메시지 유형 추가
- 2015.07.17 / 김두민 : PMSCore.h 관련 정보 추가, 메시지 클릭 처리 추가
- 2015.04.03 / 김두민 : APNS 토큰 발급 오류 수정, 라이브러리 적용 방법 수정
- 2015.03.28 / 김두민 : 문서 포맷 변경
- 2015.03.17 / 김두민 : APNS 토큰 발급 요청부분 수정
- 2015.02.02 / 김두민 : API Specification 섹션을 별도 문서로 분리
- 2015.01.15 / 김두민 : step by step 섹션 추가
- 2015.01.14 / 김두민 : v3.0.3 패치내용 반영, 에러코드표 추가, 주요기능 섹션 추가
- 2015.01.13 / 김두민 : v3.0.2 패치내용 반영
- 2015.01.13 / 김두민 : 문서 포맷 수정 및 이미지 추가
- 2014.12.23 / 김두민 : v3.0.1 패치내용 반영
- 2014.12.23 / 김두민 : 초안작성
Build Architecture
iOS Version
의존프레임워크
PMS.framework를 App 프로젝트 폴더에 옮겨 넣는다
TARGET > Build Phases > Link Binary With Libraries에 Add Other… 을 선택 후 PMS.framework를 추가
TARGET > Build Phases > Link Binary With Libraries에 에서 PMS의 의존 프레임워크 4가지를 추가
Project > Apple LLVM 6.0 - Language - Modules의 Enable Modules (C and Objective-C) 값을 YES로 변경
******-Info.plist
파일에 AppKey와 ApiUrl설정
PMS를 사용하려는 클래스에서 #import <PMS/PMS.h>
한 후 사용
// APNS서버에 Push토큰 요청
if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerForRemoteNotifications)]) {
// Xcode5.x 이하에서 빌드 안됨
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
[[UIApplication sharedApplication] registerForRemoteNotifications];
if([UIApplication sharedApplication].currentUserNotificationSettings.types == UIUserNotificationTypeNone){
// 시스템 알림 설정 == OFF
}
} else {
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];
if([UIApplication sharedApplication].enabledRemoteNotificationTypes == UIRemoteNotificationTypeNone){
// 시스템 알림 설정 == OFF
}
}
-(void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)devToken
{
// [PMS deviceCert]는 setPushToken에서 자동으로 수행
[PMS setPushToken:devToken];
}
-(void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err
{
[PMS deviceCert];
}
[PMS setPushToken:devToken], [PMS deviceCert]의 통신결과를 수신하기 위해서 PMSDelegate 구현 (Optional이며, 결과를 수신하여 처리할 필요가 없을경우에는 구현하지 않아도 됨)
@interface AppDelegate : UIResponder <UIApplicationDelegate, PMSDelegate>
// PMS Delegate 설정
[PMS setDelegate:self];
#pragma mark - PMS Delegate implements
// 앱에서 푸시수신후 [PMS receivePush:tagString] 호출시 응답하는 delegate
-(void)pmsDidReceivePush:(PMSModelMessage *)resultModel Tag:(NSString *)tag
{
if(resultModel && [resultModel isSuccess]){
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:resultModel.pushTitle
message:resultModel.pushMsg
delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertView show];
}
}
// [PMS setPushToken:devToken] 호출시 응답하는 delegate
-(void)pmsSetPushTokenComplete:(PMSResult*)result
{
NSLog(@"pmsSetPushTokenComplete : %@", result);
}
// 클릭전송을 Batch로 수행한후 응답하는 delegate
-(void)pmsSendClickMsgComplete:(PMSResult *)result
{
NSLog(@"pmsSendClickMsgComplete : %@", result);
}
// 읽음처리를 Batch로 수행한후 응답하는 delegate
-(void)pmsSendReadMsgComplete:(PMSResult *)result
{
NSLog(@"pmsSendReadMsgComplete : %@", result);
}
[PMS setConfigWithNotiFlag:YES MsgFlag:NO MktFlag:YES CompleteBlock:^(PMSResult *result) {
// TODO Something
}];
// Local에 저장되어 있는 값으로 확인하는 경우
[PMS getNotiFlag]; // Push(정보성) 수신여부 확인
[PMS getMsgFlag]; // 메시지함 적재여부 확인
[PMS getMktFlag]; // 마케팅 수신 동의여부 확인 (NotiFlag의 영향 받지 않음)
// 서버상에 설정되어있는 값을 확인 (네트워크 요청이 발생하며 가급적 사용을 지양함)
[PMS getConfigFlagsWithCompleteBlockV2:^(PMSResult *result, BOOL notiFlag, BOOL msgFlag, BOOL mktFlag) {
// TODO Something
}];
// 22:30~09:00 으로 설정하는 경우
[PMS setEtqStartHour:22
EtqStartMin:30
EtqEndHour:09
EtqEndMin:00
CompleteBlock:nil];
PMS 로그인이란?
644e1dd7-2a7f-18fb-b8ed-ed78c3f92c2b
라는 단말을 사용하는 사용자는 Tester
이다일반 로그인
[PMS loginWithCustId:@"사용자아이디" CompleteBlock:^(PMSResult *result) {
if([result isSuccess]){
// TODO Something... on login Success
}else{
// TODO Something... on login Fail!!!
}
}];
DeviceCert를 이용한 로그인
[PMS deviceCertWithCustId:tfCustId.text UserData:dict CompleteBlock:^(PMSResult *result) {
if([result isSuccess]){
// TODO Something... on cert Success
}else{
// TODO Something... on cert Fail!!!
}
}];
메시지 유형
으로 Grouping 함// 네트워크 통신을 통해 그룹을 받아오는 경우
[PMS loadGrpListWithCompleteBlock:^(PMSResult *result, NSArray *groupArray) {
if([result isSuccess]){
// 받아온 그룹을 저장하고 테이블에 데이터 표시
mGroupData = [NSMutableArray arrayWithArray:groupArray];
// groupArray는 PMSModelMessageGroup[]
[mGroupTableView reloadData];
}else{
// TODO 그룹 로드 실패시
}
}];
// 네트워크 통신없이 Local DB에서 그룹을 받아오는 경우
mGroupData = [NSMutableArray arrayWithArray:[PMS loadGrpListWithCompleteBlock:nil]];
[mGroupTableView reloadData];
@interface MessageBoxViewController : UIViewController<UITableViewDelegate, UITableViewDataSource>
{
NSString *targetGrpCode; // 그룹핑하여 메시지를 가져올 경우
int deleteCount; // 삭제 기능을 사용할 경우에만
int page; // 현재 조회중인 페이지 저장
int totalCount; // 모든 메시지 개수 저장
}
- (void) loadNextPageData
{
if(mMsgData == nil){
// PMS에서 받아온 메시지를 저장할 NSMutableArray를 alloc
mMsgData = [NSMutableArray new];
}
if(page == 0){
// 페이지가 0일 경우는 새로고침이나 기타 동작으로 첫페이지부터 다시 불러오는 경우
[mMsgData removeAllObjects];
[mMsgTableView setContentOffset:CGPointZero animated:NO];
}
// 네트워크 요청하면서 받아올때
[PMS loadMsgListWithGrpCode:targetGrpCode
Page:++page
PerPage:perPage
CompleteBlock:^(PMSResult *result, NSArray *msgArray) {
if([result isSuccess]){
// 받아온 데이터를 add
// msgArray는 PMSModelMessage[]
[mMsgData addObjectsFromArray:msgArray];
dispatch_async(dispatch_get_main_queue(), ^{
[mMsgTableView reloadData];
});
// 그룹 newCount리셋 (새로받아온 메시지의 카운트를 0으로)
[PMS resetNewCountWithGrpCode:targetGrpCode];
// 메시지 개수 확인 (다음페이지 요청을 할 필요가 있는지 판단하기 위함)
totalCount = [PMS getMessageCountWithGrpCode:targetGrpCode];
}else{
// 실패시 -1 페이지
page--;
}
}];
}
// 섹션당 로우개수는 서버에서 받아온 메시지 데이터 길이
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (mMsgData) {
return [mMsgData count];
}else{
return 0;
}
}
// UITableView에 셀 표시
// 페이징은 구현방법에 따라 상이할 수 있음
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = @"MessageTableViewCell";
MessageTableViewCell *cell = (MessageTableViewCell *)[mMsgTableView dequeueReusableCellWithIdentifier: identifier];
if (!cell) {
cell = [[[NSBundle mainBundle] loadNibNamed:identifier owner:self options:nil] objectAtIndex:0];
}
PMSModelMessage *msg = [mMsgData objectAtIndex:[indexPath row]];
[cell renderingCellWithMsg:msg];
// 다음페이지 가져옴 (5개 아이템 남은경우)
if([indexPath row] >= mMsgData.count - 5
&& mMsgData.count+deleteCount < totalCount){
[self loadNextPageData];
}
return cell;
}
// 로우 선택시 상세보기 페이지로 이동
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
PMSModelMessage *msg = [mMsgData objectAtIndex:[indexPath row]];
[msg setReadYn:@"Y"];
MessageDetailViewController *msgDetailViewController = [[MessageDetailViewController alloc] initWithNibName:@"MessageDetailViewController" bundle:nil msg:msg];
[self.navigationController pushViewController:msgDetailViewController animated:YES];
}
메시지 삭제/복구는 실제로 삭제되지 않으며, 서버와 동기화 되지 않음
[PMS deleteMsgWithUserMsgId:currentMsg.userMsgId];
[PMS restoreMsgWithUserMsgId:currentMsg.userMsgId];
// Batch로 요청하는 경우
[PMS sendReadMsgEventWithMsgId:currentMsg.msgId];
// Direct로 요청하는 경우
[PMS sendReadMsgEventWithMsgId:currentMsg.msgId CompleteBlock:^(PMSResult *result) {
// TODO 읽음처리 요청 이후 동작
}];
// 클릭 링크발생시 PMS 링크인지 확인한 후 요청처리
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
if([PMS isPmsClickRequest:request]){
// PMS클릭 처리가 가능할 경우
NSURLRequest *innerRequest = [PMS clickMsgProcess:request];
[self.webView loadRequest:innerRequest];
return NO;
}else{
return YES;
}
}
// 수신한 리치 푸시의 HTML의 Anchor태그를 PMS에서 처리할 수 있는 링크주소로 변환
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
[PMS replaceAnchorTagForPMSClick:self.webView];
}
푸시에 의한 동작을 처리해야 하는 케이스는 다음 3가지가 존재
case1인 경우를 판별하는 방법
case2,3인 경우를 판별하는 방법
푸시수신후 [PMS receivePush:tagString:]을 호출하면, 해당 푸시 메시지의 상세 내용을 pmsDidReceivePush에서 반환해 준다.
앱 실행중일때 푸시 수신시 동작 샘플코드
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
[PMS receivePush:userInfo tagString:@"didReceive"];
}
if(launchOptions){
[PMS receivePush:launchOptions tagString:@"didFinish"];
}
-(void)pmsDidReceivePush:(PMSModelMessage *)resultModel Payload:(NSDictionary *)payload Tag:(NSString *)tag
{
if(resultModel && [resultModel isSuccess]){
// 성공적으로 메시지를 받아온 경우
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:resultModel.pushTitle message:resultModel.pushMsg delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertView show];
}else{
// 메시지를 받아오지 못한경우 돌려받은 Payload를 이용해서 팝업 출력
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"[Push message]" message:[[payload objectForKey:@"aps"] objectForKey:@"alert"] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertView show];
}
}
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
// 푸시 허용하지 않은경우
if([PMS isReadyForUse] && !notificationSettings.types){
// 설정값과 다를경우 PMS시스템에 팝업 허용하지 않은 사용자로 업데이트
if([PMS getNotiFlag]){
[PMS setConfigWithNotiFlag:NO MsgFlag:YES CompleteBlock:nil];
}
}
}
// iOS버전 분기
if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerForRemoteNotifications)]) {
if([UIApplication sharedApplication].currentUserNotificationSettings.types == UIUserNotificationTypeNone){
// 시스템 알림 설정 == OFF
}
} else {
if([UIApplication sharedApplication].enabledRemoteNotificationTypes == UIRemoteNotificationTypeNone){
// 시스템 알림 설정 == OFF
}
}
<!-- ATS 모두 허용 -->
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key><true/>
</dict>
<!-- ATS 특정 도메인만 허용 -->
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>amail.co.kr</key> <!-- 허용할 도메인 1 (고객사에 MsgApi 따라 서로 상이함) -->
<dict>
<key>NSThirdPartyExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
<key>pushpia.com</key> <!-- 허용할 도메인 n (PMS이외에 다른 도메인을 추가로 허용) -->
<dict>
<key>NSThirdPartyExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
DeviceCert
NewMsg
Message
MessageGroup
MessageCount
SetConfig
ReadMsg
ClickMsg
<A>
태그를 선택했을 경우 호출해주는 메소드 이며, 아직 iOS는 지원하지 않는다 Login
메시지 삭제
메시지 복구
Batch작업 강제 시작
PMSConfig.h
를 이용하여 PMS의 주요 설정값을 변경할 수 있으며, 설정하지 않을경우 기본값으로 적용됨// AppKey와 MsgApiUrl변경
// PMSConfig에서 다시 설정할 경우 plist에 선언한 값은 무시됨
[PMSConfig setApiUrl:@"http://apiUrl.com"];
[PMSConfig setAppKey:@"YourAppKey"];
// 서버 msgApi 버전설정 (특수한 경우에만 사용)
[PMSConfig setMsgApiVersionMajor:2 minor:0 patch:5];
// 네트워크 타임아웃 시간 설정
[PMSConfig setNetworkTimeout:10.0f];
// 메시지를 한번에 몇페이지씩 받아올 것인지 설정
[PMSConfig setPerPage:20];
// 네트워크 요청 재시도 횟수
[PMSConfig setReattemptCount:3];
// readMsg, clickMsg의 Batch timer interval설정
[PMSConfig setTimerInterval:10.0f];
// 암호화 사용여부설정 (특수한 경우에만 사용)
[PMSConfig cryptEnable:YES];
// PMSLog를 출력할 것인지의 설정 (오류 발생시 YES로 설정하여 원인파악)
[PMSConfig logEnable:YES];
// PMSApiLog를 출력할 것인지의 설정 (오류 발생시 YES로 설정하여 원인파악)
[PMSConfig apiLogEnable:YES];
// Msg를 LocalDB에 저장할 것인지에 대한 여부 결정 (특수한 경우에만 사용)
[PMSConfig useMsgDB:YES];
// PushToken을 UUID로 사용할 것인지에 대한 옵션
// YES로 설정할 경우 푸시허영하지 않음으로 APNS토큰이 발급되지 않은단말은 PMS에 등록되지 않음
[PMSConfig usePushTokenToUUID:NO];
// Sample Code
// 모두 전송할 필요 없이 PMS 서버에 저장하고자 하는 값만 전송
NSMutableDictionary* userData = [NSMutableDictionary new];
[userData setValue:@"Tester" forKey:@"custName"];
[userData setValue:@"19850101" forKey:@"birthday"];
[userData setValue:@"01012345678" forKey:@"phoneNumber"];
[userData setValue:@"loc 1" forKey:@"location1"];
[userData setValue:@"loc 2" forKey:@"location2"];
[userData setValue:@"M" forKey:@"gender"]; // M or F
[userData setValue:@"data1" forKey:@"data1"];
[userData setValue:@"data2" forKey:@"data2"];
[userData setValue:@"data3" forKey:@"data3"];
Code | 설명 |
---|---|
000 | 통신성공 |
100 | 파라미터 오류, 필수 파라미터 누락 |
101 | 파라미터 오류, 잘못된 파라미터 크기 |
102 | 파라미터 오류, 유효하지 않은 파라미터 |
103 | 복호화 오류 |
104 | JSON형식 오류 |
105 | 잘못된 세션(타임아웃 등) |
106 | 암호화 오류 |
109 | 사용할 수 없는 msgApi |
110 | 기타오류 (msgApi) |
120 | 기타오류 (확인되지 않음) |
130 | - |
510 | 유효하지 않은 앱키 |
Code | 설명 |
---|---|
700 | SDK 기타 오류, PMSResult의 msg 확인 필요 |
702 | UUID 생성 오류 |
720 | 링크 클릭 처리 오류 |
730 | 읽음 처리 오류 |
920 | 네트워크 타임아웃, MsgApi 주소 확인 필요 |