diff --git a/src/main/java/com/example/sharemind/admin/application/AdminService.java b/src/main/java/com/example/sharemind/admin/application/AdminService.java index b667d56d..a426d3a3 100644 --- a/src/main/java/com/example/sharemind/admin/application/AdminService.java +++ b/src/main/java/com/example/sharemind/admin/application/AdminService.java @@ -10,13 +10,13 @@ import com.example.sharemind.admin.dto.response.PostGetUnpaidPrivateResponse; import com.example.sharemind.counselor.dto.response.CounselorGetProfileResponse; +import com.example.sharemind.sms.dto.response.SmsGetResponse; import java.util.List; public interface AdminService { List getUnpaidConsults(); - void updateConsultIsPaid(Long consultId); - + SmsGetResponse updateConsultIsPaid(Long consultId); List getPendingCounselors(); void updateProfileStatus(Long counselorId, Boolean isPassed); diff --git a/src/main/java/com/example/sharemind/admin/application/AdminServiceImpl.java b/src/main/java/com/example/sharemind/admin/application/AdminServiceImpl.java index d6684e73..24ed9a2a 100644 --- a/src/main/java/com/example/sharemind/admin/application/AdminServiceImpl.java +++ b/src/main/java/com/example/sharemind/admin/application/AdminServiceImpl.java @@ -40,6 +40,8 @@ import com.example.sharemind.post.domain.Post; import com.example.sharemind.post.exception.PostErrorCode; import com.example.sharemind.post.exception.PostException; +import com.example.sharemind.sms.application.SmsService; +import com.example.sharemind.sms.dto.response.SmsGetResponse; import lombok.RequiredArgsConstructor; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; @@ -52,6 +54,7 @@ @Transactional(readOnly = true) @RequiredArgsConstructor public class AdminServiceImpl implements AdminService { + private static final String SHUT_DOWN_KEY = "SHUT_DOWN"; private final ConsultService consultService; @@ -62,6 +65,7 @@ public class AdminServiceImpl implements AdminService { private final CustomerService customerService; private final PostService postService; private final EmailService emailService; + private final SmsService smsService; private final RedisTemplate redisTemplate; @Override @@ -72,7 +76,7 @@ public List getUnpaidConsults() { } @Transactional - public void updateConsultIsPaid(Long consultId) { + public SmsGetResponse updateConsultIsPaid(Long consultId) { Consult consult = consultService.getConsultByConsultId(consultId); if (consult.getPayment().getIsPaid()) { throw new ConsultException(ConsultErrorCode.CONSULT_ALREADY_PAID, consultId.toString()); @@ -90,6 +94,7 @@ public void updateConsultIsPaid(Long consultId) { consult.updateIsPaidAndChat(chat); } } + return smsService.sendSmsCounselor(consult.getCounselor().getCounselorId()); } @Override diff --git a/src/main/java/com/example/sharemind/admin/presentation/AdminController.java b/src/main/java/com/example/sharemind/admin/presentation/AdminController.java index 559bda59..3e2892ca 100644 --- a/src/main/java/com/example/sharemind/admin/presentation/AdminController.java +++ b/src/main/java/com/example/sharemind/admin/presentation/AdminController.java @@ -11,6 +11,7 @@ import com.example.sharemind.admin.dto.response.PostGetUnpaidPrivateResponse; import com.example.sharemind.counselor.dto.response.CounselorGetProfileResponse; import com.example.sharemind.global.exception.CustomExceptionResponse; +import com.example.sharemind.sms.dto.response.SmsGetResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; @@ -44,7 +45,7 @@ public ResponseEntity> getUnpaidConsults() { @Operation(summary = "상담(편지/채팅) 결제 여부 수정", description = "결제 여부(isPaid)가 false인 consult를 true로 수정") @ApiResponses({ - @ApiResponse(responseCode = "200", description = "수정 성공"), + @ApiResponse(responseCode = "200", description = "수정 성공, resultCode로 sms api 발송 여부가 전달됩니다."), @ApiResponse(responseCode = "400", description = "이미 결제 완료된 상담", content = @Content(mediaType = "application/json", schema = @Schema(implementation = CustomExceptionResponse.class)) @@ -58,9 +59,8 @@ public ResponseEntity> getUnpaidConsults() { @Parameter(name = "consultId", description = "상담 아이디") }) @PatchMapping("/unpaid-consults/{consultId}") - public ResponseEntity updateConsultIsPaid(@PathVariable Long consultId) { - adminService.updateConsultIsPaid(consultId); - return ResponseEntity.ok().build(); + public ResponseEntity updateConsultIsPaid(@PathVariable Long consultId) { + return ResponseEntity.ok(adminService.updateConsultIsPaid(consultId)); } @Operation(summary = "심사 대기 중인 상담사 프로필 조회", description = "심사 대기 중인 상담사 프로필 조회") diff --git a/src/main/java/com/example/sharemind/payApp/application/PayAppServiceImpl.java b/src/main/java/com/example/sharemind/payApp/application/PayAppServiceImpl.java index 20fdf1e4..d8518e2c 100644 --- a/src/main/java/com/example/sharemind/payApp/application/PayAppServiceImpl.java +++ b/src/main/java/com/example/sharemind/payApp/application/PayAppServiceImpl.java @@ -12,6 +12,7 @@ import com.example.sharemind.payment.domain.Payment; import com.example.sharemind.post.application.PostService; import com.example.sharemind.post.domain.Post; +import com.example.sharemind.sms.application.SmsService; import jakarta.servlet.http.HttpServletRequest; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; @@ -40,6 +41,7 @@ public class PayAppServiceImpl implements PayAppService { private final PostService postService; private final ChatService chatService; private final LetterService letterService; + private final SmsService smsService; private final RestClient restClient = RestClient.builder() .baseUrl(PAY_APP_URL) @@ -171,7 +173,8 @@ public String confirmConsult(HttpServletRequest request) { URLDecoder.decode(request.getParameter("pay_date"), StandardCharsets.UTF_8)); if (!payAppUserId.equals(userId) || !payAppKey.equals(key) || !payAppValue.equals(value)) { - throw new PayAppException(PayAppErrorCode.CONFIRM_BASIC_INFO_FAIL, userId + " " + key + " " + value); + throw new PayAppException(PayAppErrorCode.CONFIRM_BASIC_INFO_FAIL, + userId + " " + key + " " + value); } Payment payment = paymentService.getPaymentByPayAppId(payAppId); @@ -195,6 +198,7 @@ public String confirmConsult(HttpServletRequest request) { consult.updateIsPaidAndChat(chat, payMethod.getMethod(), approvedAt); } } + smsService.sendSmsCounselor(consult.getCounselor().getCounselorId()); } return "SUCCESS"; @@ -216,7 +220,8 @@ public String confirmPost(HttpServletRequest request) { URLDecoder.decode(request.getParameter("pay_date"), StandardCharsets.UTF_8)); if (!payAppUserId.equals(userId) || !payAppKey.equals(key) || !payAppValue.equals(value)) { - throw new PayAppException(PayAppErrorCode.CONFIRM_BASIC_INFO_FAIL, userId + " " + key + " " + value); + throw new PayAppException(PayAppErrorCode.CONFIRM_BASIC_INFO_FAIL, + userId + " " + key + " " + value); } Post post = postService.getPostByPayAppId(payAppId); diff --git a/src/main/java/com/example/sharemind/sms/application/SmsService.java b/src/main/java/com/example/sharemind/sms/application/SmsService.java new file mode 100644 index 00000000..eee477f3 --- /dev/null +++ b/src/main/java/com/example/sharemind/sms/application/SmsService.java @@ -0,0 +1,8 @@ +package com.example.sharemind.sms.application; + +import com.example.sharemind.sms.dto.response.SmsGetResponse; + +public interface SmsService { + + SmsGetResponse sendSmsCounselor(Long counselorId); +} diff --git a/src/main/java/com/example/sharemind/sms/application/SmsServiceImpl.java b/src/main/java/com/example/sharemind/sms/application/SmsServiceImpl.java new file mode 100644 index 00000000..78fc508b --- /dev/null +++ b/src/main/java/com/example/sharemind/sms/application/SmsServiceImpl.java @@ -0,0 +1,69 @@ +package com.example.sharemind.sms.application; + +import com.example.sharemind.counselor.application.CounselorService; +import com.example.sharemind.counselor.domain.Counselor; +import com.example.sharemind.sms.dto.response.SmsGetResponse; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestClient; + +@Service +@Transactional(readOnly = true) +@RequiredArgsConstructor +public class SmsServiceImpl implements SmsService { + + private static final String BASE_URL = "https://apis.aligo.in"; + private static final String COUNSELOR_MESSAGE = "[셰어마인드] 익명의 셰어님으로부터 {편지||채팅} 상담 요청이 접수되었습니다. 내 정보>마인더로 전환>상담 탭에서 확인 부탁드립니다."; + + private final CounselorService counselorService; + + @Value("${spring.sms.key}") + private String key; + + @Value("${spring.sms.id}") + private String id; + + @Value("${spring.sms.sender}") + private String sender; + + private final RestClient restClient = RestClient.builder() + .baseUrl(BASE_URL) + .build(); + private final ObjectMapper objectMapper; + + @Override + public SmsGetResponse sendSmsCounselor(Long counselorId) { + Counselor counselor = counselorService.getCounselorByCounselorId(counselorId); + return sendSms(counselor.getPhoneNumber(), COUNSELOR_MESSAGE); + } + + private SmsGetResponse sendSms(String phoneNumber, String message) { + + MultiValueMap body = new LinkedMultiValueMap<>(); + body.add("key", key); + body.add("user_id", id); + body.add("sender", sender); + body.add("receiver", phoneNumber); + body.add("msg", message); +// body.add("testmode_yn", "Y"); + + String response = restClient.post() + .uri("/send/") + .body(body).retrieve() + .body(String.class); + try { + JsonNode rootNode = objectMapper.readTree(response); + int resultCode = rootNode.get("result_code").asInt(); + String responseMessage = rootNode.get("message").asText(); + return SmsGetResponse.of(resultCode, responseMessage); + } catch (Exception e) { + throw new RuntimeException("JSON 처리 중 오류 발생", e); + } + } +} diff --git a/src/main/java/com/example/sharemind/sms/dto/response/SmsGetResponse.java b/src/main/java/com/example/sharemind/sms/dto/response/SmsGetResponse.java new file mode 100644 index 00000000..3cebecdd --- /dev/null +++ b/src/main/java/com/example/sharemind/sms/dto/response/SmsGetResponse.java @@ -0,0 +1,17 @@ +package com.example.sharemind.sms.dto.response; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor(access = AccessLevel.PRIVATE) +public class SmsGetResponse { + + private final int result_code; + private final String message; + + public static SmsGetResponse of(int resultCode, String message) { + return new SmsGetResponse(resultCode, message); + } +}