添加支付功能

pull/651/head
macro 2023-09-19 09:37:54 +08:00
parent 9b4343e436
commit b3bc051e79
13 changed files with 434 additions and 0 deletions

View File

@ -41,6 +41,13 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<!--支付宝支付Java SDK-->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>${alipay-sdk.version}</version>
</dependency>
</dependencies>
<build>

View File

@ -0,0 +1,21 @@
package com.macro.mall.portal.config;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @auther macrozheng
* @description
* @date 2023/9/8
* @github https://github.com/macrozheng
*/
@Configuration
public class AlipayClientConfig {
@Bean
public AlipayClient alipayClient(AlipayConfig config){
return new DefaultAlipayClient(config.getGatewayUrl(),config.getAppId(),config.getAppPrivateKey(), config.getFormat(),config.getCharset(),config.getAlipayPublicKey(),config.getSignType());
}
}

View File

@ -0,0 +1,57 @@
package com.macro.mall.portal.config;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @auther macrozheng
* @description
* @date 2023/9/8
* @github https://github.com/macrozheng
*/
@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "alipay")
public class AlipayConfig {
/**
*
*/
private String gatewayUrl;
/**
* ID
*/
private String appId;
/**
*
*/
private String appPrivateKey;
/**
*
*/
private String alipayPublicKey;
/**
*
* http://localhost:8060/#/pages/money/paySuccess
*/
private String returnUrl;
/**
* 访
* http://localhost:8085/alipay/notify
*/
private String notifyUrl;
/**
* JSON
*/
private String format = "JSON";
/**
* 使
*/
private String charset = "UTF-8";
/**
* 使
*/
private String signType = "RSA2";
}

View File

@ -0,0 +1,74 @@
package com.macro.mall.portal.controller;
import com.macro.mall.common.api.CommonResult;
import com.macro.mall.portal.config.AlipayConfig;
import com.macro.mall.portal.domain.AliPayParam;
import com.macro.mall.portal.service.AlipayService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* @auther macrozheng
* @description Controller
* @date 2023/9/8
* @github https://github.com/macrozheng
*/
@Controller
@Api(tags = "AlipayController")
@Tag(name = "AlipayController", description = "支付宝支付相关接口")
@RequestMapping("/alipay")
public class AlipayController {
@Autowired
private AlipayConfig alipayConfig;
@Autowired
private AlipayService alipayService;
@ApiOperation("支付宝电脑网站支付")
@RequestMapping(value = "/pay", method = RequestMethod.GET)
public void pay(AliPayParam aliPayParam, HttpServletResponse response) throws IOException {
response.setContentType("text/html;charset=" + alipayConfig.getCharset());
response.getWriter().write(alipayService.pay(aliPayParam));
response.getWriter().flush();
response.getWriter().close();
}
@ApiOperation("支付宝手机网站支付")
@RequestMapping(value = "/webPay", method = RequestMethod.GET)
public void webPay(AliPayParam aliPayParam, HttpServletResponse response) throws IOException {
response.setContentType("text/html;charset=" + alipayConfig.getCharset());
response.getWriter().write(alipayService.webPay(aliPayParam));
response.getWriter().flush();
response.getWriter().close();
}
@ApiOperation(value = "支付宝异步回调",notes = "必须为POST请求执行成功返回success执行失败返回failure")
@RequestMapping(value = "/notify", method = RequestMethod.POST)
public String notify(HttpServletRequest request){
Map<String, String> params = new HashMap<>();
Map<String, String[]> requestParams = request.getParameterMap();
for (String name : requestParams.keySet()) {
params.put(name, request.getParameter(name));
}
return alipayService.notify(params);
}
@ApiOperation(value = "支付宝统一收单线下交易查询",notes = "订单支付成功返回TRADE_SUCCESS")
@RequestMapping(value = "/query", method = RequestMethod.GET)
@ResponseBody
public CommonResult<String> query(String outTradeNo, String tradeNo){
return CommonResult.success(alipayService.query(outTradeNo,tradeNo));
}
}

View File

@ -0,0 +1,27 @@
package com.macro.mall.portal.domain;
import lombok.Data;
import java.math.BigDecimal;
/**
* @auther macrozheng
* @description
* @date 2023/9/8
* @github https://github.com/macrozheng
*/
@Data
public class AliPayParam {
/**
*
*/
private String outTradeNo;
/**
* ///
*/
private String subject;
/**
*
*/
private BigDecimal totalAmount;
}

