177 lines
7.1 KiB
Java
177 lines
7.1 KiB
Java
|
|
package com.mtkj.mtpay.controller;
|
|||
|
|
|
|||
|
|
import com.mtkj.mtpay.common.Result;
|
|||
|
|
import com.mtkj.mtpay.common.ResultCode;
|
|||
|
|
import com.mtkj.mtpay.dto.request.CheckoutRequestDTO;
|
|||
|
|
import com.mtkj.mtpay.entity.PaymentOrder;
|
|||
|
|
import com.mtkj.mtpay.service.PaymentOrderService;
|
|||
|
|
import jakarta.validation.Valid;
|
|||
|
|
import lombok.RequiredArgsConstructor;
|
|||
|
|
import lombok.extern.slf4j.Slf4j;
|
|||
|
|
import org.springframework.http.ResponseEntity;
|
|||
|
|
import org.springframework.web.bind.annotation.*;
|
|||
|
|
|
|||
|
|
import java.util.HashMap;
|
|||
|
|
import java.util.Map;
|
|||
|
|
import java.util.Optional;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 支付控制器
|
|||
|
|
*/
|
|||
|
|
@Slf4j
|
|||
|
|
@RestController
|
|||
|
|
@RequestMapping("/api/payment")
|
|||
|
|
@RequiredArgsConstructor
|
|||
|
|
public class PaymentController {
|
|||
|
|
|
|||
|
|
private final PaymentOrderService paymentOrderService;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 创建支付订单
|
|||
|
|
*/
|
|||
|
|
@PostMapping("/checkout")
|
|||
|
|
public ResponseEntity<Result<Map<String, Object>>> checkout(@Valid @RequestBody CheckoutRequestDTO request) {
|
|||
|
|
log.info("收到创建支付订单请求,商户订单号: {}", request.getMerchantTransactionId());
|
|||
|
|
|
|||
|
|
PaymentOrder order = paymentOrderService.createPaymentOrder(request);
|
|||
|
|
|
|||
|
|
Map<String, Object> data = new HashMap<>();
|
|||
|
|
data.put("merchantTransactionId", order.getMerchantTransactionId());
|
|||
|
|
data.put("token", order.getToken());
|
|||
|
|
data.put("paymentUrl", order.getPaymentUrl());
|
|||
|
|
data.put("status", order.getStatus());
|
|||
|
|
|
|||
|
|
return ResponseEntity.ok(Result.success("订单创建成功", data));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 查询订单状态
|
|||
|
|
*/
|
|||
|
|
@GetMapping("/order/{merchantTransactionId}")
|
|||
|
|
public ResponseEntity<Result<Map<String, Object>>> getOrder(@PathVariable String merchantTransactionId) {
|
|||
|
|
log.info("查询订单状态,商户订单号: {}", merchantTransactionId);
|
|||
|
|
|
|||
|
|
Optional<PaymentOrder> orderOpt = paymentOrderService.findByMerchantTransactionId(merchantTransactionId);
|
|||
|
|
|
|||
|
|
if (orderOpt.isPresent()) {
|
|||
|
|
PaymentOrder order = orderOpt.get();
|
|||
|
|
Map<String, Object> data = new HashMap<>();
|
|||
|
|
data.put("merchantTransactionId", order.getMerchantTransactionId());
|
|||
|
|
data.put("transactionId", order.getTransactionId() != null ? order.getTransactionId() : "");
|
|||
|
|
data.put("status", order.getStatus());
|
|||
|
|
data.put("amount", order.getAmount());
|
|||
|
|
data.put("currency", order.getCurrency());
|
|||
|
|
data.put("createTime", order.getCreateTime());
|
|||
|
|
data.put("token", order.getToken());
|
|||
|
|
data.put("paymentUrl", order.getPaymentUrl());
|
|||
|
|
|
|||
|
|
return ResponseEntity.ok(Result.success(data));
|
|||
|
|
} else {
|
|||
|
|
return ResponseEntity.ok(Result.fail(ResultCode.ORDER_NOT_FOUND));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取收银台页面HTML
|
|||
|
|
* 返回包含SDK初始化的HTML页面
|
|||
|
|
*/
|
|||
|
|
@GetMapping("/checkout/page")
|
|||
|
|
public ResponseEntity<String> getCheckoutPage(@RequestParam String token) {
|
|||
|
|
log.info("获取收银台页面,token: {}", token);
|
|||
|
|
|
|||
|
|
String html = generateCheckoutPage(token);
|
|||
|
|
return ResponseEntity.ok()
|
|||
|
|
.header("Content-Type", "text/html;charset=UTF-8")
|
|||
|
|
.body(html);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 生成收银台页面HTML
|
|||
|
|
*/
|
|||
|
|
private String generateCheckoutPage(String token) {
|
|||
|
|
return """
|
|||
|
|
<!doctype html>
|
|||
|
|
<html lang="zh-CN">
|
|||
|
|
<head>
|
|||
|
|
<meta charset="UTF-8">
|
|||
|
|
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
|||
|
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|||
|
|
<title>PingPong支付收银台</title>
|
|||
|
|
<style>
|
|||
|
|
#ufo-container {
|
|||
|
|
width: 100%;
|
|||
|
|
min-height: 100vh;
|
|||
|
|
margin: 0 auto;
|
|||
|
|
padding: 20px;
|
|||
|
|
box-sizing: border-box;
|
|||
|
|
}
|
|||
|
|
</style>
|
|||
|
|
</head>
|
|||
|
|
<body>
|
|||
|
|
<div id="ufo-container"></div>
|
|||
|
|
<script src="https://pay-cdn.pingpongx.com/production/static/sdk/1.2.0/ppPay.min.js"></script>
|
|||
|
|
<script>
|
|||
|
|
window.onload = function() {
|
|||
|
|
let client = new ppPay({
|
|||
|
|
lang: 'zh',
|
|||
|
|
root: '#ufo-container',
|
|||
|
|
manul: false,
|
|||
|
|
located: true,
|
|||
|
|
showPrice: true,
|
|||
|
|
bill: true,
|
|||
|
|
mode: 'sandbox',
|
|||
|
|
menu: false,
|
|||
|
|
base: {
|
|||
|
|
width: '100%',
|
|||
|
|
height: '100%',
|
|||
|
|
fontSize: '14px',
|
|||
|
|
backgroundColor: '#fff',
|
|||
|
|
showHeader: true,
|
|||
|
|
showHeaderLabel: true,
|
|||
|
|
headerLabelFont: "支付",
|
|||
|
|
headerColor: '#333333',
|
|||
|
|
headerSize: '16px',
|
|||
|
|
headerBackgroundColor: '#fff',
|
|||
|
|
headerPadding: '20px',
|
|||
|
|
btnSize: '100%',
|
|||
|
|
btnColor: '#fff',
|
|||
|
|
btnFontSize: '14px',
|
|||
|
|
btnPaddingX: '20px',
|
|||
|
|
btnPaddingY: '10px',
|
|||
|
|
btnBackgroundColor: '#1fa0e8',
|
|||
|
|
btnBorderRadius: '4px',
|
|||
|
|
btnMarginTop: '20px'
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
let sdkConfig = {
|
|||
|
|
token: '%s'
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
client.createPayment(sdkConfig);
|
|||
|
|
|
|||
|
|
function setPPPayPropWin() {
|
|||
|
|
let winWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
|
|||
|
|
let winHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
|
|||
|
|
let ufoContainer = document.getElementById('ufo-container');
|
|||
|
|
|
|||
|
|
if (winWidth >= 500) {
|
|||
|
|
let clientW = Math.floor(winWidth / 3);
|
|||
|
|
clientW = clientW >= 500 ? clientW : 500;
|
|||
|
|
ufoContainer.style.width = clientW + 'px';
|
|||
|
|
} else {
|
|||
|
|
ufoContainer.style.width = winWidth + 'px';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
setPPPayPropWin();
|
|||
|
|
window.addEventListener('resize', setPPPayPropWin);
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
</body>
|
|||
|
|
</html>
|
|||
|
|
""".formatted(token);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|