문자메세지(SMS) 알림

SeonKyum·2021년 12월 22일
0

백엔드 개념

목록 보기
8/23

coolsms 가입 & 프로젝트 설정

  1. coolsms 사이트 가입 후 api key 설정

  2. api key 생성

  3. SDK 다운로드

  4. SDK 활용법

    • 다운로드받은 sdk를 압축해제 후 인텔리제이 file → open 으로 프로젝트를 연다.
    • lib 파일안의 .jar 들을 본인의 프로젝트에 implement 한다.
      • .jar 확인

      • 적용하고 싶은 프로젝트 파일안에 .jar가 들어갈 폴더를 생성 후 넣어준다.

      • File → Project Structure → modules → main → Dependencies 에 .jar 파일들 추가

      • build.gradle 에 dependency 경로를 추가해주고, 혹시 모르니 구버전 dependency 도 추가해주고 거북이를 눌러서 빌드해준다.

        //구버전
        implementation 'net.nurigo:javaSDK:2.2'
        //경로
        implementation fileTree(dir: 'library/sms',includes: ['*.jar'])

코드 설명

로직 타겟 설정

  1. 모임에 참가한 사람들에게 모임 시작 하루전에 알림 문자 전송
  2. 회원가입시 휴대폰 번호 인증
  3. 모임 참가/취소 버튼 클릭 시 알림 문자 전송 (보류)
  4. 모임 시작시 후기 작성 페이지 유도 알림 문자 전송
  5. 모임 시작시 모임장에게 출석체크 url 보내기

