From 90cb35c23c921bb001d25cc00085887341949fd6 Mon Sep 17 00:00:00 2001 From: Sejin Park <95167215+sejineer@users.noreply.github.com> Date: Tue, 5 Mar 2024 20:21:55 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=95=8C=EB=A6=BC=ED=86=A1=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84=20/=20=EC=98=88=EC=95=BD?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=20=EC=95=8C=EB=A6=BC=ED=86=A1=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9=20(#284)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/dto/request/NaverCloudSmsReq.java | 2 +- .../ExperienceGiftServiceImpl.java | 2 +- .../repository/ExperienceGiftRepository.java | 6 + .../ReservationManipulationService.java | 2 +- .../ReservationManipulationServiceImpl.java | 16 +- .../reservation/domain/Reservation.java | 10 +- .../dto/request/OwnerReservationCreate.java | 3 +- .../dto/response/ReservationResponse.java | 84 +++++----- .../presentation/ReservationController.java | 2 +- .../domain/shopowner/domain/ShopOwner.java | 8 +- .../infrastructure/sms/NaverSmsClient.java | 143 ++++++++++++++++-- .../infrastructure/sms/dto/AlimTalkReq.java | 22 +++ .../sms}/dto/MessageMapping.java | 2 +- 13 files changed, 216 insertions(+), 86 deletions(-) create mode 100644 src/main/java/com/shallwe/global/infrastructure/sms/dto/AlimTalkReq.java rename src/main/java/com/shallwe/{domain/auth => global/infrastructure/sms}/dto/MessageMapping.java (83%) diff --git a/src/main/java/com/shallwe/domain/auth/dto/request/NaverCloudSmsReq.java b/src/main/java/com/shallwe/domain/auth/dto/request/NaverCloudSmsReq.java index 98b91a07..edc856bf 100644 --- a/src/main/java/com/shallwe/domain/auth/dto/request/NaverCloudSmsReq.java +++ b/src/main/java/com/shallwe/domain/auth/dto/request/NaverCloudSmsReq.java @@ -1,6 +1,6 @@ package com.shallwe.domain.auth.dto.request; -import com.shallwe.domain.auth.dto.MessageMapping; +import com.shallwe.global.infrastructure.sms.dto.MessageMapping; import lombok.Builder; import lombok.Data; diff --git a/src/main/java/com/shallwe/domain/experiencegift/application/ExperienceGiftServiceImpl.java b/src/main/java/com/shallwe/domain/experiencegift/application/ExperienceGiftServiceImpl.java index 5c8178a7..1d90aebe 100644 --- a/src/main/java/com/shallwe/domain/experiencegift/application/ExperienceGiftServiceImpl.java +++ b/src/main/java/com/shallwe/domain/experiencegift/application/ExperienceGiftServiceImpl.java @@ -28,8 +28,8 @@ import java.util.List; import java.util.stream.Collectors; -@RequiredArgsConstructor @Service +@RequiredArgsConstructor @Transactional(readOnly = true) public class ExperienceGiftServiceImpl implements ExperienceGiftService { diff --git a/src/main/java/com/shallwe/domain/experiencegift/domain/repository/ExperienceGiftRepository.java b/src/main/java/com/shallwe/domain/experiencegift/domain/repository/ExperienceGiftRepository.java index 89f4e7bf..6c2cf611 100644 --- a/src/main/java/com/shallwe/domain/experiencegift/domain/repository/ExperienceGiftRepository.java +++ b/src/main/java/com/shallwe/domain/experiencegift/domain/repository/ExperienceGiftRepository.java @@ -3,6 +3,7 @@ import com.shallwe.domain.common.Status; import com.shallwe.domain.experiencegift.domain.ExperienceGift; import com.shallwe.domain.shopowner.domain.ShopOwner; +import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @@ -13,7 +14,12 @@ public interface ExperienceGiftRepository extends JpaRepository, ExperienceGiftQuerydslRepository{ List findByTitleContainsAndStatus(String title,Status status); + List findByShopOwnerIdAndStatus(Long id, Status status); Optional findByIdAndShopOwner(Long experienceGiftId, ShopOwner shopOwner); + + @EntityGraph(attributePaths = {"shopOwner"}) + Optional findExperienceGiftById(Long id); + } diff --git a/src/main/java/com/shallwe/domain/reservation/application/ReservationManipulationService.java b/src/main/java/com/shallwe/domain/reservation/application/ReservationManipulationService.java index a950758b..d8fb9220 100644 --- a/src/main/java/com/shallwe/domain/reservation/application/ReservationManipulationService.java +++ b/src/main/java/com/shallwe/domain/reservation/application/ReservationManipulationService.java @@ -12,7 +12,7 @@ public interface ReservationManipulationService { List addOwnerReservation(OwnerReservationCreate ownerReservationCreate, UserPrincipal userPrincipal); - ReservationResponse addUserReservation(UserReservationCreate reservationRequest, UserPrincipal userPrincipal); + ReservationResponse addUserReservation(UserReservationCreate reservationRequest, UserPrincipal userPrincipal) throws Exception; ReservationResponse updateReservation(UpdateReservationReq updateReq, UserPrincipal userPrincipal); DeleteReservationRes deleteReservation(Long id); diff --git a/src/main/java/com/shallwe/domain/reservation/application/ReservationManipulationServiceImpl.java b/src/main/java/com/shallwe/domain/reservation/application/ReservationManipulationServiceImpl.java index d52d1245..d9ffea48 100644 --- a/src/main/java/com/shallwe/domain/reservation/application/ReservationManipulationServiceImpl.java +++ b/src/main/java/com/shallwe/domain/reservation/application/ReservationManipulationServiceImpl.java @@ -17,9 +17,6 @@ import com.shallwe.domain.reservation.exception.InvalidReservationException; import com.shallwe.domain.reservation.exception.InvalidSenderException; import com.shallwe.domain.reservation.exception.InvalidReceiverException; -import com.shallwe.domain.shopowner.domain.ShopOwner; -import com.shallwe.domain.shopowner.domain.repository.ShopOwnerRepository; -import com.shallwe.domain.shopowner.exception.InvalidShopOwnerException; import com.shallwe.domain.user.domain.User; import com.shallwe.domain.user.domain.repository.UserRepository; import com.shallwe.global.config.security.token.UserPrincipal; @@ -27,6 +24,7 @@ import java.util.List; import java.util.stream.Collectors; +import com.shallwe.global.infrastructure.sms.NaverSmsClient; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -38,18 +36,15 @@ public class ReservationManipulationServiceImpl implements ReservationManipulati private final ReservationRepository reservationRepository; private final ExperienceGiftRepository experienceGiftRepository; - private final ShopOwnerRepository shopOwnerRepository; private final UserRepository userRepository; + private final NaverSmsClient naverSmsClient; @Transactional public List addOwnerReservation(OwnerReservationCreate ownerReservationCreate, UserPrincipal userPrincipal) { ExperienceGift experienceGift = experienceGiftRepository.findById(ownerReservationCreate.getExperienceGiftId()) .orElseThrow(ExperienceGiftNotFoundException::new); - ShopOwner owner = shopOwnerRepository.findById(userPrincipal.getId()) - .orElseThrow(InvalidShopOwnerException::new); - - List reservations = OwnerReservationCreate.toEntityForOwner(ownerReservationCreate, experienceGift, owner); + List reservations = OwnerReservationCreate.toEntityForOwner(ownerReservationCreate, experienceGift); return reservations.stream() .map(reservationRepository::save) .map(ReservationResponse::toDtoOwner) @@ -57,14 +52,14 @@ public List addOwnerReservation(OwnerReservationCreate owne } @Transactional - public ReservationResponse addUserReservation(UserReservationCreate reservationRequest, UserPrincipal userPrincipal) { + public ReservationResponse addUserReservation(UserReservationCreate reservationRequest, UserPrincipal userPrincipal) throws Exception { User sender = userRepository.findById(userPrincipal.getId()) .orElseThrow(InvalidSenderException::new); User receiver = userRepository.findByPhoneNumberAndStatus(reservationRequest.getPhoneNumber(), Status.ACTIVE) .orElseThrow(InvalidReceiverException::new); - ExperienceGift experienceGift = experienceGiftRepository.findById(reservationRequest.getExperienceGiftId()) + ExperienceGift experienceGift = experienceGiftRepository.findExperienceGiftById(reservationRequest.getExperienceGiftId()) .orElseThrow(ExperienceGiftNotFoundException::new); Reservation reservation = reservationRepository.findByDateAndTimeAndExperienceGift( @@ -74,6 +69,7 @@ public ReservationResponse addUserReservation(UserReservationCreate reservationR if (reservation.getReservationStatus().equals(WAITING)) { reservation.updateStatus(ReservationStatus.BOOKED); reservation.updateUserReservationRequest(reservationRequest, sender, receiver); + naverSmsClient.sendReservationApply(sender, receiver, experienceGift, reservation); experienceGift.addReservationCount(); } else { throw new InvalidReservationException(); diff --git a/src/main/java/com/shallwe/domain/reservation/domain/Reservation.java b/src/main/java/com/shallwe/domain/reservation/domain/Reservation.java index caaeb53f..972d2f18 100644 --- a/src/main/java/com/shallwe/domain/reservation/domain/Reservation.java +++ b/src/main/java/com/shallwe/domain/reservation/domain/Reservation.java @@ -37,12 +37,6 @@ public class Reservation extends BaseEntity { @Schema(description = "선물 ID") private ExperienceGift experienceGift; - @ManyToOne - @JoinColumn(name = "owner_id", nullable = false) - @Schema(description = "사장ID") - private ShopOwner owner; - - @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "sender_id") @Schema(description = "보내는이 ID") @@ -82,9 +76,8 @@ public class Reservation extends BaseEntity { private List memoryPhotos = new ArrayList<>(); @Builder - public Reservation(ExperienceGift experienceGift, ShopOwner owner, LocalDate date, LocalTime time, ReservationStatus reservationStatus) { + public Reservation(ExperienceGift experienceGift, LocalDate date, LocalTime time, ReservationStatus reservationStatus) { this.experienceGift = experienceGift; - this.owner = owner; this.date = date; this.time = time; this.reservationStatus = reservationStatus; @@ -107,4 +100,5 @@ public void updateUserReservationRequest(UserReservationCreate reservationReques public void updateStatus(ReservationStatus status) { this.reservationStatus = status; } + } diff --git a/src/main/java/com/shallwe/domain/reservation/dto/request/OwnerReservationCreate.java b/src/main/java/com/shallwe/domain/reservation/dto/request/OwnerReservationCreate.java index e59243e1..f738a78c 100644 --- a/src/main/java/com/shallwe/domain/reservation/dto/request/OwnerReservationCreate.java +++ b/src/main/java/com/shallwe/domain/reservation/dto/request/OwnerReservationCreate.java @@ -29,7 +29,7 @@ public class OwnerReservationCreate { private Map> dateTimeMap; public static List toEntityForOwner(OwnerReservationCreate ownerReservationCreate, - ExperienceGift experienceGift, ShopOwner owner) { + ExperienceGift experienceGift) { List reservations = new ArrayList<>(); for (Map.Entry> entry : ownerReservationCreate.getDateTimeMap() @@ -42,7 +42,6 @@ public static List toEntityForOwner(OwnerReservationCreate ownerRes .experienceGift(experienceGift) .date(date) .time(time) - .owner(owner) .reservationStatus(WAITING) .build(); reservations.add(toEntity); diff --git a/src/main/java/com/shallwe/domain/reservation/dto/response/ReservationResponse.java b/src/main/java/com/shallwe/domain/reservation/dto/response/ReservationResponse.java index c653b0c4..11be9629 100644 --- a/src/main/java/com/shallwe/domain/reservation/dto/response/ReservationResponse.java +++ b/src/main/java/com/shallwe/domain/reservation/dto/response/ReservationResponse.java @@ -6,6 +6,7 @@ import com.shallwe.global.utils.AwsS3ImageUrlUtil; import java.util.Optional; + import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -16,51 +17,48 @@ @Builder public class ReservationResponse { - private Long id; - private Long senderId; - private Long ownerId; - private String sender; - private Long persons; - private String date; - private String time; - private Long experienceGiftId; - private String receiver; - private String phoneNumber; - private String invitationImageURL; - private String invitationComment; - private ReservationStatus reservationStatus; + private Long id; + private Long senderId; + private String sender; + private Long persons; + private String date; + private String time; + private Long experienceGiftId; + private String receiver; + private String phoneNumber; + private String invitationImageURL; + private String invitationComment; + private ReservationStatus reservationStatus; - public static ReservationResponse toDtoUser(Reservation reservation) { - ReservationResponseBuilder builder = ReservationResponse.builder() - .id(reservation.getId()) - .experienceGiftId(reservation.getExperienceGift().getId()) - .senderId(Optional.ofNullable(reservation.getSender()).map(User::getId).orElse(null)) - .ownerId(reservation.getOwner().getId()) - .sender(Optional.ofNullable(reservation.getSender()).map(User::getName).orElse(null)) - .persons(Optional.ofNullable(reservation.getPersons()).orElse(null)) - .date(reservation.getDate().toString()) - .time(reservation.getTime().toString()) - .phoneNumber(Optional.ofNullable(reservation.getPhoneNumber()).orElse(null)) - .receiver(Optional.ofNullable(reservation.getReceiver()).map(User::getName).orElse(null)) - .invitationImageURL( - Optional.ofNullable(reservation.getInvitationImg()).map(AwsS3ImageUrlUtil::toUrl) - .orElse(null)) - .invitationComment(Optional.ofNullable(reservation.getInvitationComment()).orElse(null)) - .reservationStatus(reservation.getReservationStatus()); + public static ReservationResponse toDtoUser(Reservation reservation) { + ReservationResponseBuilder builder = ReservationResponse.builder() + .id(reservation.getId()) + .experienceGiftId(reservation.getExperienceGift().getId()) + .senderId(Optional.ofNullable(reservation.getSender()).map(User::getId).orElse(null)) + .sender(Optional.ofNullable(reservation.getSender()).map(User::getName).orElse(null)) + .persons(Optional.ofNullable(reservation.getPersons()).orElse(null)) + .date(reservation.getDate().toString()) + .time(reservation.getTime().toString()) + .phoneNumber(Optional.ofNullable(reservation.getPhoneNumber()).orElse(null)) + .receiver(Optional.ofNullable(reservation.getReceiver()).map(User::getName).orElse(null)) + .invitationImageURL( + Optional.ofNullable(reservation.getInvitationImg()).map(AwsS3ImageUrlUtil::toUrl) + .orElse(null)) + .invitationComment(Optional.ofNullable(reservation.getInvitationComment()).orElse(null)) + .reservationStatus(reservation.getReservationStatus()); - return builder.build(); - } + return builder.build(); + } - public static ReservationResponse toDtoOwner(Reservation reservation) { - ReservationResponseBuilder builder = ReservationResponse.builder() - .id(reservation.getId()) - .experienceGiftId(reservation.getExperienceGift().getId()) - .ownerId(reservation.getOwner().getId()) - .date(reservation.getDate().toString()) - .time(reservation.getTime().toString()) - .reservationStatus(reservation.getReservationStatus()); + public static ReservationResponse toDtoOwner(Reservation reservation) { + ReservationResponseBuilder builder = ReservationResponse.builder() + .id(reservation.getId()) + .experienceGiftId(reservation.getExperienceGift().getId()) + .date(reservation.getDate().toString()) + .time(reservation.getTime().toString()) + .reservationStatus(reservation.getReservationStatus()); - return builder.build(); - } + return builder.build(); + } -} +} \ No newline at end of file diff --git a/src/main/java/com/shallwe/domain/reservation/presentation/ReservationController.java b/src/main/java/com/shallwe/domain/reservation/presentation/ReservationController.java index b7d099f5..5a3e172e 100644 --- a/src/main/java/com/shallwe/domain/reservation/presentation/ReservationController.java +++ b/src/main/java/com/shallwe/domain/reservation/presentation/ReservationController.java @@ -126,7 +126,7 @@ public ResponseCustom> getCurrentGiftReservation( public ResponseCustom createUserReservation( @Parameter(description = "예약 요청을 확인해주세요.", required = true) @RequestBody UserReservationCreate reservationRequest, @Parameter(description = "AccessToken 을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal - ) { + ) throws Exception { return ResponseCustom.CREATED( reservationManipulationService.addUserReservation(reservationRequest, userPrincipal)); } diff --git a/src/main/java/com/shallwe/domain/shopowner/domain/ShopOwner.java b/src/main/java/com/shallwe/domain/shopowner/domain/ShopOwner.java index dc014878..9ac19c57 100644 --- a/src/main/java/com/shallwe/domain/shopowner/domain/ShopOwner.java +++ b/src/main/java/com/shallwe/domain/shopowner/domain/ShopOwner.java @@ -40,9 +40,6 @@ public class ShopOwner extends BaseEntity { @Column(name = "bankbook") private String bankbook; - @OneToMany(mappedBy = "owner", fetch = FetchType.LAZY) - private List reservationList; - public void changePassword(String password) { this.password = password; } @@ -60,7 +57,7 @@ public void updateBankbook(String bankbook) { } @Builder - public ShopOwner(String name, String phoneNumber, String password, Boolean marketingConsent, String identification, String businessRegistration, String bankbook, List reservationList) { + public ShopOwner(String name, String phoneNumber, String password, Boolean marketingConsent, String identification, String businessRegistration, String bankbook) { this.name = name; this.phoneNumber = phoneNumber; this.password = password; @@ -68,7 +65,6 @@ public ShopOwner(String name, String phoneNumber, String password, Boolean marke this.identification = identification; this.businessRegistration = businessRegistration; this.bankbook = bankbook; - this.reservationList = reservationList; } -} +} \ No newline at end of file diff --git a/src/main/java/com/shallwe/global/infrastructure/sms/NaverSmsClient.java b/src/main/java/com/shallwe/global/infrastructure/sms/NaverSmsClient.java index b8902bcb..9d97c6b3 100644 --- a/src/main/java/com/shallwe/global/infrastructure/sms/NaverSmsClient.java +++ b/src/main/java/com/shallwe/global/infrastructure/sms/NaverSmsClient.java @@ -3,9 +3,13 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.shallwe.domain.auth.domain.VerificationCode; import com.shallwe.domain.auth.domain.repository.VerificationCodeRepository; -import com.shallwe.domain.auth.dto.MessageMapping; +import com.shallwe.domain.experiencegift.domain.ExperienceGift; +import com.shallwe.domain.reservation.domain.Reservation; +import com.shallwe.domain.user.domain.User; +import com.shallwe.global.infrastructure.sms.dto.MessageMapping; import com.shallwe.domain.auth.dto.request.NaverCloudSmsReq; import com.shallwe.domain.auth.dto.request.ValidVerificationCodeReq; +import com.shallwe.global.infrastructure.sms.dto.AlimTalkReq; import com.shallwe.global.infrastructure.sms.exception.InvalidPhoneNumberException; import com.shallwe.global.infrastructure.sms.exception.InvalidVerificationCodeException; import com.shallwe.global.infrastructure.sms.exception.TimeOutException; @@ -22,19 +26,20 @@ import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; +import java.text.NumberFormat; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Base64; -import java.util.List; -import java.util.Random; +import java.util.*; @Service @RequiredArgsConstructor @Transactional(readOnly = true) public class NaverSmsClient implements SmsClient { - @Value("${sms.naver-cloud.service-id}") - private String SERVICE_ID; + @Value("${sms.naver-cloud.sms-service-id}") + private String SMS_SERVICE_ID; + + @Value("${sms.naver-cloud.biztalk-service-id}") + private String BIZTALK_SERVICE_ID; @Value("${sms.naver-cloud.access-key}") private String ACCESS_KEY; @@ -51,7 +56,8 @@ public class NaverSmsClient implements SmsClient { @Transactional public SmsResponseDto send(String receivePhoneNumber) throws Exception { String timestamp = String.valueOf(System.currentTimeMillis()); - String signature = makeSignature(timestamp); + String url = "/sms/v2/services/" + SMS_SERVICE_ID + "/messages"; + String signature = makeSignature(timestamp, url); String code = generateRandomCode(); @@ -87,7 +93,7 @@ public SmsResponseDto send(String receivePhoneNumber) throws Exception { .baseUrl("https://sens.apigw.ntruss.com/sms/v2/services") .build(); - return restClient.post().uri("/" + SERVICE_ID + "/messages") + return restClient.post().uri("/" + SMS_SERVICE_ID + "/messages") .contentType(MediaType.APPLICATION_JSON) .header("x-ncp-apigw-timestamp", timestamp) .header("x-ncp-iam-access-key", ACCESS_KEY) @@ -97,6 +103,120 @@ public SmsResponseDto send(String receivePhoneNumber) throws Exception { .body(SmsResponseDto.class); } + public SmsResponseDto sendReservationApply(User sender, User receiver, ExperienceGift experienceGift, Reservation reservation) throws Exception { + String timestamp = String.valueOf(System.currentTimeMillis()); + String url = "/alimtalk/v2/services/" + BIZTALK_SERVICE_ID + "/messages"; + String signature = makeSignature(timestamp, url); + + RestClient restClient = RestClient.builder() + .requestFactory(new HttpComponentsClientHttpRequestFactory()) + .baseUrl("https://sens.apigw.ntruss.com/alimtalk/v2") + .defaultHeaders(header -> { + header.set("Content-Type", "application/json"); + header.set("x-ncp-apigw-timestamp", timestamp); + header.set("x-ncp-iam-access-key", ACCESS_KEY); + header.set("x-ncp-apigw-signature-v2", signature); + }) + .build(); + + NumberFormat format = NumberFormat.getNumberInstance(); + String price = format.format(experienceGift.getPrice()); + String account = experienceGift.getShopOwner().getBankbook(); + String date = reservation.getDate().toString(); + String time = reservation.getTime().toString(); + String receiveUserName = receiver.getName(); + String productName = experienceGift.getTitle(); + String persons = reservation.getPersons().toString() + "명"; + + List messages = new ArrayList<>(); + messages.add(MessageMapping.builder() + .to(receiver.getPhoneNumber()) + .content("[셸위]\n" + + "예약이 접수되었습니다\n" + + "아래 계좌로 입금이 확인되면 예약확정과 함께 초대장이 발송됩니다\n" + + "\n" + + "\uD83D\uDCCC 금액: " + price + "원\n" + + "입금계좌: " + account + "\n" + + "\n" + + "예약날짜: " + date + "\n" + + "예약시간: " + time + "\n" + + "수취인: " + receiveUserName + "\n" + + "상품명: " + productName +"\n" + + "옵션: " + persons) + .build()); + + AlimTalkReq alimTalkReq = AlimTalkReq.builder() + .plusFriendId("@shallwee") + .templateCode("reservationApply") + .messages(messages) + .build(); + + ObjectMapper objectMapper = new ObjectMapper(); + String body = objectMapper.writeValueAsString(alimTalkReq); + + return restClient.post() + .uri("/services/" + BIZTALK_SERVICE_ID + "/messages") + .body(body) + .retrieve() + .body(SmsResponseDto.class); + } + + public SmsResponseDto sendInvitation(final User sender, final User receiver, final ExperienceGift experienceGift, + final Reservation reservation) throws Exception { + String timestamp = String.valueOf(System.currentTimeMillis()); + String url = "/alimtalk/v2/services/" + BIZTALK_SERVICE_ID + "/messages"; + String signature = makeSignature(timestamp, url); + + RestClient restClient = RestClient.builder() + .requestFactory(new HttpComponentsClientHttpRequestFactory()) + .baseUrl("https://sens.apigw.ntruss.com/alimtalk/v2") + .defaultHeaders(header -> { + header.set("Content-Type", "application/json"); + header.set("x-ncp-apigw-timestamp", timestamp); + header.set("x-ncp-iam-access-key", ACCESS_KEY); + header.set("x-ncp-apigw-signature-v2", signature); + }) + .build(); + + String sendUserName = sender.getName(); + String date = reservation.getDate().toString(); + String time = reservation.getTime().toString(); + String receiveUserName = receiver.getName(); + String productName = experienceGift.getTitle(); + String persons = reservation.getPersons().toString() + "명"; + + List messages = new ArrayList<>(); + messages.add(MessageMapping.builder() + .to(receiver.getPhoneNumber()) + .content("[셸위]\n" + + sendUserName + "님이 초대장을 보냈어요!\uD83C\uDF81\n" + + "\n" + + "예약날짜: " + date + "\n" + + "예약시간: " + time + "\n" + + "수취인: " + receiveUserName + "\n" + + "상품명: " + productName + "\n" + + "옵션: " + persons + "\n" + + "\n" + + "따뜻한 마음이 담긴 선물을\n" + + "지금 바로 셸위 어플에서 확인해보세요\uD83E\uDD70") + .build()); + + AlimTalkReq alimTalkReq = AlimTalkReq.builder() + .plusFriendId("@shallwee") + .templateCode("invitation") + .messages(messages) + .build(); + + ObjectMapper objectMapper = new ObjectMapper(); + String body = objectMapper.writeValueAsString(alimTalkReq); + + return restClient.post() + .uri("/services/" + BIZTALK_SERVICE_ID + "/messages") + .body(body) + .retrieve() + .body(SmsResponseDto.class); + } + @Transactional public Message validVerificationCode(ValidVerificationCodeReq validVerificationCodeReq) { LocalDateTime time = LocalDateTime.now(); @@ -122,11 +242,10 @@ public Message validVerificationCode(ValidVerificationCodeReq validVerificationC .build(); } - private String makeSignature(String timestamp) throws Exception { + public String makeSignature(String timestamp, String url) throws Exception { String space = " "; String newLine = "\n"; String method = "POST"; - String url = "/sms/v2/services/" + SERVICE_ID + "/messages"; String message = new StringBuilder() .append(method) @@ -146,7 +265,7 @@ private String makeSignature(String timestamp) throws Exception { return Base64.getEncoder().encodeToString(rawHmac); } - private String generateRandomCode() { + public String generateRandomCode() { return String.format("%06d", new Random().nextInt(999999)); } diff --git a/src/main/java/com/shallwe/global/infrastructure/sms/dto/AlimTalkReq.java b/src/main/java/com/shallwe/global/infrastructure/sms/dto/AlimTalkReq.java new file mode 100644 index 00000000..55db56a6 --- /dev/null +++ b/src/main/java/com/shallwe/global/infrastructure/sms/dto/AlimTalkReq.java @@ -0,0 +1,22 @@ +package com.shallwe.global.infrastructure.sms.dto; + +import lombok.Builder; +import lombok.Data; + +import java.util.List; + +@Data +public class AlimTalkReq { + + private String plusFriendId; + private String templateCode; + private List messages; + + @Builder + public AlimTalkReq(String plusFriendId, String templateCode, List messages) { + this.plusFriendId = plusFriendId; + this.templateCode = templateCode; + this.messages = messages; + } + +} diff --git a/src/main/java/com/shallwe/domain/auth/dto/MessageMapping.java b/src/main/java/com/shallwe/global/infrastructure/sms/dto/MessageMapping.java similarity index 83% rename from src/main/java/com/shallwe/domain/auth/dto/MessageMapping.java rename to src/main/java/com/shallwe/global/infrastructure/sms/dto/MessageMapping.java index 7a5539fe..780e2d16 100644 --- a/src/main/java/com/shallwe/domain/auth/dto/MessageMapping.java +++ b/src/main/java/com/shallwe/global/infrastructure/sms/dto/MessageMapping.java @@ -1,4 +1,4 @@ -package com.shallwe.domain.auth.dto; +package com.shallwe.global.infrastructure.sms.dto; import lombok.Builder; import lombok.Data;