/**
* Controller handling VNPAY payment integration endpoints.
*
* Provides both web interface (JSP pages) and REST APIs for payment operations:
* - Payment creation and processing
* - Transaction status queries
* - Refund operations
* - Instant Payment Notification (IPN) handling
*
* Web Interface Endpoints:
* - GET / : Index page
* - GET /pay : Payment form
* - GET /querydr : Transaction query
* - GET /refund : Refund request
* - GET /ipn : IPN test interface
*
* REST API Endpoints:
* - POST /api/payment/create : Create new payment
* - POST /api/payment/process : Process payment return
* - POST /api/payment/query : Query transaction status
* - POST /api/payment/refund : Request refund
* - POST /ipn : Handle IPN notifications
*
* Supports both JSP templates (/WEB-INF/jsp/) and HTML templates
(/resources/templates/)
* for different view rendering needs.
*/
package Project_ITSS.[Link];
import Project_ITSS.[Link].*;
import Project_ITSS.[Link];
import Project_ITSS.[Link].*;
import [Link];
import [Link];
import [Link];
import [Link];
import [Link].*;
import [Link];
//import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
@Controller
public class VNPayController {
private static final Logger logger =
[Link]([Link]);
private final VNPayService vnPayService;
@Autowired
public VNPayController(VNPayService vnPayService) {
[Link] = vnPayService;
}
/**
* View Controllers for rendering JSP pages
*/
/**
* Renders the index page
* @return index view name
*/
@GetMapping("/")
public String index() {
return "index";
}
/**
* Renders the payment form page
* @return payment form view name
*/
@GetMapping("/pay")
public String paymentPage() {
return "vnpay_pay";
}
/**
* Renders the transaction query page
* @return query form view name
*/
@GetMapping("/querydr")
public String queryPage() {
return "vnpay_querydr";
}
/**
* Renders the refund request page
* @return refund form view name
*/
@GetMapping("/refund")
public String refundPage() {
return "vnpay_refund";
}
/**
* Handles the return URL from VNPAY after payment
* Validates the payment response signature and displays the result
*
* @param requestParams Parameters returned from VNPAY
* @param request HTTP request
* @param model Spring MVC model
* @return return page view name
*/
@GetMapping("/return")
public String returnPage(
@RequestParam Map<String, String> requestParams,
HttpServletRequest request,
[Link] model) {
// Create copy of params for hash calculation
Map<String, String> fields = new HashMap<>(requestParams);
// Get and remove hash from param map before recalculating
String vnp_SecureHash = [Link]("vnp_SecureHash");
[Link]("vnp_SecureHashType");
[Link]("vnp_SecureHash");
// Create response object
PaymentReturnResponse response = new PaymentReturnResponse();
// Validate hash
String signValue = [Link](fields);
[Link]([Link](vnp_SecureHash));
if ([Link]()) {
// Parse and validate required fields
try {
[Link]([Link]("vnp_TxnRef"));
[Link]([Link]([Link]("vnp_Amount",
"0")));
[Link]([Link]("vnp_OrderInfo"));
[Link]([Link]("vnp_ResponseCode"));
[Link]([Link]("vnp_TransactionNo"));
[Link]([Link]("vnp_BankCode"));
// Parse payment date
String payDate = [Link]("vnp_PayDate");
if (payDate != null && [Link]() >= 14) {
LocalDateTime dateTime = [Link](
[Link](0, 14),
[Link]("yyyyMMddHHmmss")
);
[Link](dateTime);
}
[Link]([Link]("vnp_TransactionStatus"));
} catch (Exception e) {
// Log the error
[Link]("Error processing return URL parameters", e);
[Link]("Lỗi xử lý thông tin thanh toán");
[Link](false);
}
}
// Log transaction details
[Link]("Payment return - TxnId: {}, Amount: {}, Status: {},
ResponseCode: {}",
[Link](),
[Link](),
[Link](),
[Link]()
);
[Link]("payment", response);
return "vnpay_return";
}
/**
* Renders the IPN test page
* @return IPN test view name
*/
@GetMapping("/ipn")
public String ipnPage() {
return "vnpay_ipn";
}
/**
* REST API Controllers for VNPAY integration
*/
/**
* API endpoint for creating a new payment
* Generates payment URL with VNPAY signature
*
* @param request Payment request with amount and other details
* @param servletRequest HTTP request for client IP
* @return ResponseEntity with payment URL and status
*/
@GetMapping("/api/payment/form")
public String showPaymentForm() {
return "payment-form";
}
@PostMapping("/api/payment/create")
@ResponseBody
public ResponseEntity<PaymentResponse> createPayment(
@RequestBody PaymentRequest request,
HttpServletRequest servletRequest) {
PaymentResponse response = [Link](request,
servletRequest);
return [Link](response);
}
@PostMapping("/api/payment/process")
@ResponseBody
public ResponseEntity<PaymentReturnResponse> processPayment(
@RequestParam Map<String, String> requestParams) {
Map<String, String> fields = new HashMap<>(requestParams);
String vnp_SecureHash = [Link]("vnp_SecureHash");
[Link]("vnp_SecureHashType");
[Link]("vnp_SecureHash");
PaymentReturnResponse response = new PaymentReturnResponse();
String signValue = [Link](fields);
[Link]([Link](vnp_SecureHash));
if ([Link]()) {
try {
[Link]([Link]("vnp_TxnRef"));
[Link]([Link]([Link]("vnp_Amount",
"0")));
[Link]([Link]("vnp_OrderInfo"));
[Link]([Link]("vnp_ResponseCode"));
[Link]([Link]("vnp_TransactionNo"));
[Link]([Link]("vnp_BankCode"));
String payDate = [Link]("vnp_PayDate");
if (payDate != null && [Link]() >= 14) {
LocalDateTime dateTime = [Link](
[Link](0, 14),
[Link]("yyyyMMddHHmmss")
);
[Link](dateTime);
}
[Link]([Link]("vnp_TransactionStatus"));
} catch (Exception e) {
[Link]("Error processing payment response", e);
[Link]("Error processing payment information");
[Link](false);
}
}
[Link]("Payment processed - TxnId: {}, Amount: {}, Status: {},
ResponseCode: {}",
[Link](),
[Link](),
[Link](),
[Link]()
);
return [Link](response);
}
/**
* API endpoint for querying transaction status
*
* @param request Query parameters with order ID
* @param servletRequest HTTP request for client IP
* @return ResponseEntity with transaction details
*/
@PostMapping("/api/payment/query")
@ResponseBody
public ResponseEntity<QueryResponse> queryTransaction(
@RequestBody QueryRequest request,
HttpServletRequest servletRequest) {
QueryResponse response = [Link](request,
servletRequest);
return [Link](response);
}
/**
* API endpoint for refund requests
*
* @param request Refund details including amount
* @param servletRequest HTTP request for client IP
* @return ResponseEntity with refund status
*/
@PostMapping("/api/payment/refund")
@ResponseBody
public ResponseEntity<RefundResponse> refundTransaction(
@RequestBody RefundRequest request,
HttpServletRequest servletRequest) {
RefundResponse response = [Link](request,
servletRequest);
return [Link](response);
}
/**
* Handles IPN (Instant Payment Notification) from VNPAY
* Validates signature and processes payment confirmation
*
* @param requestParams Parameters sent by VNPAY
* @return ResponseEntity with processing status
*/
@PostMapping("/ipn")
@ResponseBody
public ResponseEntity<IPNResponse> handleIpnNotification(
@RequestParam MultiValueMap<String, String> requestParams) {
// Convert MultiValueMap to Map<String, String> for VNPay service
Map<String, String> vnpParams = new HashMap<>();
[Link]((key, value) -> {
if (value != null && ![Link]()) {
[Link](key, [Link](0));
}
});
IPNResponse response = [Link](vnpParams);
return [Link](response);
}
}