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.AlipayClient;
|
||||||
import com.alipay.api.DefaultAlipayClient;
|
import com.alipay.api.DefaultAlipayClient;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
@ -12,12 +11,12 @@ public class AliPayConfig {
|
|||||||
@Bean("alipayClient")
|
@Bean("alipayClient")
|
||||||
public AlipayClient alipayClient(AliPayConfigProperties properties) {
|
public AlipayClient alipayClient(AliPayConfigProperties properties) {
|
||||||
return new DefaultAlipayClient(properties.getGatewayUrl(),
|
return new DefaultAlipayClient(properties.getGatewayUrl(),
|
||||||
properties.getApp_id(),
|
properties.getAppId(),
|
||||||
properties.getMerchant_private_key(),
|
properties.getMerchantPrivateKey(),
|
||||||
properties.getFormat(),
|
properties.getFormat(),
|
||||||
properties.getCharset(),
|
properties.getCharset(),
|
||||||
properties.getAlipay_public_key(),
|
properties.getAlipayPublicKey(),
|
||||||
properties.getSign_type());
|
properties.getSignType());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -10,21 +10,21 @@ import org.springframework.stereotype.Component;
|
|||||||
public class AliPayConfigProperties {
|
public class AliPayConfigProperties {
|
||||||
|
|
||||||
// 「沙箱环境」应用ID - 您的APPID,收款账号既是你的APPID对应支付宝账号。获取地址;https://open.alipay.com/develop/sandbox/app
|
// 「沙箱环境」应用ID - 您的APPID,收款账号既是你的APPID对应支付宝账号。获取地址;https://open.alipay.com/develop/sandbox/app
|
||||||
private String app_id;
|
private String appId;
|
||||||
// 「沙箱环境」商户私钥,你的PKCS8格式RSA2私钥
|
// 「沙箱环境」商户私钥,你的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这类自定义参数,必须外网可以正常访问
|
// 「沙箱环境」页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
|
||||||
private String return_url;
|
private String returnUrl;
|
||||||
// 「沙箱环境」
|
// 「沙箱环境」
|
||||||
private String gatewayUrl;
|
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";
|
private String format = "json";
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ alipay:
|
|||||||
alipay_public_key: ${paymall.alipay.alipay-public-key}
|
alipay_public_key: ${paymall.alipay.alipay-public-key}
|
||||||
notify_url: ${paymall.alipay.notify-url}
|
notify_url: ${paymall.alipay.notify-url}
|
||||||
return_url: ${paymall.alipay.return-url}
|
return_url: ${paymall.alipay.return-url}
|
||||||
gateway-url: ${paymall.alipay.gateway-url}
|
gateway_url: ${paymall.alipay.gateway-url}
|
||||||
|
|
||||||
# 日志
|
# 日志
|
||||||
logging:
|
logging:
|
||||||
|
@ -33,24 +33,24 @@ public class AliPayTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void init() {
|
public void init() {
|
||||||
log.info(config.getNotify_url());
|
log.info(config.getNotifyUrl());
|
||||||
// ④ 用属性里的值来构造 AlipayClient
|
// ④ 用属性里的值来构造 AlipayClient
|
||||||
this.alipayClient = new DefaultAlipayClient(
|
this.alipayClient = new DefaultAlipayClient(
|
||||||
config.getGatewayUrl(),
|
config.getGatewayUrl(),
|
||||||
config.getApp_id(),
|
config.getAppId(),
|
||||||
config.getMerchant_private_key(),
|
config.getMerchantPrivateKey(),
|
||||||
config.getFormat(),
|
config.getFormat(),
|
||||||
config.getCharset(),
|
config.getCharset(),
|
||||||
config.getAlipay_public_key(),
|
config.getAlipayPublicKey(),
|
||||||
config.getSign_type()
|
config.getSignType()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test_aliPay_pageExecute() throws AlipayApiException {
|
public void test_aliPay_pageExecute() throws AlipayApiException {
|
||||||
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest(); // 发送请求的 Request类
|
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest(); // 发送请求的 Request类
|
||||||
request.setNotifyUrl(config.getNotify_url());
|
request.setNotifyUrl(config.getNotifyUrl());
|
||||||
request.setReturnUrl(config.getReturn_url());
|
request.setReturnUrl(config.getReturnUrl());
|
||||||
|
|
||||||
JSONObject bizContent = new JSONObject();
|
JSONObject bizContent = new JSONObject();
|
||||||
bizContent.put("out_trade_no", "smile000091004001"); // 我们自己生成的订单编号
|
bizContent.put("out_trade_no", "smile000091004001"); // 我们自己生成的订单编号
|
||||||
@ -79,7 +79,7 @@ public class AliPayTest {
|
|||||||
public void test_alipay_certificateExecute() throws AlipayApiException {
|
public void test_alipay_certificateExecute() throws AlipayApiException {
|
||||||
|
|
||||||
AlipayTradeQueryModel bizModel = new AlipayTradeQueryModel();
|
AlipayTradeQueryModel bizModel = new AlipayTradeQueryModel();
|
||||||
bizModel.setOutTradeNo("daniel82AAAA000032333361Y001");
|
bizModel.setOutTradeNo("smile000091004001");
|
||||||
|
|
||||||
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
|
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
|
||||||
request.setBizModel(bizModel);
|
request.setBizModel(bizModel);
|
||||||
|
@ -4,6 +4,7 @@ import com.alipay.api.domain.AlipayTradeQueryModel;
|
|||||||
import com.alipay.api.request.AlipayTradeQueryRequest;
|
import com.alipay.api.request.AlipayTradeQueryRequest;
|
||||||
import com.alipay.api.response.AlipayTradeQueryResponse;
|
import com.alipay.api.response.AlipayTradeQueryResponse;
|
||||||
import edu.whut.domain.order.service.IOrderService;
|
import edu.whut.domain.order.service.IOrderService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@ -16,12 +17,12 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Component()
|
@Component()
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class NoPayNotifyOrderJob {
|
public class NoPayNotifyOrderJob {
|
||||||
|
|
||||||
@Resource
|
private final IOrderService orderService;
|
||||||
private IOrderService orderService;
|
|
||||||
@Resource
|
private final AlipayClient alipayClient;
|
||||||
private AlipayClient alipayClient;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 每3秒执行一次,扫描超过1分钟未收到回调的待支付订单
|
* 每3秒执行一次,扫描超过1分钟未收到回调的待支付订单
|
||||||
@ -29,7 +30,7 @@ public class NoPayNotifyOrderJob {
|
|||||||
@Scheduled(cron = "0/3 * * * * ?")
|
@Scheduled(cron = "0/3 * * * * ?")
|
||||||
public void exec() {
|
public void exec() {
|
||||||
try {
|
try {
|
||||||
log.info("任务;检测未接收到或未正确处理的支付回调通知");
|
log.info("任务:检测未接收到或未正确处理的支付回调通知");
|
||||||
List<String> orderIds = orderService.queryNoPayNotifyOrder();
|
List<String> orderIds = orderService.queryNoPayNotifyOrder();
|
||||||
if (null == orderIds || orderIds.isEmpty()) return;
|
if (null == orderIds || orderIds.isEmpty()) return;
|
||||||
|
|
||||||
@ -46,10 +47,15 @@ public class NoPayNotifyOrderJob {
|
|||||||
// 如果支付宝返回业务成功码(10000),则更新订单为支付成功
|
// 如果支付宝返回业务成功码(10000),则更新订单为支付成功
|
||||||
if ("10000".equals(code)) {
|
if ("10000".equals(code)) {
|
||||||
orderService.changeOrderPaySuccess(orderId);
|
orderService.changeOrderPaySuccess(orderId);
|
||||||
|
}else {
|
||||||
|
log.warn("订单[{}]支付宝查询未成功:{}/{}",
|
||||||
|
orderId,
|
||||||
|
alipayTradeQueryResponse.getSubCode(),
|
||||||
|
alipayTradeQueryResponse.getSubMsg());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("检测未接收到或未正确处理的支付回调通知失败", e);
|
log.error("任务:检测未接收到或未正确处理的支付回调通知 失败", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user