feat(payment): 支付功能调整和订单状态查询
parent
13d4e21691
commit
da69a15cb9
|
@ -74,13 +74,13 @@ public class AliPayController extends BaseController {
|
|||
String appId = "2021005114616085";
|
||||
String state = ShareCodeUtils.idToCode(SecurityUtils.getUserId()); // 防止CSRF攻击
|
||||
|
||||
String encodedRedirectUri = URLEncoder.encode("https://3195d9a3.r27.cpolar.top/ali/pay/callback", "UTF-8");
|
||||
String encodedRedirectUri = URLEncoder.encode("https://4b0ca615.r27.cpolar.top/ali/pay/callback", "UTF-8");
|
||||
String authUrl = String.format(
|
||||
"https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?app_id=%s&scope=%s&redirect_uri=%s&state=%s",
|
||||
appId, scope, encodedRedirectUri, state
|
||||
);
|
||||
|
||||
QrCodeUtil.generate(authUrl, 300, 300, "png", response.getOutputStream());
|
||||
// QrCodeUtil.generate(authUrl, 300, 300, "png", response.getOutputStream());
|
||||
return AjaxResult.success("成功", authUrl);
|
||||
}
|
||||
|
||||
|
@ -136,8 +136,10 @@ public class AliPayController extends BaseController {
|
|||
return AjaxResult.error("商品id不能为空");
|
||||
}
|
||||
payVo = aliPayService.memberPay(orderTradeDto);
|
||||
// QrCodeUtil.generate(payVo.getUrl(), 300, 300, "png", response.getOutputStream());
|
||||
} else if ("points".equalsIgnoreCase(type)) {
|
||||
payVo = aliPayService.pointsPay(orderTradeDto.getPaymentAmount());
|
||||
payVo = aliPayService.pointsPay(orderTradeDto.getAmount());
|
||||
// QrCodeUtil.generate(payVo.getUrl(), 300, 300, "png", response.getOutputStream());
|
||||
}
|
||||
|
||||
return AjaxResult.success(payVo);
|
||||
|
@ -198,10 +200,15 @@ public class AliPayController extends BaseController {
|
|||
// 验签通过
|
||||
|
||||
String code = params.get("out_trade_no"); // 商户订单号
|
||||
OrderTrade orderTrade = orderTradeService.lambdaQuery()
|
||||
.eq(OrderTrade::getCode, code)
|
||||
.one();
|
||||
if (orderTrade == null) {
|
||||
redisCache.deleteObject(code);
|
||||
return "failure";
|
||||
}
|
||||
// 获取订单后缀
|
||||
String suffix = code.substring(code.lastIndexOf("_") + 1);
|
||||
String orderTradeJson = redisCache.getCacheObject(code);
|
||||
OrderTrade orderTrade = JSONUtil.toBean(orderTradeJson, OrderTrade.class);
|
||||
|
||||
orderTradeService.orderHandler(orderTrade, suffix, params);
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import cn.hutool.core.util.RandomUtil;
|
|||
import cn.hutool.extra.qrcode.QrCodeUtil;
|
||||
import cn.hutool.json.JSON;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alipay.api.AlipayApiException;
|
||||
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
|
||||
import com.alipay.easysdk.base.oauth.models.AlipaySystemOauthTokenResponse;
|
||||
|
@ -36,10 +37,8 @@ import javax.validation.constraints.NotBlank;
|
|||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @Author:ChenYan
|
||||
|
@ -62,6 +61,12 @@ public class OrderTradeController extends BaseController {
|
|||
@Autowired
|
||||
private OrderTradeService orderTradeService;
|
||||
|
||||
@Autowired
|
||||
private AliPayService aliPayService;
|
||||
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
|
||||
/**
|
||||
* 查询列表
|
||||
*/
|
||||
|
@ -121,7 +126,14 @@ public class OrderTradeController extends BaseController {
|
|||
*/
|
||||
@GetMapping("/queryTradeStatus")
|
||||
@ApiOperation(value = "查询交易状态")
|
||||
public Object queryTradeStatus(@Valid @NotBlank(message = "订单号不能为空") String outTradeNo) throws Exception {
|
||||
public AjaxResult queryTradeStatus(@Valid @NotBlank(message = "订单号不能为空") String outTradeNo) throws Exception {
|
||||
return aliPayService.queryTradeStatus(outTradeNo);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@GetMapping("/getTradStatus")
|
||||
public Object getTradStatus(String outTradeNo) throws Exception {
|
||||
Factory.setOptions(config);
|
||||
AlipayTradeQueryResponse query = Factory.Payment.Common().query(outTradeNo);
|
||||
Map<String, Object> map = JSONUtils.jsonToMap(query.getHttpBody());
|
||||
|
@ -132,7 +144,6 @@ public class OrderTradeController extends BaseController {
|
|||
// TRADE_CLOSED(未付款交易超时关闭,或支付完成后全额退款)
|
||||
// TRADE_SUCCESS(交易支付成功)
|
||||
// TRADE_FINISHED(交易结束,不可退款)
|
||||
// 当 trade_status 等于 TRADE_SUCCESS 或 TRADE_FINISHED 时, 表示支付成功
|
||||
return map.get("alipay_trade_query_response");
|
||||
}
|
||||
|
||||
|
|
|
@ -128,7 +128,7 @@ mall:
|
|||
privateKey: MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCyhwMKnP7oBQ9qKhxke9AXN7ZNcniMnJFcWWFPfs3W6QqKBGFGFYQFyqfmnf2gM4nYtEbvit0CcmSrdniR3aZVb6s0A/KWqD5ejf+zjdnn5XH4GYsm/DXZoBqdAMWQUaQcVB1lC9az1rn13n9UHBJ+s+UAWtFjXMDd78dsE7enU3RjBffyvl/A+r6c0jnSHDNttSXyamxGX8ng8hK5XdCAusOfYpWnLY90sjlyz98snIfVPqAfD3KTP88gRF1KfWZniwMCR/OjCp6jm5d5dvOj8xyk7R1LfZ0CH/fXOcvpCe9JISS9DyzEzW5XpsnO5p8Mo8wFL6TKVBng+Ss0Tr0NAgMBAAECggEAPnaCl+oKPf/XPtvxBy9SxWzWug49I2V8boVPSNMjDfiHmXai2jSY9rXLPSM2JCEkL9ATqag6X6rKkjtnQBH/KpFho1dmP1QqTkb8mkQdY8ehsp6tUzyXUsdzyE8G0NHfy5Gan0ofGtkcQ2xPvIv95JromtErxcokKQLGEYhsj3xL+KVsUh5YedX/6sAiJ1KS5Zs82eh6bbCvUzuSPc4hjyfLSux5AnGBPnwEzWWJiA5z9zK17i8Cb7FnEeRmNvJw7VsXaCMFquZ6+bzlKdSuUqzqNhHMX8AivePTjj7pPHFW3FTh64E20yzl7CIwkScToXT3H7oaHRA1xGySmGNBuQKBgQDXFcg0b8L0A/Zril+4IwfckH1gpUbqlplzfozM/a/0rojQEdS+X7g4ypdPc47cwoLJx08/84L8ZPj49CImoGNdj5K9B2fY/E10SIJJqN5lb9NI4KINvGGM58NDSAl+GjT5mljkPI8jzQ1ACcy9DGV/KVScGHUWUpeLOK22AEcfWwKBgQDUfPFBHc2Bkuv3bRoNT+fnChMw5CI65wD74vR5GKyurh50DB3RZXwhRsAFd9NowINm9B2KAR0IrB+vh3EwfJaWDauh3ykZZtrAphSa11dJXvtathHTuQmXalZv5brh5mHie87yoxMn7vqDi0bwkNlb/b1wwokwc0oc3NSoNsFptwKBgCJhjPs00kkHSSCvodVhZCRRxHjqcoeVQzo/BGrQMow+SghYkVVNH7mUSNOeeTu4rAdtILHsTwfhbBr/i2X5RWjzRlWJFYSN8COiY5E6uTIlyfRgVAc2EbHgakoa/cl2jvlHPuZc99SVNoUCDAQ8Mw08ohXBoxXKZgcPLFVnffb5AoGBAJW5cDmk6WCrCRAwVVIaAtsek0U5CxGcImpakk8d3te7IwQ8YWph6yR7eOSheVrvg+ewjXvnqvCocC877brvnyAeg9isqYYXnn5uyEgPApdVkSFq94bLdIG30S5JnvR8ZG61NK5t0BqsXuL/6b2rIy2Zzrm8qfR02D0cMdBRvNljAoGBAMJG7/TqodrYPYyOZ4/IbbhAitBHWpHYJHSENnuxbQGAQuCt52Jp3eULR2r7uk3dUDuE8mB2QAEStuV/orfdxxRxJIYbEynJFGCa9O5LTevbM4MoNRfLCPPmFK5PJivlJcdrCyQKEmGSLLrVdb3H/Wzu0/4K/ZhwyrtBz4MRkuwD
|
||||
# 沙箱支付宝公钥
|
||||
publicKey: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgfv3CE8I87I5HHcMtK1RrPQZzLqYlXxRa96lIYkEyFsxdMcMSwnNJJf/mceZhMQnXQDkuEYTZPO/DJbmiZkBWbRZNfIJur5Af/wKZEmHahtEWlrdJdJ6fh7j11eeqbXBfo55H1dxPEQA/obfe85WrqoE0fa06XElgq5/RwsSKjZpnorbO8mMnDaRwxIOoRVHQlHgfkMtTHfP+Zw8Kv0tyJdWLxVDgtg0OoO8VnrDNGBwsxJDOvLjZBbp9NX3wiWQpfh4OBkN1KKfIA9yfBhS6N0bnWfr428Boz/qNhycdrG/MYGQDiG8hVt177fKvTVXRf/kdSIz3izN1GnzOUkadQIDAQAB
|
||||
notifyUrl: https://253d7236.r27.cpolar.top/ali/pay/notify
|
||||
notifyUrl: https://4b0ca615.r27.cpolar.top/ali/pay/notify
|
||||
# 沙箱支付宝网关
|
||||
gatewayUrl: https://openapi-sandbox.dl.alipaydev.com/gateway.do
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ public class OrderTradeDto {
|
|||
*/
|
||||
@ApiModelProperty(value = "支付金额", required = true)
|
||||
@NotNull(message = "支付金额不能为空")
|
||||
private Double paymentAmount;
|
||||
private Double amount;
|
||||
|
||||
/**
|
||||
* 订单类型 会员member 积分points
|
||||
|
|
|
@ -14,5 +14,8 @@ public interface AliPayService {
|
|||
|
||||
AjaxResult fetch(String outBizNo, String amount) throws AlipayApiException;
|
||||
|
||||
// 查询订单状态
|
||||
AjaxResult queryTradeStatus(String outTradeNo) throws Exception;
|
||||
|
||||
String balance() throws AlipayApiException;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ package com.mcwl.pay.service.impl;
|
|||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.DateField;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.lang.UUID;
|
||||
import cn.hutool.extra.mail.MailUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
|
@ -21,13 +23,17 @@ import com.alipay.api.response.AlipayFundAccountQueryResponse;
|
|||
import com.alipay.api.response.AlipayFundTransUniTransferResponse;
|
||||
import com.alipay.easysdk.factory.Factory;
|
||||
import com.alipay.easysdk.kernel.Config;
|
||||
import com.alipay.easysdk.payment.common.models.AlipayTradeCloseResponse;
|
||||
import com.alipay.easysdk.payment.common.models.AlipayTradeQueryResponse;
|
||||
import com.alipay.easysdk.payment.facetoface.models.AlipayTradePrecreateResponse;
|
||||
import com.mcwl.common.JSONUtils;
|
||||
import com.mcwl.common.core.domain.AjaxResult;
|
||||
import com.mcwl.common.core.domain.entity.SysUser;
|
||||
import com.mcwl.common.core.redis.RedisCache;
|
||||
import com.mcwl.common.exception.ServiceException;
|
||||
import com.mcwl.common.utils.SecurityUtils;
|
||||
import com.mcwl.common.utils.ShareCodeUtils;
|
||||
import com.mcwl.common.utils.StringUtils;
|
||||
import com.mcwl.memberCenter.domain.MemberLevel;
|
||||
import com.mcwl.memberCenter.service.MemberLevelService;
|
||||
import com.mcwl.pay.config.AliConfig;
|
||||
|
@ -47,10 +53,7 @@ import org.springframework.stereotype.Component;
|
|||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
|
@ -60,6 +63,9 @@ import java.util.concurrent.TimeUnit;
|
|||
@Slf4j
|
||||
public class AliPayServiceImpl implements AliPayService {
|
||||
|
||||
@Autowired
|
||||
private Config config;
|
||||
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
|
||||
|
@ -156,25 +162,24 @@ public class AliPayServiceImpl implements AliPayService {
|
|||
// 设置orderTrade信息
|
||||
OrderTrade tradeEntity = new OrderTrade();
|
||||
BeanUtil.copyProperties(orderTradeDto, tradeEntity);
|
||||
tradeEntity.setCode(UUID.randomUUID().toString(true).substring(0, 30));
|
||||
tradeEntity.setCode(UUID.randomUUID().toString(true).substring(0, 30) + "_member");
|
||||
tradeEntity.setUserId(SecurityUtils.getUserId());
|
||||
tradeEntity.setUserName(SecurityUtils.getUsername());
|
||||
tradeEntity.setProductId(productId);
|
||||
tradeEntity.setProductName(memberLevel.getMemberName());
|
||||
tradeEntity.setTotalAmount(orderTradeDto.getPaymentAmount());
|
||||
tradeEntity.setOrderStatus(3);
|
||||
tradeEntity.setPayStatus(2);
|
||||
tradeEntity.setTotalAmount(orderTradeDto.getAmount());
|
||||
tradeEntity.setOrderStatus(1);
|
||||
tradeEntity.setPayStatus(1);
|
||||
orderTradeService.save(tradeEntity);
|
||||
|
||||
//调用支付宝的接口
|
||||
AlipayTradePrecreateResponse payResponse = Factory.Payment.FaceToFace()
|
||||
// 设置过期时
|
||||
// 设置过期时间
|
||||
.preCreate(memberLevel.getMemberName(),
|
||||
tradeEntity.getCode() + "_member",
|
||||
orderTradeDto.getPaymentAmount().toString());
|
||||
tradeEntity.getCode(),
|
||||
orderTradeDto.getAmount().toString());
|
||||
// 缓存到redis
|
||||
redisCache.setCacheObject(tradeEntity.getCode() + "_member", JSONUtil.toJsonStr(tradeEntity), 3, TimeUnit.MINUTES);
|
||||
redisCache.setCacheObject(tradeEntity.getCode() + "_member" + "_promotionId", orderTradeDto.getPromotionId(), 3, TimeUnit.MINUTES);
|
||||
redisCache.setCacheObject(tradeEntity.getCode() + "_promotionId", orderTradeDto.getPromotionId());
|
||||
// AlipayTradePrecreateResponse payResponse = Factory.Payment.FaceToFace().preCreate("订单主题:Mac笔记本", "LS123qwe123", "19999");
|
||||
//参照官方文档响应示例,解析返回结果
|
||||
String httpBodyStr = payResponse.getHttpBody();
|
||||
|
@ -198,7 +203,7 @@ public class AliPayServiceImpl implements AliPayService {
|
|||
public PayVo pointsPay(Double paymentAmount) throws Exception {
|
||||
// 设置orderTrade信息
|
||||
OrderTrade tradeEntity = new OrderTrade();
|
||||
tradeEntity.setCode(UUID.randomUUID().toString(true).substring(0, 30));
|
||||
tradeEntity.setCode(UUID.randomUUID().toString(true).substring(0, 30) + "_points");
|
||||
tradeEntity.setUserId(SecurityUtils.getUserId());
|
||||
tradeEntity.setProductId(-1);
|
||||
tradeEntity.setProductName("积分充值");
|
||||
|
@ -206,14 +211,14 @@ public class AliPayServiceImpl implements AliPayService {
|
|||
tradeEntity.setTotalAmount(paymentAmount);
|
||||
tradeEntity.setOrderStatus(1);
|
||||
tradeEntity.setPayStatus(1);
|
||||
|
||||
orderTradeService.save(tradeEntity);
|
||||
//调用支付宝的接口
|
||||
AlipayTradePrecreateResponse payResponse = Factory.Payment.FaceToFace()
|
||||
.preCreate(tradeEntity.getProductName(),
|
||||
tradeEntity.getCode() + "_points",
|
||||
tradeEntity.getCode(),
|
||||
tradeEntity.getPaymentAmount().toString());
|
||||
// 缓存到redis
|
||||
redisCache.setCacheObject(tradeEntity.getCode() + "_points", JSONUtil.toJsonStr(tradeEntity), 3, TimeUnit.MINUTES);
|
||||
redisCache.setCacheObject(tradeEntity.getCode(), JSONUtil.toJsonStr(tradeEntity), 30, TimeUnit.SECONDS);
|
||||
//参照官方文档响应示例,解析返回结果
|
||||
String httpBodyStr = payResponse.getHttpBody();
|
||||
JSONObject jsonObject = JSONObject.parseObject(httpBodyStr);
|
||||
|
@ -310,6 +315,67 @@ public class AliPayServiceImpl implements AliPayService {
|
|||
throw new ServiceException("转账失败:" + response.getSubMsg());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaxResult queryTradeStatus(String outTradeNo) throws Exception {
|
||||
|
||||
// 查询redis中订单信息
|
||||
String orderTradeJson = redisCache.getCacheObject(outTradeNo);
|
||||
OrderTrade orderTrade = JSONUtil.toBean(orderTradeJson, OrderTrade.class);
|
||||
|
||||
// 如果redis中存在该订单, 则直接返回该订单的支付状态
|
||||
if (StringUtils.isNotBlank(orderTradeJson) && Objects.nonNull(orderTrade)) {
|
||||
return AjaxResult.success("查询成功", orderTrade.getPayStatus());
|
||||
}
|
||||
|
||||
// 查询支付宝订单
|
||||
orderTrade = orderTradeService.lambdaQuery()
|
||||
.eq(OrderTrade::getCode, outTradeNo)
|
||||
.one();
|
||||
|
||||
// 如果数据库中不存在该订单, 则返回订单不存在
|
||||
if (Objects.isNull(orderTrade)) {
|
||||
return AjaxResult.error("订单不存在");
|
||||
}
|
||||
|
||||
|
||||
if (orderTrade.getPayStatus() == 1) {
|
||||
// 查询支付宝订单
|
||||
Object tradStatus = this.getTradStatus(outTradeNo);
|
||||
String jsonString = JSONObject.toJSONString(tradStatus);
|
||||
JSONObject jsonObject = JSONObject.parseObject(jsonString);
|
||||
Object tradeStatus = jsonObject.get("trade_status");
|
||||
if (tradeStatus != null && tradeStatus.equals("TRADE_SUCCESS")) {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put("buyer_pay_amount", jsonObject.get("buyer_pay_amount").toString());
|
||||
params.put("out_trade_no", jsonObject.get("out_trade_no").toString());
|
||||
params.put("gmt_payment", jsonObject.get("send_pay_date").toString());
|
||||
params.put("total_amount", jsonObject.get("total_amount").toString());
|
||||
params.put("trade_no", jsonObject.get("trade_no").toString());
|
||||
String code = orderTrade.getCode();
|
||||
// 获取订单后缀
|
||||
String suffix = code.substring(code.lastIndexOf("_") + 1);
|
||||
orderTradeService.orderHandler(orderTrade, suffix, params);
|
||||
return AjaxResult.success("查询成功", orderTrade.getPayStatus());
|
||||
}
|
||||
long expire = redisCache.getExpire(outTradeNo);
|
||||
// expire 超过15分钟,则删除redis中订单信息
|
||||
if (expire > 900) {
|
||||
// 关闭交易
|
||||
AlipayTradeCloseResponse close = Factory.Payment.Common().close(outTradeNo);
|
||||
if (close.getCode().equals("10000")) {
|
||||
orderTrade.setOrderStatus(4);
|
||||
orderTradeService.updateById(orderTrade);
|
||||
redisCache.deleteObject(outTradeNo + "promotionId");
|
||||
}
|
||||
}
|
||||
return AjaxResult.success("查询成功", orderTrade.getPayStatus());
|
||||
}
|
||||
|
||||
redisCache.setCacheObject(outTradeNo, JSONUtil.toJsonStr(orderTrade), 5, TimeUnit.SECONDS);
|
||||
return AjaxResult.success("查询成功", orderTrade.getPayStatus());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String balance() throws AlipayApiException {
|
||||
// 初始化SDK
|
||||
|
@ -380,6 +446,20 @@ public class AliPayServiceImpl implements AliPayService {
|
|||
|
||||
}
|
||||
|
||||
private Object getTradStatus(String outTradeNo) throws Exception {
|
||||
Factory.setOptions(config);
|
||||
AlipayTradeQueryResponse query = Factory.Payment.Common().query(outTradeNo);
|
||||
Map<String, Object> map = JSONUtils.jsonToMap(query.getHttpBody());
|
||||
|
||||
// 返回交易结果, 是否交易成功需要根据该对象中的 trade_status 来确定
|
||||
// trade_status 的枚举值如下, 请见 https://opendocs.alipay.com/apis/api_1/alipay.trade.query
|
||||
// WAIT_BUYER_PAY(交易创建,等待买家付款)
|
||||
// TRADE_CLOSED(未付款交易超时关闭,或支付完成后全额退款)
|
||||
// TRADE_SUCCESS(交易支付成功)
|
||||
// TRADE_FINISHED(交易结束,不可退款)
|
||||
// 当 trade_status 等于 TRADE_SUCCESS 或 TRADE_FINISHED 时, 表示支付成功
|
||||
return map.get("alipay_trade_query_response");
|
||||
}
|
||||
|
||||
private void addLogAndUpdateUserWallet(SysUser sysUser, String amount) {
|
||||
BigDecimal wallet = new BigDecimal(sysUser.getWallet().toString());
|
||||
|
|
|
@ -133,6 +133,10 @@ public class OrderTradeServiceImpl extends ServiceImpl<OrderTradeMapper, OrderTr
|
|||
memberHandler(orderTrade, promotionId);
|
||||
}
|
||||
|
||||
// 删除redis缓存
|
||||
redisCache.deleteObject(orderTrade.getCode());
|
||||
redisCache.deleteObject(params.get("out_trade_no") + "promotionId");
|
||||
|
||||
}
|
||||
|
||||
private void pointsHandler(OrderTrade orderTrade, Map<String, String> params) {
|
||||
|
|
Loading…
Reference in New Issue