7.14 简单前端界面实现
This commit is contained in:
parent
26b3302a56
commit
fbaa6b06dc
5
docs/dev-ops/nginx/html/form.html
Normal file
5
docs/dev-ops/nginx/html/form.html
Normal 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¬ify_url=http%3A%2F%2Fxfg-studio.natapp1.cc%2Fapi%2Fv1%2Falipay%2Falipay_notify_url&version=1.0&app_id=9021000132689924&sign_type=RSA2×tamp=2024-10-04+09%3A44%3A12&alipay_sdk=alipay-sdk-java-4.38.157.ALL&format=json">
|
||||
<input type="hidden" name="biz_content" value="{"out_trade_no":"26674145122785","total_amount":"1.68","subject":"测试商品","product_code":"FAST_INSTANT_TRADE_PAY"}">
|
||||
<input type="submit" value="立即支付" style="display:none" >
|
||||
</form>
|
||||
<script>document.forms[0].submit();</script>
|
BIN
docs/dev-ops/nginx/html/images/keyboard-001.jpg
Normal file
BIN
docs/dev-ops/nginx/html/images/keyboard-001.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 950 KiB |
BIN
docs/dev-ops/nginx/html/images/placeholder.png
Normal file
BIN
docs/dev-ops/nginx/html/images/placeholder.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
123
docs/dev-ops/nginx/html/index.html
Normal file
123
docs/dev-ops/nginx/html/index.html
Normal 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>
|
||||
|
105
docs/dev-ops/nginx/html/login.html
Normal file
105
docs/dev-ops/nginx/html/login.html
Normal 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>
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -10,21 +10,21 @@ 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";
|
||||
private String charset = "utf-8";
|
||||
// 传输格式
|
||||
private String format = "json";
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user