移除PayPal支付功能,仅保留支付宝支付
- 删除PayPalService.java和PayPalController.java - 从PaymentMethod枚举中移除PAYPAL选项 - 移除PaymentController和PaymentApiController中的PayPal相关代码 - 移除前端PayPal支付选项和相关API - 清理配置文件中的PayPal配置 - 修复OrderController中的PayPal引用错误
This commit is contained in:
@@ -211,3 +211,4 @@ ngrok http 8080
|
||||
- IJPay文档:https://github.com/Javen205/IJPay
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -272,3 +272,4 @@ if (result.success) {
|
||||
安全和用户体验都得到了提升!
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -292,3 +292,4 @@ grep "img2vid_abc123def456" logs/application.log
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -293,3 +293,4 @@ public TaskQueue addTextToVideoTask(String username, String taskId) {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -36,5 +36,6 @@ public class PasswordChecker {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -284,3 +284,4 @@ ResourceNotFound.TemplateNotFound
|
||||
- 创建邮件模板并配置template-id
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -302,3 +302,4 @@ const startPolling = (taskId) => {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -172,3 +172,4 @@ const updateWork = async (workId, updateData) => {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -17,11 +17,6 @@ ALIPAY_PUBLIC_KEY=alipay_public_key
|
||||
ALIPAY_NOTIFY_URL=https://yourdomain.com/api/payments/alipay/notify
|
||||
ALIPAY_RETURN_URL=https://yourdomain.com/api/payments/alipay/return
|
||||
|
||||
# PayPal配置
|
||||
PAYPAL_CLIENT_ID=your_paypal_client_id
|
||||
PAYPAL_CLIENT_SECRET=your_paypal_client_secret
|
||||
PAYPAL_RETURN_URL=https://yourdomain.com/api/payments/paypal/return
|
||||
PAYPAL_CANCEL_URL=https://yourdomain.com/api/payments/paypal/cancel
|
||||
|
||||
# 日志配置
|
||||
LOG_FILE_PATH=./logs/application.log
|
||||
|
||||
@@ -436,5 +436,6 @@ MIT License
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -34,3 +34,4 @@ console.log('App.vue 加载成功')
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -47,14 +47,6 @@ export const handleAlipayCallback = (params) => {
|
||||
return api.post('/payments/alipay/callback', params)
|
||||
}
|
||||
|
||||
// PayPal支付API
|
||||
export const createPayPalPayment = (paymentData) => {
|
||||
return api.post(`/payments/paypal/create`, paymentData)
|
||||
}
|
||||
|
||||
export const handlePayPalCallback = (params) => {
|
||||
return api.post('/payment/paypal/callback', params)
|
||||
}
|
||||
|
||||
// 支付统计API
|
||||
export const getPaymentStats = () => {
|
||||
|
||||
@@ -60,3 +60,4 @@ export const getWorkStats = () => {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -95,5 +95,6 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -23,17 +23,6 @@
|
||||
</div>
|
||||
<span>Alipay扫码支付</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="payment-method"
|
||||
:class="{ active: selectedMethod === 'paypal' }"
|
||||
@click="selectMethod('paypal')"
|
||||
>
|
||||
<div class="method-icon paypal-icon">
|
||||
<el-icon><CreditCard /></el-icon>
|
||||
</div>
|
||||
<span>PayPal支付</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 金额显示 -->
|
||||
@@ -127,8 +116,8 @@ const handlePay = async () => {
|
||||
const paymentData = {
|
||||
orderId: props.orderId,
|
||||
amount: props.amount.toString(),
|
||||
method: selectedMethod.value.toUpperCase(),
|
||||
description: `${props.title} - ${selectedMethod.value === 'alipay' ? '支付宝' : 'PayPal'}支付`
|
||||
method: 'ALIPAY',
|
||||
description: `${props.title} - 支付宝支付`
|
||||
}
|
||||
|
||||
console.log('=== 开始支付流程 ===')
|
||||
@@ -139,52 +128,46 @@ const handlePay = async () => {
|
||||
const createResponse = await createPayment(paymentData)
|
||||
console.log('创建支付订单响应:', createResponse)
|
||||
|
||||
if (createResponse.data && createResponse.data.success) {
|
||||
if (createResponse.data && createResponse.data.success) {
|
||||
const paymentId = createResponse.data.data.id
|
||||
console.log('2. 支付订单创建成功,ID:', paymentId)
|
||||
|
||||
if (selectedMethod.value === 'alipay') {
|
||||
ElMessage.info('正在生成支付宝二维码...')
|
||||
ElMessage.info('正在生成支付宝二维码...')
|
||||
|
||||
console.log('3. 创建支付宝支付...')
|
||||
// 创建支付宝支付
|
||||
const alipayResponse = await createAlipayPayment({ paymentId })
|
||||
console.log('支付宝支付响应:', alipayResponse)
|
||||
console.log('支付宝支付响应数据:', alipayResponse.data)
|
||||
console.log('支付宝支付响应数据详情:', JSON.stringify(alipayResponse.data, null, 2))
|
||||
|
||||
if (alipayResponse.data && alipayResponse.data.success) {
|
||||
// 显示二维码
|
||||
const qrCode = alipayResponse.data.data.qrCode
|
||||
console.log('4. 支付宝二维码:', qrCode)
|
||||
|
||||
console.log('3. 创建支付宝支付...')
|
||||
// 创建支付宝支付
|
||||
const alipayResponse = await createAlipayPayment({ paymentId })
|
||||
console.log('支付宝支付响应:', alipayResponse)
|
||||
console.log('支付宝支付响应数据:', alipayResponse.data)
|
||||
console.log('支付宝支付响应数据详情:', JSON.stringify(alipayResponse.data, null, 2))
|
||||
|
||||
if (alipayResponse.data && alipayResponse.data.success) {
|
||||
// 显示二维码
|
||||
const qrCode = alipayResponse.data.data.qrCode
|
||||
console.log('4. 支付宝二维码:', qrCode)
|
||||
|
||||
// 更新二维码显示
|
||||
const qrCodeElement = document.querySelector('#qr-code-img')
|
||||
if (qrCodeElement) {
|
||||
qrCodeElement.src = `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(qrCode)}`
|
||||
qrCodeElement.style.display = 'block'
|
||||
console.log('5. 二维码图片已设置')
|
||||
}
|
||||
|
||||
// 隐藏模拟二维码
|
||||
const qrPlaceholder = document.querySelector('.qr-placeholder')
|
||||
if (qrPlaceholder) {
|
||||
qrPlaceholder.style.display = 'none'
|
||||
console.log('6. 模拟二维码已隐藏')
|
||||
}
|
||||
|
||||
ElMessage.success('二维码已生成,请使用支付宝扫码支付')
|
||||
console.log('=== 支付流程完成 ===')
|
||||
|
||||
} else {
|
||||
console.error('支付宝响应失败:', alipayResponse)
|
||||
ElMessage.error(alipayResponse.data?.message || '生成二维码失败')
|
||||
emit('pay-error', new Error(alipayResponse.data?.message || '生成二维码失败'))
|
||||
// 更新二维码显示
|
||||
const qrCodeElement = document.querySelector('#qr-code-img')
|
||||
if (qrCodeElement) {
|
||||
qrCodeElement.src = `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(qrCode)}`
|
||||
qrCodeElement.style.display = 'block'
|
||||
console.log('5. 二维码图片已设置')
|
||||
}
|
||||
|
||||
// 隐藏模拟二维码
|
||||
const qrPlaceholder = document.querySelector('.qr-placeholder')
|
||||
if (qrPlaceholder) {
|
||||
qrPlaceholder.style.display = 'none'
|
||||
console.log('6. 模拟二维码已隐藏')
|
||||
}
|
||||
|
||||
ElMessage.success('二维码已生成,请使用支付宝扫码支付')
|
||||
console.log('=== 支付流程完成 ===')
|
||||
|
||||
} else {
|
||||
// PayPal支付处理
|
||||
ElMessage.info('PayPal支付功能开发中...')
|
||||
emit('pay-error', new Error('PayPal支付功能暂未开放'))
|
||||
console.error('支付宝响应失败:', alipayResponse)
|
||||
ElMessage.error(alipayResponse.data?.message || '生成二维码失败')
|
||||
emit('pay-error', new Error(alipayResponse.data?.message || '生成二维码失败'))
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
@@ -49,18 +49,6 @@
|
||||
<el-icon><CreditCard /></el-icon>
|
||||
支付宝
|
||||
</el-radio>
|
||||
<el-radio value="PAYPAL">
|
||||
<el-icon><CreditCard /></el-icon>
|
||||
PayPal
|
||||
</el-radio>
|
||||
<el-radio value="WECHAT">
|
||||
<el-icon><CreditCard /></el-icon>
|
||||
微信支付
|
||||
</el-radio>
|
||||
<el-radio value="UNIONPAY">
|
||||
<el-icon><CreditCard /></el-icon>
|
||||
银联支付
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
@@ -103,30 +91,6 @@
|
||||
<p>支持支付宝扫码支付和网页支付</p>
|
||||
</div>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="24" :sm="12" :md="6">
|
||||
<div class="payment-method-info">
|
||||
<el-icon size="32" color="#0070BA"><CreditCard /></el-icon>
|
||||
<h5>PayPal</h5>
|
||||
<p>支持PayPal账户支付和信用卡支付</p>
|
||||
</div>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="24" :sm="12" :md="6">
|
||||
<div class="payment-method-info">
|
||||
<el-icon size="32" color="#07C160"><CreditCard /></el-icon>
|
||||
<h5>微信支付</h5>
|
||||
<p>支持微信扫码支付和H5支付</p>
|
||||
</div>
|
||||
</el-col>
|
||||
|
||||
<el-col :xs="24" :sm="12" :md="6">
|
||||
<div class="payment-method-info">
|
||||
<el-icon size="32" color="#E6A23C"><CreditCard /></el-icon>
|
||||
<h5>银联支付</h5>
|
||||
<p>支持银联卡支付和网银支付</p>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
@@ -19,12 +19,6 @@ public class PaymentConfig {
|
||||
return new AliPayConfig();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConfigurationProperties(prefix = "paypal")
|
||||
public PayPalConfig payPalConfig() {
|
||||
return new PayPalConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付宝配置
|
||||
*/
|
||||
@@ -64,34 +58,4 @@ public class PaymentConfig {
|
||||
public void setAliPayRootCertPath(String aliPayRootCertPath) { this.aliPayRootCertPath = aliPayRootCertPath; }
|
||||
}
|
||||
|
||||
/**
|
||||
* PayPal支付配置
|
||||
*/
|
||||
public static class PayPalConfig {
|
||||
private String clientId;
|
||||
private String clientSecret;
|
||||
private String mode;
|
||||
private String returnUrl;
|
||||
private String cancelUrl;
|
||||
private String domain;
|
||||
|
||||
// Getters and Setters
|
||||
public String getClientId() { return clientId; }
|
||||
public void setClientId(String clientId) { this.clientId = clientId; }
|
||||
|
||||
public String getClientSecret() { return clientSecret; }
|
||||
public void setClientSecret(String clientSecret) { this.clientSecret = clientSecret; }
|
||||
|
||||
public String getMode() { return mode; }
|
||||
public void setMode(String mode) { this.mode = mode; }
|
||||
|
||||
public String getReturnUrl() { return returnUrl; }
|
||||
public void setReturnUrl(String returnUrl) { this.returnUrl = returnUrl; }
|
||||
|
||||
public String getCancelUrl() { return cancelUrl; }
|
||||
public void setCancelUrl(String cancelUrl) { this.cancelUrl = cancelUrl; }
|
||||
|
||||
public String getDomain() { return domain; }
|
||||
public void setDomain(String domain) { this.domain = domain; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.example.demo.controller;
|
||||
|
||||
import com.example.demo.model.*;
|
||||
import com.example.demo.service.OrderService;
|
||||
import com.example.demo.service.PaymentService;
|
||||
import jakarta.validation.Valid;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -15,11 +15,24 @@ import org.springframework.security.core.Authentication;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Optional;
|
||||
import com.example.demo.model.Order;
|
||||
import com.example.demo.model.OrderItem;
|
||||
import com.example.demo.model.OrderStatus;
|
||||
import com.example.demo.model.OrderType;
|
||||
import com.example.demo.model.Payment;
|
||||
import com.example.demo.model.PaymentMethod;
|
||||
import com.example.demo.model.User;
|
||||
import com.example.demo.service.OrderService;
|
||||
import com.example.demo.service.PaymentService;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/orders")
|
||||
@@ -362,8 +375,6 @@ public class OrderController {
|
||||
// 根据支付方式跳转到相应的支付页面
|
||||
if (paymentMethod == PaymentMethod.ALIPAY) {
|
||||
return "redirect:/payment/alipay/create?paymentId=" + savedPayment.getId();
|
||||
} else if (paymentMethod == PaymentMethod.PAYPAL) {
|
||||
return "redirect:/payment/paypal/create?paymentId=" + savedPayment.getId();
|
||||
} else {
|
||||
model.addAttribute("error", "不支持的支付方式");
|
||||
return "redirect:/orders/" + id;
|
||||
|
||||
@@ -1,162 +0,0 @@
|
||||
package com.example.demo.controller;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* PayPal支付控制器
|
||||
* 基于IJPay实现
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/payments/paypal")
|
||||
public class PayPalController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(PayPalController.class);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 创建支付订单
|
||||
*/
|
||||
@PostMapping("/create-order")
|
||||
public ResponseEntity<Map<String, Object>> createOrder(@RequestParam String outTradeNo,
|
||||
@RequestParam String totalAmount,
|
||||
@RequestParam String subject,
|
||||
@RequestParam String body) {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
try {
|
||||
// TODO: 实现PayPal订单创建逻辑
|
||||
// 这里需要根据实际的PayPal API进行实现
|
||||
response.put("success", true);
|
||||
response.put("message", "PayPal订单创建功能待实现");
|
||||
response.put("outTradeNo", outTradeNo);
|
||||
response.put("totalAmount", totalAmount);
|
||||
response.put("subject", subject);
|
||||
logger.info("PayPal订单创建请求: outTradeNo={}, totalAmount={}", outTradeNo, totalAmount);
|
||||
} catch (Exception e) {
|
||||
logger.error("PayPal订单创建失败", e);
|
||||
response.put("success", false);
|
||||
response.put("message", "订单创建失败: " + e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 捕获支付
|
||||
*/
|
||||
@PostMapping("/capture")
|
||||
public ResponseEntity<Map<String, Object>> captureOrder(@RequestParam String orderId) {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
try {
|
||||
// TODO: 实现PayPal支付捕获逻辑
|
||||
response.put("success", true);
|
||||
response.put("message", "PayPal支付捕获功能待实现");
|
||||
response.put("orderId", orderId);
|
||||
logger.info("PayPal支付捕获请求: orderId={}", orderId);
|
||||
} catch (Exception e) {
|
||||
logger.error("PayPal支付捕获失败", e);
|
||||
response.put("success", false);
|
||||
response.put("message", "支付捕获失败: " + e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询订单
|
||||
*/
|
||||
@GetMapping("/query")
|
||||
public ResponseEntity<Map<String, Object>> queryOrder(@RequestParam String orderId) {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
try {
|
||||
// TODO: 实现PayPal订单查询逻辑
|
||||
response.put("success", true);
|
||||
response.put("message", "PayPal订单查询功能待实现");
|
||||
response.put("orderId", orderId);
|
||||
logger.info("PayPal订单查询请求: orderId={}", orderId);
|
||||
} catch (Exception e) {
|
||||
logger.error("PayPal订单查询失败", e);
|
||||
response.put("success", false);
|
||||
response.put("message", "订单查询失败: " + e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款
|
||||
*/
|
||||
@PostMapping("/refund")
|
||||
public ResponseEntity<Map<String, Object>> refund(@RequestParam String captureId,
|
||||
@RequestParam String refundAmount,
|
||||
@RequestParam String refundReason) {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
try {
|
||||
// TODO: 实现PayPal退款逻辑
|
||||
response.put("success", true);
|
||||
response.put("message", "PayPal退款功能待实现");
|
||||
response.put("captureId", captureId);
|
||||
response.put("refundAmount", refundAmount);
|
||||
logger.info("PayPal退款请求: captureId={}, amount={}", captureId, refundAmount);
|
||||
} catch (Exception e) {
|
||||
logger.error("PayPal退款失败", e);
|
||||
response.put("success", false);
|
||||
response.put("message", "退款失败: " + e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付成功回调
|
||||
*/
|
||||
@GetMapping("/return")
|
||||
public ResponseEntity<Map<String, Object>> returnUrl(HttpServletRequest request) {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
try {
|
||||
String token = request.getParameter("token");
|
||||
String payerId = request.getParameter("PayerID");
|
||||
|
||||
logger.info("PayPal支付成功回调: token={}, payerId={}", token, payerId);
|
||||
|
||||
response.put("success", true);
|
||||
response.put("message", "PayPal支付回调功能待实现");
|
||||
response.put("token", token);
|
||||
response.put("payerId", payerId);
|
||||
} catch (Exception e) {
|
||||
logger.error("PayPal支付回调处理失败", e);
|
||||
response.put("success", false);
|
||||
response.put("message", "支付处理失败: " + e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付取消回调
|
||||
*/
|
||||
@GetMapping("/cancel")
|
||||
public ResponseEntity<Map<String, Object>> cancelUrl(HttpServletRequest request) {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
try {
|
||||
String token = request.getParameter("token");
|
||||
logger.info("PayPal支付取消: token={}", token);
|
||||
|
||||
response.put("success", false);
|
||||
response.put("message", "PayPal支付取消功能待实现");
|
||||
response.put("token", token);
|
||||
} catch (Exception e) {
|
||||
logger.error("PayPal支付取消处理失败", e);
|
||||
response.put("success", false);
|
||||
response.put("message", "支付取消处理失败: " + e.getMessage());
|
||||
}
|
||||
return ResponseEntity.ok(response);
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,6 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import com.example.demo.model.Payment;
|
||||
import com.example.demo.model.PaymentStatus;
|
||||
import com.example.demo.service.AlipayService;
|
||||
import com.example.demo.service.PayPalService;
|
||||
import com.example.demo.service.PaymentService;
|
||||
|
||||
@RestController
|
||||
@@ -36,9 +35,6 @@ public class PaymentApiController {
|
||||
|
||||
@Autowired
|
||||
private AlipayService alipayService;
|
||||
|
||||
@Autowired
|
||||
private PayPalService payPalService;
|
||||
|
||||
|
||||
/**
|
||||
@@ -418,50 +414,6 @@ public class PaymentApiController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建PayPal支付
|
||||
*/
|
||||
@PostMapping("/paypal/create")
|
||||
public ResponseEntity<Map<String, Object>> createPayPalPayment(
|
||||
@RequestBody Map<String, Object> paymentData,
|
||||
Authentication authentication) {
|
||||
try {
|
||||
String username;
|
||||
if (authentication != null && authentication.isAuthenticated()) {
|
||||
username = authentication.getName();
|
||||
} else {
|
||||
return ResponseEntity.badRequest()
|
||||
.body(createErrorResponse("请先登录后再创建支付"));
|
||||
}
|
||||
|
||||
Long paymentId = Long.valueOf(paymentData.get("paymentId").toString());
|
||||
Payment payment = paymentService.findById(paymentId)
|
||||
.orElseThrow(() -> new RuntimeException("支付记录不存在"));
|
||||
|
||||
// 检查权限
|
||||
if (!payment.getUser().getUsername().equals(username)) {
|
||||
return ResponseEntity.status(403)
|
||||
.body(createErrorResponse("无权限操作此支付记录"));
|
||||
}
|
||||
|
||||
// 调用PayPal接口创建支付
|
||||
String paymentUrl = payPalService.createPayment(payment);
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", true);
|
||||
response.put("message", "PayPal支付创建成功");
|
||||
response.put("data", Map.of("paymentUrl", paymentUrl));
|
||||
|
||||
return ResponseEntity.ok(response);
|
||||
} catch (Exception e) {
|
||||
logger.error("创建PayPal支付失败", e);
|
||||
return ResponseEntity.badRequest()
|
||||
.body(createErrorResponse("创建PayPal支付失败: " + e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private Map<String, Object> createErrorResponse(String message) {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", false);
|
||||
|
||||
@@ -15,14 +15,12 @@ import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import com.example.demo.model.Payment;
|
||||
import com.example.demo.model.PaymentMethod;
|
||||
import com.example.demo.model.User;
|
||||
import com.example.demo.service.AlipayService;
|
||||
import com.example.demo.service.PayPalService;
|
||||
import com.example.demo.service.PaymentService;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
@@ -40,9 +38,6 @@ public class PaymentController {
|
||||
@Autowired
|
||||
private AlipayService alipayService;
|
||||
|
||||
@Autowired
|
||||
private PayPalService payPalService;
|
||||
|
||||
/**
|
||||
* 显示支付页面
|
||||
*/
|
||||
@@ -78,7 +73,6 @@ public class PaymentController {
|
||||
}
|
||||
|
||||
// 根据支付方式创建支付
|
||||
String redirectUrl;
|
||||
if (payment.getPaymentMethod() == PaymentMethod.ALIPAY) {
|
||||
Map<String, Object> paymentResult = alipayService.createPayment(payment);
|
||||
if (paymentResult.containsKey("qrCode")) {
|
||||
@@ -86,9 +80,6 @@ public class PaymentController {
|
||||
return "redirect:/payment/qr?qrCode=" + paymentResult.get("qrCode");
|
||||
}
|
||||
return "redirect:/payment/error";
|
||||
} else if (payment.getPaymentMethod() == PaymentMethod.PAYPAL) {
|
||||
redirectUrl = payPalService.createPayment(payment);
|
||||
return "redirect:" + redirectUrl;
|
||||
} else {
|
||||
model.addAttribute("error", "不支持的支付方式");
|
||||
model.addAttribute("paymentMethods", PaymentMethod.values());
|
||||
@@ -158,65 +149,6 @@ public class PaymentController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PayPal支付返回
|
||||
*/
|
||||
@GetMapping("/paypal/return")
|
||||
public String paypalReturn(@RequestParam("paymentId") String paymentId,
|
||||
@RequestParam("PayerID") String payerId,
|
||||
Model model) {
|
||||
try {
|
||||
boolean success = payPalService.executePayment(paymentId, payerId);
|
||||
|
||||
if (success) {
|
||||
Payment payment = paymentService.findByExternalTransactionId(paymentId)
|
||||
.orElseThrow(() -> new RuntimeException("支付记录不存在"));
|
||||
model.addAttribute("payment", payment);
|
||||
model.addAttribute("success", true);
|
||||
return "payment/result";
|
||||
} else {
|
||||
model.addAttribute("error", "支付执行失败");
|
||||
return "payment/result";
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("处理PayPal支付返回失败:", e);
|
||||
model.addAttribute("error", "支付处理失败:" + e.getMessage());
|
||||
return "payment/result";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PayPal支付取消
|
||||
*/
|
||||
@GetMapping("/paypal/cancel")
|
||||
public String paypalCancel(Model model) {
|
||||
model.addAttribute("error", "支付已取消");
|
||||
return "payment/result";
|
||||
}
|
||||
|
||||
/**
|
||||
* PayPal Webhook通知
|
||||
*/
|
||||
@PostMapping("/paypal/webhook")
|
||||
@ResponseBody
|
||||
public String paypalWebhook(HttpServletRequest request) {
|
||||
try {
|
||||
Map<String, String> params = request.getParameterMap().entrySet().stream()
|
||||
.collect(java.util.stream.Collectors.toMap(
|
||||
Map.Entry::getKey,
|
||||
entry -> entry.getValue()[0]
|
||||
));
|
||||
|
||||
boolean success = payPalService.handleWebhook(params);
|
||||
return success ? "success" : "fail";
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("处理PayPal Webhook失败:", e);
|
||||
return "fail";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付记录列表
|
||||
*/
|
||||
|
||||
@@ -67,3 +67,4 @@ public class MailMessage {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
package com.example.demo.model;
|
||||
|
||||
public enum PaymentMethod {
|
||||
ALIPAY("支付宝"),
|
||||
PAYPAL("PayPal");
|
||||
ALIPAY("支付宝");
|
||||
|
||||
private final String displayName;
|
||||
|
||||
|
||||
@@ -201,3 +201,4 @@ public class PointsFreezeRecord {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -269,3 +269,4 @@ public class TaskQueue {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -261,3 +261,4 @@ public class TaskStatus {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -69,3 +69,4 @@ public interface TaskStatusRepository extends JpaRepository<TaskStatus, Long> {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -38,5 +38,6 @@ public class PlainTextPasswordEncoder implements PasswordEncoder {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,202 +0,0 @@
|
||||
package com.example.demo.service;
|
||||
|
||||
import com.example.demo.model.Payment;
|
||||
import com.example.demo.model.PaymentMethod;
|
||||
import com.example.demo.model.PaymentStatus;
|
||||
import com.example.demo.repository.PaymentRepository;
|
||||
import com.paypal.api.payments.*;
|
||||
import com.paypal.base.rest.APIContext;
|
||||
import com.paypal.base.rest.PayPalRESTException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
public class PayPalService {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(PayPalService.class);
|
||||
|
||||
private final PaymentRepository paymentRepository;
|
||||
|
||||
@Value("${paypal.client-id}")
|
||||
private String clientId;
|
||||
|
||||
@Value("${paypal.client-secret}")
|
||||
private String clientSecret;
|
||||
|
||||
@Value("${paypal.mode}")
|
||||
private String mode;
|
||||
|
||||
@Value("${paypal.return-url}")
|
||||
private String returnUrl;
|
||||
|
||||
@Value("${paypal.cancel-url}")
|
||||
private String cancelUrl;
|
||||
|
||||
public PayPalService(PaymentRepository paymentRepository) {
|
||||
this.paymentRepository = paymentRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建PayPal支付订单
|
||||
*/
|
||||
public String createPayment(Payment payment) {
|
||||
try {
|
||||
// 设置支付状态
|
||||
payment.setStatus(PaymentStatus.PENDING);
|
||||
payment.setPaymentMethod(PaymentMethod.PAYPAL);
|
||||
payment.setOrderId(generateOrderId());
|
||||
payment.setReturnUrl(returnUrl);
|
||||
|
||||
// 保存支付记录
|
||||
paymentRepository.save(payment);
|
||||
|
||||
// 创建API上下文
|
||||
APIContext apiContext = new APIContext(clientId, clientSecret, mode);
|
||||
|
||||
// 创建支付金额
|
||||
Amount amount = new Amount();
|
||||
amount.setCurrency(payment.getCurrency());
|
||||
amount.setTotal(payment.getAmount().toString());
|
||||
|
||||
// 创建交易
|
||||
Transaction transaction = new Transaction();
|
||||
transaction.setAmount(amount);
|
||||
transaction.setDescription(payment.getDescription() != null ? payment.getDescription() : "商品支付");
|
||||
|
||||
// 创建交易列表
|
||||
List<Transaction> transactions = new ArrayList<>();
|
||||
transactions.add(transaction);
|
||||
|
||||
// 创建支付者
|
||||
Payer payer = new Payer();
|
||||
payer.setPaymentMethod("paypal");
|
||||
|
||||
// 创建支付
|
||||
com.paypal.api.payments.Payment paypalPayment = new com.paypal.api.payments.Payment();
|
||||
paypalPayment.setIntent("sale");
|
||||
paypalPayment.setPayer(payer);
|
||||
paypalPayment.setTransactions(transactions);
|
||||
|
||||
// 设置重定向URL
|
||||
RedirectUrls redirectUrls = new RedirectUrls();
|
||||
redirectUrls.setReturnUrl(returnUrl + "?paymentId={PAY_ID}&PayerID={PAYER_ID}");
|
||||
redirectUrls.setCancelUrl(cancelUrl);
|
||||
paypalPayment.setRedirectUrls(redirectUrls);
|
||||
|
||||
// 创建支付
|
||||
com.paypal.api.payments.Payment createdPayment = paypalPayment.create(apiContext);
|
||||
|
||||
// 更新支付记录
|
||||
payment.setExternalTransactionId(createdPayment.getId());
|
||||
paymentRepository.save(payment);
|
||||
|
||||
logger.info("PayPal支付订单创建成功,订单号:{},PayPal ID:{}",
|
||||
payment.getOrderId(), createdPayment.getId());
|
||||
|
||||
// 获取批准URL
|
||||
for (Links link : createdPayment.getLinks()) {
|
||||
if ("approval_url".equals(link.getRel())) {
|
||||
return link.getHref();
|
||||
}
|
||||
}
|
||||
|
||||
throw new RuntimeException("未找到PayPal批准URL");
|
||||
|
||||
} catch (PayPalRESTException e) {
|
||||
logger.error("PayPal API调用异常:", e);
|
||||
payment.setStatus(PaymentStatus.FAILED);
|
||||
paymentRepository.save(payment);
|
||||
throw new RuntimeException("PayPal支付服务异常:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行PayPal支付
|
||||
*/
|
||||
public boolean executePayment(String paymentId, String payerId) {
|
||||
try {
|
||||
// 创建API上下文
|
||||
APIContext apiContext = new APIContext(clientId, clientSecret, mode);
|
||||
|
||||
// 创建支付执行
|
||||
PaymentExecution paymentExecution = new PaymentExecution();
|
||||
paymentExecution.setPayerId(payerId);
|
||||
|
||||
// 获取支付信息
|
||||
com.paypal.api.payments.Payment payment = com.paypal.api.payments.Payment.get(apiContext, paymentId);
|
||||
|
||||
// 执行支付
|
||||
com.paypal.api.payments.Payment executedPayment = payment.execute(apiContext, paymentExecution);
|
||||
|
||||
// 查找支付记录
|
||||
Payment paymentRecord = paymentRepository.findByExternalTransactionId(paymentId)
|
||||
.orElseThrow(() -> new RuntimeException("支付记录不存在:" + paymentId));
|
||||
|
||||
// 更新支付状态
|
||||
if ("approved".equals(executedPayment.getState())) {
|
||||
paymentRecord.setStatus(PaymentStatus.SUCCESS);
|
||||
paymentRecord.setPaidAt(LocalDateTime.now());
|
||||
logger.info("PayPal支付成功,订单号:{}", paymentRecord.getOrderId());
|
||||
} else {
|
||||
paymentRecord.setStatus(PaymentStatus.FAILED);
|
||||
logger.warn("PayPal支付失败,订单号:{},状态:{}",
|
||||
paymentRecord.getOrderId(), executedPayment.getState());
|
||||
}
|
||||
|
||||
paymentRepository.save(paymentRecord);
|
||||
return true;
|
||||
|
||||
} catch (PayPalRESTException e) {
|
||||
logger.error("PayPal支付执行异常:", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理PayPal Webhook通知
|
||||
*/
|
||||
public boolean handleWebhook(Map<String, String> params) {
|
||||
try {
|
||||
String eventType = params.get("event_type");
|
||||
String resourceType = params.get("resource_type");
|
||||
|
||||
logger.info("收到PayPal Webhook通知,事件类型:{},资源类型:{}", eventType, resourceType);
|
||||
|
||||
if ("PAYMENT.SALE.COMPLETED".equals(eventType) && "sale".equals(resourceType)) {
|
||||
String paymentId = params.get("resource.id");
|
||||
|
||||
// 查找支付记录
|
||||
Payment payment = paymentRepository.findByExternalTransactionId(paymentId)
|
||||
.orElseThrow(() -> new RuntimeException("支付记录不存在:" + paymentId));
|
||||
|
||||
// 更新支付状态
|
||||
payment.setStatus(PaymentStatus.SUCCESS);
|
||||
payment.setPaidAt(LocalDateTime.now());
|
||||
paymentRepository.save(payment);
|
||||
|
||||
logger.info("PayPal Webhook处理成功,订单号:{}", payment.getOrderId());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("处理PayPal Webhook异常:", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成订单号
|
||||
*/
|
||||
private String generateOrderId() {
|
||||
return "PP" + System.currentTimeMillis() + UUID.randomUUID().toString().substring(0, 8).toUpperCase();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,12 +38,6 @@ alipay.sign-type=RSA2
|
||||
alipay.notify-url=${ALIPAY_NOTIFY_URL}
|
||||
alipay.return-url=${ALIPAY_RETURN_URL}
|
||||
|
||||
# PayPal配置 (生产环境)
|
||||
paypal.client-id=${PAYPAL_CLIENT_ID}
|
||||
paypal.client-secret=${PAYPAL_CLIENT_SECRET}
|
||||
paypal.mode=live
|
||||
paypal.return-url=${PAYPAL_RETURN_URL}
|
||||
paypal.cancel-url=${PAYPAL_CANCEL_URL}
|
||||
|
||||
# JWT配置 - 使用环境变量
|
||||
jwt.secret=${JWT_SECRET}
|
||||
|
||||
@@ -28,3 +28,4 @@ CREATE TABLE IF NOT EXISTS task_queue (
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -27,3 +27,4 @@ CREATE TABLE IF NOT EXISTS points_freeze_records (
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -30,3 +30,4 @@ CREATE TABLE task_status (
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -574,5 +574,6 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -490,5 +490,6 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -529,5 +529,6 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -52,15 +52,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="card payment-card h-100" onclick="selectPaymentMethod('PAYPAL')">
|
||||
<div class="card-body text-center">
|
||||
<i class="fab fa-paypal payment-icon paypal-icon"></i>
|
||||
<h5 class="card-title">PayPal</h5>
|
||||
<p class="card-text">全球领先的在线支付</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
@@ -128,9 +119,6 @@
|
||||
if (method === 'ALIPAY') {
|
||||
currencySelect.value = 'CNY';
|
||||
currencySelect.options[0].selected = true;
|
||||
} else if (method === 'PAYPAL') {
|
||||
currencySelect.value = 'USD';
|
||||
currencySelect.options[1].selected = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,3 +31,4 @@ pause > nul
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -58,3 +58,4 @@ public class TestApiConnection {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -17,3 +17,4 @@ except Exception as e:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -25,3 +25,4 @@ else:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -61,3 +61,4 @@ if __name__ == "__main__":
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user