기본적인 문자메세지 틀 구현

  • 다운 받았던 SDK를 인텔리제이로 열어보면 여러가지 예시 코드들이 담겨있다.

  • 개인 메세지(2, 3, 5)와 단체 메세지(1, 4)를 혼용할 수 있는 예시를 주목하여 코드를 짰다.

  • 기본 sms 로직

    service / SmsService

    @Service
    @RequiredArgsConstructor
    public class SmsService {
    
        public void sendSms() {
            JsonObject params = new JsonObject();
            JsonArray messages = new JsonArray();
    
            JsonObject msg = new JsonObject();
            JsonArray toList = new JsonArray();
    
            toList.add("01099403102");
            msg.add("to", toList);
            msg.addProperty("from", "01099403102");
            msg.addProperty("text",
                    "안녕하세요 줍깅입니다. 오늘 참여하실[같이 줍깅해요!]모임의 모임날짜가 3일 남으셨습니다.");
            messages.add(msg);
    
            params.add("messages", messages);
    
            Call<GroupModel> api = APIInit.getAPI().sendMessages(APIInit.getHeaders(), params);
            api.enqueue(new Callback<GroupModel>() {
                @Override
                public void onResponse(Call<GroupModel> call, Response<GroupModel> response) {
                    // 성공 시 200이 출력됩니다.
                    if (response.isSuccessful()) {
                        System.out.println("statusCode : " + response.code());
                        GroupModel body = response.body();
                        System.out.println("groupId : " + body.getGroupId());
                        System.out.println("status: " + body.getStatus());
                        System.out.println("count: " + body.getCount().toString());
                    } else {
                        try {
                            System.out.println(response.errorBody().string());
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
    
                @Override
                public void onFailure(Call<GroupModel> call, Throwable throwable) {
                    throwable.printStackTrace();
                }
            });
        }
    
    }

    util / coolsms / GroupModel

    @Getter
    public class GroupModel {
        private ArrayList<JsonObject> log;
        private JsonObject agent;
        private JsonObject count;
        private String accountId;
        private String apiVersion;
        private String groupId;
        private String dateCreated;
        private String dateUpdated;
        private String _id;
        private String status;
    }

    util / coolsms / CoolsmsMsgV4 (Coolsms서버와의 통신)

    public interface CoolsmsMsgV4 {
    
        // 심플 메시지
        @POST("messages/v4/send")
        Call<GroupModel> sendMessage(@Header("Authorization") String auth,
                                       @Body Message message);
    
        // 여러건 발송
        @POST("messages/v4/send-many")
        Call<GroupModel> sendMessages(@Header("Authorization") String auth,
                                      @Body JsonObject messages);

    util / coolsms / config.ini (api key, api secret 이 담겨져있는 파일)

    [AUTH]
    api_key = {api_key 넣기}
    api_secret = {api_secret 넣기} 
    [SERVER]
    domain = api.coolsms.co.kr
    protocol = https
    prefix =

    util / coolsms / APIInit (헤더를 만들어서 요청하는 로직, 서버에로 보내는 로직 )

    public class APIInit {
    
        private static Retrofit retrofit;
        private static CoolsmsMsgV4 messageService;
    
        public static String getHeaders() {
            try {
    						//실험결과 절대경로만되고 상대경로는 되지않음
                Ini ini = new Ini(new File("C:\\Users\\user\\Desktop\\gits\\joopging\\src\\main\\java\\com\\project\\joopging\\util\\coolsms\\config.ini"));
                String apiKey = ini.get("AUTH","api_key");
                String apiSecret =ini.get("AUTH","api_secret");
                String salt = UUID.randomUUID().toString().replaceAll("-","");
                String date = ZonedDateTime.now(ZoneId.of("Asia/Seoul")).toString().split("\\[")[0];
    
                Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
                SecretKeySpec secret_key = new SecretKeySpec(apiSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
                sha256_HMAC.init(secret_key);
                String signature = new String(Hex.encodeHex(sha256_HMAC.doFinal((date + salt).getBytes(StandardCharsets.UTF_8))));
                return "HMAC-SHA256 ApiKey=" + apiKey + ", Date=" + date + ", salt=" + salt + ", signature=" + signature;
            } catch (InvalidKeyException | NoSuchAlgorithmException | IOException e) {
                e.printStackTrace();
            }
            return null;
        }
    
        public static CoolsmsMsgV4 getAPI() {
            if (messageService == null) {
                setRetrofit();
                messageService = retrofit.create(CoolsmsMsgV4.class);
            }
            return messageService;
        }
    
        public static void setRetrofit() {
            HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
    //        Request 시 로그가 필요하면 추가하세요.
    //        interceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);
    //        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
    
            String domain = "api.coolsms.co.kr";
            String protocol = "https";
            String prefix = "/";
    
            try {
    						//실험결과 절대경로만되고 상대경로는 되지않음
                Ini ini = new Ini(new File("C:\\Users\\user\\Desktop\\gits\\joopging\\src\\main\\java\\com\\project\\joopging\\util\\coolsms\\config.ini"));
                if (ini.get("SERVER", "domain") != null) domain = ini.get("SERVER", "domain");
                if (ini.get("SERVER", "protocol") != null) protocol = ini.get("SERVER", "protocol");
                if (ini.get("SERVER", "prefix") != null) prefix = ini.get("SERVER", "prefix");
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            OkHttpClient client = new OkHttpClient.Builder()
                    .addInterceptor(interceptor)
                    .build();
            retrofit = new Retrofit.Builder()
                    .baseUrl(protocol + "://" + domain + prefix)
                    .addConverterFactory(ScalarsConverterFactory.create())
                    .addConverterFactory(GsonConverterFactory.create())
                    .client(client)
                    .build();
        }
    
    }

1. 모임에 참가한 사람들에게 모임 시작 하루전에 알림 문자 전송

schedule / SmsSchedule 추가로직

//스케쥴러 매일 9시
    //러닝데이트 1일 전에 알럿문자메세지
    @Scheduled(cron = "0 0 9 * * *")
    @Transactional(readOnly = true)
    public void sendRunningDateAlertToCrew() {
        List<Post> postList = postRepository.findAll();
        JsonArray toList = new JsonArray();
        String nowPlusOneDay = getLocalDateTimeNowToStringDay(LocalDateTime.now().plusDays(1));
        for (Post post : postList) {
            String runningDate = getRunningDateToStringDay(post);
          if (nowPlusOneDay.equals(runningDate)) {
              List<Crew> crewList = post.getCrew();
              String postTitle = post.getTitle();
              String message = "안녕하세요 줍깅입니다. " +
                      "신청하신"+ " [" + postTitle + "] " +"모임의 모임날짜가 하루전입니다.";
              for (Crew crew : crewList) {
                  User user = crew.getUserJoin();
                  Long userId = user.getId();
                  User myUser = userRepository.findById(userId).orElseThrow(
                          NullPointerException::new
                  );
                  String userNumber = myUser.getNumber();
                  toList.add(userNumber);
              }
              sendSms(toList, message);
          }
        }
    }

2. 회원가입시 휴대폰 번호 인증

//휴대폰 번호 인증
    public CertificateNumberResponseDto certificatePhoneNumber(PhoneNumberRequestDto requestDto) {
        JsonArray toList = new JsonArray();
        String phoneNumber = requestDto.getPhoneNumber();
        toList.add(phoneNumber);

        Random random = new Random();
        String numStr = "";
        for(int i = 0; i < 4; i++) {
            String ran = Integer.toString(random.nextInt(10));
            numStr+=ran;
        }
        log.info("수신자 번호 :" + phoneNumber);
        log.info("인증번호 :" + numStr);
        String message = "안녕하세요 줍깅입니다. 인증번호는 [ " + numStr + " ] 입니다";
        sendSms(toList, message);
        CertificateNumberResponseDto responseDto = new CertificateNumberResponseDto();
        responseDto.setCertificationNumber(numStr);
        return responseDto;

    }

### 3. 모임 참가/취소 버튼 클릭 시 알림 문자 전송 (보류)

### 4. 모임 시작시 후기 작성 페이지 유도 알림 문자 전송

schedule / `SmsSchedule` 추가로직

```java
//스케쥴러 5분마다 체크
    //Crew 전체에게 후기 쓰고 설문조사 유도 알럿문자메세지
    @Scheduled(cron = "0 0/5 * * * *")
    @Transactional(readOnly = true)
    public void sendInduceReviewAlertToCrew() {
        System.out.println("스케쥴러 시작");
        List<Post> postList = postRepository.findAll();
        JsonArray toList = new JsonArray();
        String now = getLocalDateTimeNowToStringMinute(LocalDateTime.now());
        for (Post post : postList) {
            String runningDate = getRunningDateToStringMinute(post);
            if (now.equals(runningDate)) {
                List<Crew> crewList = post.getCrew();
                String postTitle = post.getTitle();
                String message = "안녕하세요 줍깅입니다. 이번" +" ["+ postTitle + "] " + "모임은 어떠셨나요?" +
                        "후기를 작성하여 다른 사용자에게 플로깅이 얼마나 좋은지 알려주세요!" +
                        "[이벤트] 이벤트 기간 중 설문조사를 작성하시면 소정의 기프티콘을 드려요! " +
                        "https://forms.gle/X3nQmmbHiRwmmWtZ8";
                for (Crew crew : crewList) {
                    User user = crew.getUserJoin();
                    Long userId = user.getId();
                    User myUser = userRepository.findById(userId).orElseThrow(
                            NullPointerException::new
                    );
                    String userNumber = myUser.getNumber();
                    toList.add(userNumber);
                }
                sendSms(toList,message);
            }
        }
    }

5. 모임 시작시 모임장에게 출석체크 url 보내기

schedule / SmsSchedule 추가로직

//스케쥴러 5분마다 체크
    //CrewHead 에게 출석체크 url 알럿문자메세지
    @Scheduled(cron ="0 0/5 * * * *")
    @Transactional(readOnly = true)
    public void sendAttendanceCheckAlertToCrewHead() {
        System.out.println("스케쥴러 시작");
        List<Post> postList = postRepository.findAll();
        JsonArray toList = new JsonArray();
        String now = getLocalDateTimeNowToStringMinute(LocalDateTime.now());
        for (Post post : postList) {
            String runningDate = getRunningDateToStringMinute(post);
            if (now.equals(runningDate)) {
                User user = post.getWriter();
                Long userId = user.getId();
                User myUser = userRepository.findById(userId).orElseThrow(
                        NullPointerException::new
                );
                String number = myUser.getNumber();
                String postTitle = post.getTitle();
                Long postId = post.getId();
                String message = "안녕하세요 줍깅입니다." +" ["+ postTitle +"] "+ "모임의 모임원들은" +
                        "다 모이셨나요? 출석체크를 해주세요!" +
                        "출석체크는 앞으로 유저간의 신뢰도를 측정하는데 도움이 됩니다!" +
                        "http://joopgging.link/meetingcheck/" + postId;
                toList.add(number);
                sendSms(toList,message);
            }

        }
    }
profile
차근차근,,

0개의 댓글