2022년 11월 16일 수요일

네이버 ncloud SENS (Simple & Easy Notification Service) java로 SMS 전송 개발

알바로 이것저것 하는 중에

네이버 ncloud SENS (Simple & Easy Notification Service) 로 

문자 전송 (추후엔 카톡까지 연동) 을 개발하게 됨.


구글링 하다보니.. spring에서 돌리는 소스를 발견


내가 개발 중인 환경은 jsp 이기에 이 소스를 컨버젼해서 쓰면 되겠군.. (아싸 득템)

이란 마음으로 시작...


아오 썩을..

계속 401 오류가 나온다.. (Authentication Failed)

네이버 쉑끼들한데 문의를 해보니 원론적인 답변만...

API 문서 : https://api.ncloud-docs.com/docs/ai-application-service-sens

네이버 쉑끼들한데 일단 한마디..


니들이 뭐가 그리 잘나서 우리는 고객의 코드를 리뷰 안해줌~~ 이딴 소릴 지껄이냐.. 

내가 니들 서비스 공짜로 쓰냐! 다 돈내고 쓰는거고.. 내가 몇백줄을 보낸 것도 아니고..

거기다가.. 니들이 만든 문서하고는.. 온갖 개폼은 다 잡아놓은 문서임.. 

알아먹을려면 알아먹어봐라 라는 중2병스러운 쓰레기를 만들어 놓고는 꼴깝 좀 떨지마라..


그리고.. 잘못된 소스를 올려놓은 어떤 블로그에게 한마디..

님의 소스에 수많은 개발자들이 오늘도 삽질을 합니다.

좀 잘 좀 확인하고 올립시다. 

내 뒤에 오는 사람들은 우리같은 고생은 안하는게 좋지 않겠습니까?


자 이제 진정하고.. 이제 소스 리뷰... 

