7.14 简单前端界面实现

This commit is contained in:
zhangsan 2025-07-14 11:58:54 +08:00
parent 26b3302a56
commit fbaa6b06dc
10 changed files with 265 additions and 27 deletions

View File

@ -0,0 +1,5 @@
<form name="punchout_form" method="post" action="https://openapi-sandbox.dl.alipaydev.com/gateway.do?charset=utf-8&method=alipay.trade.page.pay&sign=fVfjda%2FIPa2CS680R%2Fqn3%2BvyNzSd7eVavXWa5IXG6bvxmwhmo1PKDMRDjYBNFHm4ppgcKaUohl7Wl1bfhSta1LK44%2FjMWqiuRYm3gpFkj1gt4ZKeuXYmQO7lcvdTyDF9U2xA%2BydKEWmuJVKJ%2BRRV5xEwCZ2ZICq%2BeF442IFmqpjrjNUlsswlNM%2BfzFJUaDggBXaKKfr0B8h%2BQ0lEfPA%2FfahBLoMG9V3CcxDPE0CGtL6YUacHzFY4niWZM7Lf2e0r5giXHKiAQ%2Fkx4vHbh4N7yG%2B%2BAj2OlDdVSolMOG3Vs3leElRttAWRJLTUxwR3GSHdQScr8kOEnEaCc9TiVGCNmg%3D%3D&return_url=https%3A%2F%2Fgaga.plus&notify_url=http%3A%2F%2Fxfg-studio.natapp1.cc%2Fapi%2Fv1%2Falipay%2Falipay_notify_url&version=1.0&app_id=9021000132689924&sign_type=RSA2&timestamp=2024-10-04+09%3A44%3A12&alipay_sdk=alipay-sdk-java-4.38.157.ALL&format=json">
<input type="hidden" name="biz_content" value="{&quot;out_trade_no&quot;:&quot;26674145122785&quot;,&quot;total_amount&quot;:&quot;1.68&quot;,&quot;subject&quot;:&quot;测试商品&quot;,&quot;product_code&quot;:&quot;FAST_INSTANT_TRADE_PAY&quot;}">
<input type="submit" value="立即支付" style="display:none" >
</form>
<script>document.forms[0].submit();</script>

Binary file not shown.

After

Width:  |  Height:  |  Size: 950 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -0,0 +1,123 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>商品下单支付页</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #f7f7f7;
text-align: center; /* 添加居中对齐 */
}
.container {
max-width: 600px;
margin: 50px auto;
padding: 20px;
background-color: #fff;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.product-info {
margin-bottom: 20px;
border: 1px solid #ddd; /* 添加边框 */
padding: 10px; /* 添加内边距 */
text-align: center; /* 添加居中对齐 */
}
.product-info h2 {
margin: 0;
margin-bottom: 5px;
}
.product-info p {
font-size: 36px; /* 加大字体 */
font-weight: bold; /* 加粗字体 */
color: red; /* 字体颜色改为红色 */
margin: 0; /* 移除默认的margin */
margin-top: 20px;
}
.order-button {
display: block;
width: calc(100% - 40px); /* 减去padding的宽度 */
padding: 10px;
margin: 10px auto; /* 添加自动外边距实现居中 */
font-size: 16px;
color: #fff;
background-color: #007bff;
border: none;
cursor: pointer;
border-radius: 20px; /* 添加圆角 */
}
.order-button:hover {
background-color: #0056b3;
}
.account-info {
font-size: 12px; /* 设置字体大小为9号 */
text-align: center; /* 居中对齐 */
display: block; /* 使span表现得像块级元素 */
margin: 10px 0; /* 添加上下外边距 */
}
</style>
</head>
<body>
<div class="container">
<div class="product-info">
<h2>程序员 - 同款机械键盘</h2>
<img width="350" src="images/keyboard-001.jpg"/>
<p>价格¥1.68</p>
</div>
<button id="orderButton" class="order-button">立即下单「沙箱支付」</button>
<span class="account-info">测试账号jhmfgu7187@sandbox.com 密码111111 支付111111</span>
</div>
<script>
function getCookie(name) {
let cookieArr = document.cookie.split(";");
for(let i = 0; i < cookieArr.length; i++) {
let cookiePair = cookieArr[i].split("=");
if(name == cookiePair[0].trim()) {
return decodeURIComponent(cookiePair[1]);
}
}
return null;
}
document.getElementById('orderButton').addEventListener('click', function() {
var userId = getCookie("loginToken");
if (!userId) {
window.location.href = "login.html"; // 跳转到登录页
return;
}
var productId = "10001";
var url = 'http://127.0.0.1:8092/api/v1/alipay/create_pay_order';
var requestBody = {
userId: userId,
productId: productId
};
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(requestBody) // 将请求体转换为JSON字符串
})
.then(response => response.json()) // 解析JSON格式的响应
.then(json => {
if (json.code === "0000") { // 假设成功的code是"0000"
var formHtml = json.data; // 获取data字段中的HTML表单字符串
document.body.innerHTML += formHtml; // 将表单添加到页面上
document.forms[0].submit(); // 自动提交表单
} else {
console.error('Error:', json.info); // 输出错误信息
}
})
.catch(error => console.error('Error:', error));
});
</script>
</body>
</html>