View File

@ -0,0 +1,36 @@
package com.macro.mall.portal.service;
import com.macro.mall.portal.domain.AliPayParam;
import java.util.Map;
/**
* @auther macrozheng
* @description Service
* @date 2023/9/8
* @github https://github.com/macrozheng
*/
public interface AlipayService {
/**
*
*/
String pay(AliPayParam aliPayParam);
/**
*
*/
String notify(Map<String, String> params);
/**
* @param outTradeNo
* @param tradeNo
* @return
*/
String query(String outTradeNo, String tradeNo);
/**
*
*/
String webPay(AliPayParam aliPayParam);
}

View File

@ -67,4 +67,10 @@ public interface OmsPortalOrderService {
* ID
*/
void deleteOrder(Long orderId);
/**
* orderSn
*/
@Transactional
void paySuccessByOrderSn(String orderSn, Integer payType);
}

View File

@ -0,0 +1,160 @@
package com.macro.mall.portal.service.impl;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.macro.mall.mapper.OmsOrderMapper;
import com.macro.mall.portal.config.AlipayConfig;
import com.macro.mall.portal.domain.AliPayParam;
import com.macro.mall.portal.service.AlipayService;
import com.macro.mall.portal.service.OmsPortalOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* @auther macrozheng
* @description Service
* @date 2023/9/8
* @github https://github.com/macrozheng
*/
@Slf4j
@Service
public class AlipayServiceImpl implements AlipayService {
@Autowired
private AlipayConfig alipayConfig;
@Autowired
private AlipayClient alipayClient;
@Autowired
private OmsOrderMapper orderMapper;
@Autowired
private OmsPortalOrderService portalOrderService;
@Override
public String pay(AliPayParam aliPayParam) {
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
if(StrUtil.isNotEmpty(alipayConfig.getNotifyUrl())){
//异步接收地址,公网可访问
request.setNotifyUrl(alipayConfig.getNotifyUrl());
}
if(StrUtil.isNotEmpty(alipayConfig.getReturnUrl())){
//同步跳转地址
request.setReturnUrl(alipayConfig.getReturnUrl());
}
//******必传参数******
JSONObject bizContent = new JSONObject();
//商户订单号,商家自定义,保持唯一性
bizContent.put("out_trade_no", aliPayParam.getOutTradeNo());
//支付金额最小值0.01元
bizContent.put("total_amount", aliPayParam.getTotalAmount());
//订单标题,不可使用特殊符号
bizContent.put("subject", aliPayParam.getSubject());
//电脑网站支付场景固定传值FAST_INSTANT_TRADE_PAY
bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");
request.setBizContent(bizContent.toString());
String formHtml = null;
try {
formHtml = alipayClient.pageExecute(request).getBody();
} catch (AlipayApiException e) {
e.printStackTrace();
}
return formHtml;
}
@Override
public String notify(Map<String, String> params) {
String result = "failure";
boolean signVerified = false;
try {
//调用SDK验证签名
signVerified = AlipaySignature.rsaCheckV1(params, alipayConfig.getAlipayPublicKey(), alipayConfig.getCharset(), alipayConfig.getSignType());
} catch (AlipayApiException e) {
log.error("支付回调签名校验异常!",e);
e.printStackTrace();
}
if (signVerified) {
String tradeStatus = params.get("trade_status");
if("TRADE_SUCCESS".equals(tradeStatus)){
result = "success";
log.info("notify方法被调用了tradeStatus:{}",tradeStatus);
String outTradeNo = params.get("out_trade_no");
portalOrderService.paySuccessByOrderSn(outTradeNo,1);
}else{
log.warn("订单未支付成功trade_status:{}",tradeStatus);
}
} else {
log.warn("支付回调签名校验失败!");
}
return result;
}
@Override
public String query(String outTradeNo, String tradeNo) {
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
//******必传参数******
JSONObject bizContent = new JSONObject();
//设置查询参数out_trade_no和trade_no至少传一个
if(StrUtil.isNotEmpty(outTradeNo)){
bizContent.put("out_trade_no",outTradeNo);
}
if(StrUtil.isNotEmpty(tradeNo)){
bizContent.put("trade_no",tradeNo);
}
//交易结算信息: trade_settle_info
String[] queryOptions = {"trade_settle_info"};
bizContent.put("query_options", queryOptions);
request.setBizContent(bizContent.toString());
AlipayTradeQueryResponse response = null;
try {
response = alipayClient.execute(request);
} catch (AlipayApiException e) {
log.error("查询支付宝账单异常!",e);
}
if(response.isSuccess()){
log.info("查询支付宝账单成功!");
portalOrderService.paySuccessByOrderSn(outTradeNo,1);
} else {
log.error("查询支付宝账单失败!");
}
//交易状态WAIT_BUYER_PAY交易创建等待买家付款、TRADE_CLOSED未付款交易超时关闭或支付完成后全额退款、TRADE_SUCCESS交易支付成功、TRADE_FINISHED交易结束不可退款
return response.getTradeStatus();
}
@Override
public String webPay(AliPayParam aliPayParam) {
AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest ();
if(StrUtil.isNotEmpty(alipayConfig.getNotifyUrl())){
//异步接收地址,公网可访问
request.setNotifyUrl(alipayConfig.getNotifyUrl());
}
if(StrUtil.isNotEmpty(alipayConfig.getReturnUrl())){
//同步跳转地址
request.setReturnUrl(alipayConfig.getReturnUrl());
}
//******必传参数******
JSONObject bizContent = new JSONObject();
//商户订单号,商家自定义,保持唯一性
bizContent.put("out_trade_no", aliPayParam.getOutTradeNo());
//支付金额最小值0.01元
bizContent.put("total_amount", aliPayParam.getTotalAmount());
//订单标题,不可使用特殊符号
bizContent.put("subject", aliPayParam.getSubject());
//手机网站支付默认传值FAST_INSTANT_TRADE_PAY
bizContent.put("product_code", "QUICK_WAP_WAY");
request.setBizContent(bizContent.toString());
String formHtml = null;
try {
formHtml = alipayClient.pageExecute(request).getBody();
} catch (AlipayApiException e) {
e.printStackTrace();
}
return formHtml;
}
}