JAVA 버전부터..

  1. import java.io.BufferedReader;
  2. import java.io.DataOutputStream;
  3. import java.io.InputStreamReader;
  4. import java.io.UnsupportedEncodingException;
  5. import java.net.HttpURLConnection;
  6. import java.net.URL;
  7. import java.security.InvalidKeyException;
  8. import java.security.NoSuchAlgorithmException;
  9. import java.util.Base64;
  10. import java.util.Base64.Encoder
  11. import org.json.JSONArray;
  12. import org.json.JSONObject
  13. import javax.crypto.Mac;
  14. import javax.crypto.spec.SecretKeySpec;
  15.  
  16. public class sendMessage {
  17.  
  18.   final static String ACCECSS_KEY = "네이버API인증키"// 네이버 클라우드 플랫폼 회원에게 발급되는 개인 인증키         // Access Key : https://www.ncloud.com/mypage/manage/info > 인증키 관리 > Access Key ID
  19.   final static String SMS_SERVICEID = "SMS서비스ID"// 프로젝트에 할당된 SMS 서비스 ID                     // service ID : https://console.ncloud.com/sens/project > Simple & ... > Project > 서비스 ID
  20.   final static String SMS_SECRECT_KEY = "네이버API인증키의 SECRET KEY"// MyPage의 API 인증키에서  secret key   // Service Key : https://www.ncloud.com/mypage/manage/info > 인증키 관리 >  secret key
  21.   final static String hostNameUrl = "https://sens.apigw.ntruss.com"// 호스트 URL
  22.   static String requestUrl = "/sms/v2/services/"// 요청 URL
  23.   final static String requestUrlType = "/messages"// 요청 URL
  24.   final static String method = "POST"// 요청 method
  25.  
  26.   public static void main(String[] args) throws ExceptionNoSuchAlgorithmException {
  27.     // TODO Auto-generated method stub  
  28.     sendSMS();
  29.   }
  30.  
  31.   // https://api.ncloud-docs.com/docs/common-ncpapi
  32.   private static String makeSignature(String url, String timestamp, String method,
  33.     String accessKey, String secretKey)
  34.     String space = " "// one space
  35.     String newLine = "\n"// new line
  36.  
  37.     String message = new StringBuilder()
  38.       .append(method)
  39.       .append(space)
  40.       .append(url)
  41.       .append(newLine)
  42.       .append(timestamp)
  43.       .append(newLine)
  44.       .append(accessKey)
  45.       .toString();
  46.  
  47.     SecretKeySpec signingKey;
  48.     String encodeBase64String;
  49.  
  50.     try {
  51.       signingKey = new SecretKeySpec(secretKey.getBytes("UTF-8")"HmacSHA256");
  52.       Mac mac = Mac.getInstance("HmacSHA256");
  53.       mac.init(signingKey);
  54.       byte[] rawHmac = mac.doFinal(message.getBytes("UTF-8"));
  55.       //encodeBase64String = Base64.getEncoder().encodeToString(rawHmac);
  56.       Encoder encoder = Base64.getEncoder();
  57.       encodeBase64String = encoder.encodeToString(rawHmac);
  58.     } catch (UnsupportedEncodingException e) {
  59.       // TODO Auto-generated catch block
  60.       encodeBase64String = e.toString();
  61.     }
  62.     return encodeBase64String;
  63.   }
  64.  
  65.   private static void sendSMS() {
  66.  
  67.     String text = "보내는 내용...";
  68.     String timestamp = Long.toString(System.currentTimeMillis())// current timestamp (epoch)
  69.  
  70.     requestUrl += SMS_SERVICEID + requestUrlType;
  71.     String apiUrl = hostNameUrl + requestUrl;
  72.     //System.out.println("APIURL ::: " + requestUrl);
  73.     // JSON 을 활용한 body data 생성
  74.     JSONObject bodyJson = new JSONObject();
  75.     JSONObject toJson = new JSONObject();
  76.     JSONArray toArr = new JSONArray();
  77.  
  78.     // toJson.put("subject",""); // Optional, messages.subject 개별 메시지 제목,
  79.     // LMS, MMS에서만 사용 가능
  80.     // toJson.put("content","sms test in spring 111"); // Optional,
  81.     // messages.content 개별 메시지 내용, SMS: 최대 80byte, LMS, MMS: 최대 2000byte
  82.     toJson.put("to""받는번호")// Mandatory(필수), messages.to 수신번호, -를 제외한 숫자만 입력 가능
  83.     toArr.put(toJson);
  84.  
  85.     bodyJson.put("type""LMS")// Madantory, 메시지 Type (SMS | LMS | MMS), (소문자 가능)
  86.     bodyJson.put("contentType""COMM")// Optional, 메시지 내용 Type (AD | COMM)
  87.     // * AD: 광고용, COMM: 일반용 (default: COMM) * 광고용 메시지 발송 시 불법 스팸 방지를 위한
  88.     // 정보통신망법 (제 50조)가 적용됩니다.
  89.     bodyJson.put("countryCode""82")// Optional, 국가 전화번호, (default: 82)
  90.     bodyJson.put("from""보내는번호")// Mandatory, 발신번호, 사전 등록된 발신번호만 사용 가능
  91.     // bodyJson.put("subject",""); // Optional, 기본 메시지 제목, LMS, MMS에서만 사용 가능
  92.     bodyJson.put("content", text)// Mandatory(필수), 기본  메시지 내용, SMS: 최대  80byte, LMS, MMS: 최대 2000byte
  93.     bodyJson.put("messages", toArr)// Mandatory(필수), 아래 항목들 참조
  94.     // (messages.XXX), 최대 1,000개
  95.  
  96.     /*
  97.         JSONArray fileArr = new JSONArray();
  98.         JSONObject fileJson = new JSONObject();
  99.         fileJson.put("name", "02.jpg");
  100.      
  101.         String text = "/CL001/02.jpg";
  102.           byte[] targetBytes = text.getBytes();
  103.      
  104.           Encoder encoder = Base64.getEncoder();
  105.           byte[] encodedBytes = encoder.encode(targetBytes);
  106.      
  107.         fileJson.put("body", new String(encodedBytes));
  108.         fileArr.put(fileJson);
  109.      
  110.         bodyJson.put("files", fileArr);
  111.         */
  112.     // String body = bodyJson.toJSONString();
  113.     String body = bodyJson.toString();
  114.  
  115.     System.out.println(body);
  116.  
  117.     try {
  118.       URL url = new URL(apiUrl);
  119.  
  120.       HttpURLConnection con = (HttpURLConnection) url.openConnection();
  121.       con.setUseCaches(false);
  122.       con.setDoOutput(true);
  123.       con.setDoInput(true);
  124.       con.setRequestProperty("content-type""application/json");
  125.       con.setRequestProperty("x-ncp-apigw-timestamp", timestamp);
  126.       con.setRequestProperty("x-ncp-iam-access-key", ACCECSS_KEY);
  127.       con.setRequestProperty("x-ncp-apigw-signature-v2", makeSignature(requestUrl, timestamp, method, ACCECSS_KEY, SMS_SECRECT_KEY));
  128.       con.setRequestMethod(method);
  129.       con.setDoOutput(true);
  130.       DataOutputStream wr = new DataOutputStream(con.getOutputStream());
  131.  
  132.       wr.write(body.getBytes());
  133.       wr.flush();
  134.       wr.close();
  135.  
  136.       int responseCode = con.getResponseCode();
  137.       BufferedReader br;
  138.  
  139.       if (responseCode == 202) { // 정상 호출
  140.         br = new BufferedReader(new InputStreamReader(
  141.           con.getInputStream()));
  142.       } else { // 에러 발생
  143.         br = new BufferedReader(new InputStreamReader(
  144.           con.getErrorStream()));
  145.       }
  146.  
  147.       String inputLine;
  148.       StringBuffer response = new StringBuffer();
  149.       while ((inputLine = br.readLine()) != null) {
  150.         response.append(inputLine);
  151.       }
  152.       br.close();
  153.  
  154.       System.out.println("===============RESPOSE===============");
  155.       System.out.println(response.toString());
  156.  
  157.     } catch (Exception e) {
  158.       System.out.println(e);
  159.     }
  160.   }
  161. }