View File

@ -0,0 +1,105 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>S Pay Mall 商城登录页</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f5f5f5;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
}
.login-container {
background-color: #fff;
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
text-align: center;
max-width: 400px;
width: 100%;
}
.login-container h1 {
margin-bottom: 20px;
color: #333;
}
.qr-code {
margin: 20px 0;
}
.qr-code img {
width: 200px;
height: 200px;
}
.instructions {
color: #666;
font-size: 14px;
}
</style>
</head>
<body>
<div class="login-container">
<h1>S Pay Mall 商城登录页</h1>
<div class="qr-code">
<img id="qr-code-img" src="images/placeholder.png" alt="微信二维码">
</div>
<p class="instructions">请使用微信扫描二维码登录</p>
</div>
<script>
document.addEventListener("DOMContentLoaded", function() {
// 获取二维码 ticket
fetch('http://localhost:8092/api/v1/login/weixin_qrcode_ticket')
.then(response => response.json())
.then(data => {
if (data.code === "0000") {
const ticket = data.data;
const qrCodeImg = document.getElementById('qr-code-img');
qrCodeImg.src = `https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=${ticket}`;
// 开始轮询检查登录状态
const intervalId = setInterval(() => {
checkLoginStatus(ticket, intervalId);
}, 3000); // 每3秒检查一次
} else {
console.error('获取二维码 ticket 失败:', data.info);
}
})
.catch(error => {
console.error('请求失败:', error);
});
function checkLoginStatus(ticket, intervalId) {
fetch(`http://localhost:8092/api/v1/login/check_login?ticket=${ticket}`)
.then(response => response.json())
.then(data => {
if (data.code === "0000") {
console.info("login success");
// 停止轮询
clearInterval(intervalId);
// 保存登录 token 到 cookie设置有效期为30天
setCookie('loginToken', data.data, 30);
// 在这里可以重定向到登录后的页面
window.location.href = 'index.html'; // 假设登录成功后跳转到首页
} else {
console.info("login wait");
}
})
.catch(error => {
console.error('请求失败:', error);
});
}
function setCookie(name, value, days) {
const date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
const expires = "expires=" + date.toUTCString();
document.cookie = name + "=" + value + ";" + expires + ";path=/";
}
});
</script>
</body>
</html>

View File

@ -2,7 +2,6 @@ package edu.whut.config;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -12,12 +11,12 @@ public class AliPayConfig {
@Bean("alipayClient")
public AlipayClient alipayClient(AliPayConfigProperties properties) {
return new DefaultAlipayClient(properties.getGatewayUrl(),
properties.getApp_id(),
properties.getMerchant_private_key(),
properties.getAppId(),
properties.getMerchantPrivateKey(),
properties.getFormat(),
properties.getCharset(),
properties.getAlipay_public_key(),
properties.getSign_type());
properties.getAlipayPublicKey(),
properties.getSignType());
}
}

View File

