Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@ dependencies {
implementation group: 'com.google.maps', name: 'google-maps-services', version: '2.2.0'

// payment
implementation 'com.github.iamport:iamport-rest-client-java:0.2.23'
implementation 'com.siot:iamport-rest-client:1.2.0'
implementation 'io.portone:server-sdk:0.17.0'

compileOnly 'org.projectlombok:lombok'

Expand Down
2 changes: 2 additions & 0 deletions nginx/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ http {
listen [::]:80;
server_name api.gongspot.site;

client_max_body_size 10M;

# Let's Encrypt 인증 요청은 HTTP로 유지
location ^~ /.well-known/acme-challenge/ {
allow all;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class OrderRequestDTO {
private Long userId;
private Long productId;
private PayMethod payMethod;
private BigDecimal totalPrice;
private Long totalPrice;
private String merchantUid;

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,35 @@

import com.gongspot.project.common.code.status.ErrorStatus;
import com.gongspot.project.common.exception.GeneralException;
import com.siot.IamportRestClient.IamportClient;
import com.siot.IamportRestClient.exception.IamportResponseException;
import com.siot.IamportRestClient.response.Payment;

import io.portone.sdk.server.payment.Payment;
import io.portone.sdk.server.payment.PaymentClient;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.concurrent.CompletionException;

@Slf4j
@Service
@RequiredArgsConstructor
public class PortoneApiService {

private IamportClient iamportClient;
private PaymentClient iamportClient;

@Value("${imp.api-key}")
private String apiKey;

@Value("${imp.store-id}")
private String storeId;

@Value("${imp.api.secretkey}")
private String secretKey;

@PostConstruct
public void init() {
this.iamportClient = new IamportClient(apiKey, secretKey);
this.iamportClient = new PaymentClient(secretKey,"https://api.portone.io", storeId);
}

/**
Expand All @@ -38,27 +39,30 @@ public void init() {
* @param impUid 클라이언트로부터 전달받은 결제 고유번호
* @param clientAmount 클라이언트가 요청한 결제 금액
*/
public void verifyPayment(String impUid, BigDecimal clientAmount) {
public void verifyPayment(String impUid, Long clientAmount) {
try {
Payment payment = iamportClient.paymentByImpUid(impUid).getResponse();
Payment payment = iamportClient.getPayment(impUid).join();

if (payment == null) {
log.error("Payment not found for impUid: {}", impUid);
if (payment instanceof Payment.Unrecognized) {
log.error("Unrecognized payment type for impUid: {}", impUid);
throw new GeneralException(ErrorStatus.PAYMENT_NOT_FOUND);
}

// 서버 DB에 저장된 금액(clientAmount)과 아임포트 서버의 실제 결제 금액(payment.getAmount()) 비교
BigDecimal portoneAmount = payment.getAmount();
if (portoneAmount.compareTo(clientAmount) != 0) {
log.error("Payment amount mismatch. Portone amount: {}, Client amount: {}", portoneAmount, clientAmount);
throw new GeneralException(ErrorStatus.PAYMENT_AMOUNT_MISMATCH);
}
if (payment instanceof Payment.Recognized recognized) {
Long portoneAmount = recognized.getAmount().getTotal();

log.info("Payment verification successful for impUid: {}", impUid);
if (portoneAmount.compareTo(clientAmount) != 0) {
log.error("Payment amount mismatch. Portone amount: {}, Client amount: {}", portoneAmount, clientAmount);
throw new GeneralException(ErrorStatus.PAYMENT_AMOUNT_MISMATCH);
}

} catch (IamportResponseException | IOException e) {
log.info("Payment verification successful for impUid: {}", impUid);
}

} catch (CompletionException e) {
log.error("Failed to verify payment with impUid: {}", impUid, e);
throw new GeneralException(ErrorStatus.PAYMENT_VERIFICATION_FAILED);
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
@RestController
@RequiredArgsConstructor
@RequestMapping("/reviews")
@Tag(name = "Review")
@Tag(name = "리뷰" , description = "리뷰 관련 API")
@Validated
public class ReviewController {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,18 +66,20 @@ public void saveReview(Long userId, Long placeId, ReviewRequestDTO.ReviewRegiste
likeRepository.save(newLike);
}

for (MultipartFile picture : reviewPictures) {
String uuid = UUID.randomUUID().toString();
Uuid savedUuid = uuidRepository.save(Uuid.builder()
.uuid(uuid).build());
if (reviewPictures != null && !reviewPictures.isEmpty()) {
for (MultipartFile picture : reviewPictures) {
String uuid = UUID.randomUUID().toString();
Uuid savedUuid = uuidRepository.save(Uuid.builder()
.uuid(uuid).build());

ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentLength(picture.getSize());
metadata.setContentType(picture.getContentType());
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentLength(picture.getSize());
metadata.setContentType(picture.getContentType());

String pictureUrl = s3Manager.uploadFile(s3Manager.generateReviewKeyName(savedUuid), savedUuid.getUuid(), picture, metadata);
String pictureUrl = s3Manager.uploadFile(s3Manager.generateReviewKeyName(savedUuid), savedUuid.getUuid(), picture, metadata);

mediaRepository.save(ReviewConverter.toReviewImage(pictureUrl, picture.getOriginalFilename(), picture.getContentType(), newReview));
mediaRepository.save(ReviewConverter.toReviewImage(pictureUrl, picture.getOriginalFilename(), picture.getContentType(), newReview));
}
}
} catch (DataIntegrityViolationException e) {
throw new BusinessException(ErrorStatus.REVIEW_SAVE_FAIL);
Expand Down
3 changes: 2 additions & 1 deletion src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,5 @@ spring.servlet.multipart.max-request-size=10MB
# iamport payment
imp.api-key = ${IMP_API_KEY}
imp.api.secretkey = ${IMP_SECRET_KEY}
imp.imp_uid=${IMP_UID}
imp.imp_uid=${IMP_UID}
imp.store-id=${IMP_SID}