View File

@ -419,6 +419,20 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
}
}
@Override
public void paySuccessByOrderSn(String orderSn, Integer payType) {
OmsOrderExample example = new OmsOrderExample();
example.createCriteria()
.andOrderSnEqualTo(orderSn)
.andStatusEqualTo(0)
.andDeleteStatusEqualTo(0);
List<OmsOrder> orderList = orderMapper.selectByExample(example);
if(CollUtil.isNotEmpty(orderList)){
OmsOrder order = orderList.get(0);
paySuccess(order.getId(),payType);
}
}
/**
* 18:8+2+2+6id
*/

View File

@ -42,3 +42,11 @@ logstash:
host: localhost
enableInnerLog: false
alipay:
gatewayUrl: https://openapi-sandbox.dl.alipaydev.com/gateway.do
appId: your appId
alipayPublicKey: your alipayPublicKey
appPrivateKey: your appPrivateKey
returnUrl: http://localhost:8060/#/pages/money/paySuccess
notifyUrl:

View File

@ -50,3 +50,11 @@ logging:
logstash:
host: logstash
alipay:
gatewayUrl: https://openapi-sandbox.dl.alipaydev.com/gateway.do
appId: your appId
alipayPublicKey: your alipayPublicKey
appPrivateKey: your appPrivateKey
returnUrl: http://192.168.3.101:8060/#/pages/money/paySuccess
notifyUrl:

View File

@ -36,6 +36,7 @@ secure:
- /home/**
- /product/**
- /brand/**
- /alipay/**
# 自定义redis key
redis:

15
pom.xml
View File

@ -46,6 +46,7 @@
<spring-data-commons.version>2.7.5</spring-data-commons.version>
<jjwt.version>0.9.1</jjwt.version>
<aliyun-oss.version>2.5.0</aliyun-oss.version>
<alipay-sdk.version>4.38.61.ALL</alipay-sdk.version>
<logstash-logback.version>7.2</logstash-logback.version>
<minio.version>8.4.5</minio.version>
<jaxb-api.version>2.3.1</jaxb-api.version>
@ -257,4 +258,18 @@
</pluginManagement>
</build>
<!--使用aliyun的Maven镜像源提升下载速度-->
<repositories>
<repository>
<id>aliyunmaven</id>
<name>aliyun</name>
<url>https://maven.aliyun.com/repository/public</url>
</repository>
<repository>
<id>central2</id>
<name>central2</name>
<url>https://repo1.maven.org/maven2/</url>
</repository>
</repositories>
</project>