@ -10,19 +10,19 @@ import org.springframework.stereotype.Component;
public class AliPayConfigProperties {
// 沙箱环境应用ID - 您的APPID收款账号既是你的APPID对应支付宝账号获取地址https://open.alipay.com/develop/sandbox/app
private String app_id;
private String appId;
// 沙箱环境商户私钥你的PKCS8格式RSA2私钥
private String merchant_private_key;
private String merchantPrivateKey;
// 沙箱环境支付宝公钥
private String alipay_public_key;
private String alipayPublicKey;
// 沙箱环境服务器异步通知页面路径
private String notify_url;
private String notifyUrl;
// 沙箱环境页面跳转同步通知页面路径 需http://格式的完整路径不能加?id=123这类自定义参数必须外网可以正常访问
private String return_url;
private String returnUrl;
// 沙箱环境
private String gatewayUrl;
// 签名方式
private String sign_type = "RSA2";
private String signType = "RSA2";
// 字符编码格式
private String charset = "utf-8";
// 传输格式

View File

@ -52,7 +52,7 @@ alipay:
alipay_public_key: ${paymall.alipay.alipay-public-key}
notify_url: ${paymall.alipay.notify-url}
return_url: ${paymall.alipay.return-url}
gateway-url: ${paymall.alipay.gateway-url}
gateway_url: ${paymall.alipay.gateway-url}
# 日志
logging:

View File

@ -33,24 +33,24 @@ public class AliPayTest {
@Before
public void init() {
log.info(config.getNotify_url());
log.info(config.getNotifyUrl());
// 用属性里的值来构造 AlipayClient
this.alipayClient = new DefaultAlipayClient(
config.getGatewayUrl(),
config.getApp_id(),
config.getMerchant_private_key(),
config.getAppId(),
config.getMerchantPrivateKey(),
config.getFormat(),
config.getCharset(),
config.getAlipay_public_key(),
config.getSign_type()
config.getAlipayPublicKey(),
config.getSignType()
);
}
@Test
public void test_aliPay_pageExecute() throws AlipayApiException {
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest(); // 发送请求的 Request类
request.setNotifyUrl(config.getNotify_url());
request.setReturnUrl(config.getReturn_url());
request.setNotifyUrl(config.getNotifyUrl());
request.setReturnUrl(config.getReturnUrl());
JSONObject bizContent = new JSONObject();
bizContent.put("out_trade_no", "smile000091004001"); // 我们自己生成的订单编号
@ -79,7 +79,7 @@ public class AliPayTest {
public void test_alipay_certificateExecute() throws AlipayApiException {
AlipayTradeQueryModel bizModel = new AlipayTradeQueryModel();
bizModel.setOutTradeNo("daniel82AAAA000032333361Y001");
bizModel.setOutTradeNo("smile000091004001");
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
request.setBizModel(bizModel);

View File

@ -4,6 +4,7 @@ import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeQueryResponse;
import edu.whut.domain.order.service.IOrderService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@ -16,12 +17,12 @@ import java.util.List;
*/
@Slf4j
@Component()
@RequiredArgsConstructor
public class NoPayNotifyOrderJob {
@Resource
private IOrderService orderService;
@Resource
private AlipayClient alipayClient;
private final IOrderService orderService;
private final AlipayClient alipayClient;
/**
* 每3秒执行一次扫描超过1分钟未收到回调的待支付订单
@ -29,7 +30,7 @@ public class NoPayNotifyOrderJob {
@Scheduled(cron = "0/3 * * * * ?")
public void exec() {
try {
log.info("任务检测未接收到或未正确处理的支付回调通知");
log.info("任务检测未接收到或未正确处理的支付回调通知");
List<String> orderIds = orderService.queryNoPayNotifyOrder();
if (null == orderIds || orderIds.isEmpty()) return;
@ -46,10 +47,15 @@ public class NoPayNotifyOrderJob {
// 如果支付宝返回业务成功码(10000)则更新订单为支付成功
if ("10000".equals(code)) {
orderService.changeOrderPaySuccess(orderId);
}else {
log.warn("订单[{}]支付宝查询未成功:{}/{}",
orderId,
alipayTradeQueryResponse.getSubCode(),
alipayTradeQueryResponse.getSubMsg());
}
}
} catch (Exception e) {
log.error("检测未接收到或未正确处理的支付回调通知失败", e);
log.error("任务:检测未接收到或未正确处理的支付回调通知 失败", e);
}
}