소스의 원본은 인터넷에서 굴러다니는 거 줒어옴..(냠냠.. 줍줍)

문제가 뭐였냐면... SMS_SECRECT_KEY 이게 문제였음.. 

원본의 주석에는 SMS SERVICE의 SECRECT KEY를 넣으라고 써 있는데.. 

계속 인증 오류가 나서.. 혹시나 하는 마음에 ncloud API의 SECRECT KEY를 넣으니 바로 됨.


이 문제로 하루 날린거 생각하면.. 아 진짜... 열받음..

그리고 원래는 MMS로 개발하려 했으나.. 

네이버 놈들의 부실한 설명으로 이미지를 어떻게 첨부하라는 건지 

도대체 알아먹을 수가 없겠음.. (아니면 내가 돌대가리 이거나..)

하여간 그래서 LMS로 전환해서 링크 넣는 식으로 처리해 버림..

(그래도 혹시 나중에 알면 내용 추가할려고 주석으로 흔적만 남겨 놓음)


여기서 끗???!!! 이 아니라.. 난 너무 친절한 놈이라.. JSP 버전도 준비했지! 

의외로 JAVA 의 동생뻘이면서 약간씩 다른게 있어서리.. 

초보자들에게 삽질하지 말라고... (난 천사~~)


그건 다음 포스트에!! 두둥!!! (분량 늘리기냐!!!)



댓글 없음:

댓글 쓰기

BE Band (비밴드) - 2024년 03월 02일 잠실새내 락앤롤욱스 공연

나의 10~20대를 보낸 잠실에서의 공연.. 오랜만에 가보니.. 여기가.. 마눌님과 자주 가던 영화관이었는데... 여긴 뭐가 있었는데... 란 추억도 떠올리며 기분좋게 감.​ 공연장은 좀 협소한 편이었고, 인천의 쥐똥나무 보다는 약간 크고... 인천 ...