본문 바로가기
아이폰 개발/Swift

swift push node js apns 연동

by 인생여희 2021. 7. 30.

swift push + node js apns 연동

ios - appDelegate.swift


import UIKit
import RealmSwift


@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    
    let userId_G = UserPreferences.sharedInstance.getUserId() ?? ""
    
    var window: UIWindow?

    //MARK: 최초화면
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
       
        print("[!!]Realm DB 위치  =  \(Realm.Configuration.defaultConfiguration.fileURL!)")
        
        //MARK:푸시 토큰 권한 묻기
        registerForRemoteNotifications()


        let coordinator = SiginCoordinator()
        let navCon = coordinator.showFirstPage()
        
        window = UIWindow(frame: UIScreen.main.bounds)
        window?.rootViewController = navCon
        window?.makeKeyAndVisible()
        
        return true
    }


    
    
    
    //MARK:문제집 리스트 조회 api
    /// 문제집 리스트 조회 api
    public func loadQuestionsDatas(complete: @escaping (Bool)-> Void){
        
        /// 테이블뷰 데이터 배열 (문제집)
        var items = [QuestionVO]()
        
        HttpAdapter(method: .POST, service: .questionListByAppCode, param: ["code" : APP.CODE.rawValue, "userId" : userId_G]).request { data in
            
            if let result = data{
                let data = result["rows"] as? Array<[String:Any]>
                
                if let data = data{
                    for i in 0 ..< data.count {
    
                        let questionVo = QuestionVO()
                        let questionsData = questionVo.parser(data: data[i])
                        
                        if let data = questionsData {
                        
                            /// 문제집 이름 -> 초성 중성 종성으로 변환 후 저장
                            data.nameChoIndex = ChosungUtil.getUTF8StringCho(data.name)
                            data.nameChoJungJongIndex = ChosungUtil.getUTF8StringChoJungJong(data.name)
                            /// 문제집 설명 -> 초성 중성 종성으로 변환 후 저장
                            data.descChoIndex = ChosungUtil.getUTF8StringCho(data.desc)
                            data.descChoJungJongIndex = ChosungUtil.getUTF8StringChoJungJong(data.desc)
                            
                            //MARK: TableView 배열 삽입
                            items.append(data)
                        }
                    }//for - end

                }//data = data - end

                
                //MARK: 문제집 리스트 정보 앱디비에 저장
                DispatchQueue.main.async {
                    QuestionVO.insert(objects: items)
                }
                
                complete(true)
                
            }else{
                complete(false)
            }
            
        }//Api-call-end
    }
    
    //MARK: 푸시 토큰 권한
    /// 푸시 토큰 권한
    private func registerForRemoteNotifications() {
        // 1. 푸시 center (유저에게 권한 요청 용도)
        let center = UNUserNotificationCenter.current()
        
        // push처리에 대한 delegate - UNUserNotificationCenterDelegate
        center.delegate = self
        
        let options: UNAuthorizationOptions = [.alert, .sound, .badge]
        center.requestAuthorization(options: options) { (granted, error) in
            
            /// 승인 받았는지 여부 체크
            guard granted else {
                print("유저가 푸시 알림을 거부했습니다.")
                return
            }
            DispatchQueue.main.async {
                
                print("유저가 푸시 알림을 허용했습니다.")
                
                // 2. APNs에 디바이스 토큰 등록
                UIApplication.shared.registerForRemoteNotifications()
            }
        }
    }
    
}



extension AppDelegate: UNUserNotificationCenterDelegate {

    // 앱이 foreground상태 일 때, 알림이 온 경우 처리
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {

        // 푸시가 오면 alert, badge, sound표시를 하라는 의미
        completionHandler([.banner, .list])
    }

    /// push가 온 경우 처리
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

        // deep link처리 시 아래 url값 가지고 처리
        let pushData = response.notification.request.content.userInfo
        print("pushData = \(pushData)")


         let apnsDic = pushData["aps"] as? [String:String]
         let msgString = apnsDic?["alert"] ?? ""
         
         let payloadString = apnsDic?["payload"] ?? ""
         
         print("msgString = \(msgString)")
         print("payloadString = \(payloadString)")
         
        
        // if url.containts("receipt")...
    }
    
    
    //MARK: APNS로 부터 응답처리
    ///- 디바이스 토큰 등록 성공 시 실행되는 메서드
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        
        let deviceTokenString = deviceToken.map { String(format: "%02x", $0) }.joined()
        print("발급된 토큰 : \(deviceTokenString)")
    }
    
    ///- 디바이스 토큰 등록 실패 시 실행되는 메서드
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        
        print("토큰 등록 실패")
    }
}

 

node js

var express = require('express');
var router = express.Router();
var loger = require('../../config/logmodule.js');            //로그모듈
var path = require('path');
var apn = require('apn');
const logger = require('../../config/logmodule.js');
loger.info("메모리 로딩 시작. - admin.js");



/* send push */
router.get('/sendpush', function (req, res, next) {

  loger.debug("push 페이지 진입 ")

  let publicPath = path.join(__dirname, "../../public");

  loger.debug("p8 인증서 경로 :  " + publicPath + '/푸시인증서.p8')

  // Set up apn with the APNs Auth Key
  var apnProvider = new apn.Provider({
    token: {
      key: publicPath + '/푸시인증서.p8', 
      keyId: '', 
      teamId: '', 
    },
    production: false // 개발용
  });

  // 디바이스 토큰
  var deviceToken = '디바이스 토큰!!';

  // Prepare a new notification
  var notification = new apn.Notification();

  // 앱 번들아이디
  notification.topic = '';

  // Set expiration to 1 hour from now (in case device is offline)
  notification.expiry = Math.floor(Date.now() / 1000) + 3600;

  // 배지 표시
  //notification.badge = 3;
  // 사운드
  //notification.sound = 'ping.aiff';

  notification.alert = "\uD83D\uDCE7 \u2709 You have a new message";

  // Send any extra payload data with the notification which will be accessible to your app in didReceiveRemoteNotification
  notification.payload = {'id': '123'};

  // 실제로 푸시 발송하는 함수
  apnProvider.send(notification, deviceToken).then(function (result) {

    if (result.failed.length == 0) {
      console.log(result);
      loger.debug("푸시 발송 성공 : " + result.sent)
      
      res.json({
        result: 'success',
        tocken: '푸시 발송 성공'
      });
    } else {
      loger.debug("푸시 발송 실패 ")
      res.json({
        result: 'fail',
        tocken: '푸시 발송 실패'
      });
    }
  });

});


module.exports = router;
loger.info("메모리 로딩 완료. - push.js");

 

 

참고 소스

https://nicgoon.tistory.com/202

http://webs.co.kr/index.php?document_srl=3319441&mid=apple

https://runlife.tistory.c