17 changed files with 530 additions and 3 deletions
@ -0,0 +1,29 @@ |
|||
package com.bnyer.img.constants; |
|||
|
|||
/** |
|||
* 用户会员vip支付常量 |
|||
* @author chengkun |
|||
* @date 2022/4/21 18:12 |
|||
*/ |
|||
public class UserVipOrderStatusConstant { |
|||
|
|||
/** |
|||
* 待支付 |
|||
*/ |
|||
public static final String UN_PAY = "0"; |
|||
|
|||
/** |
|||
* 已支付 |
|||
*/ |
|||
public static final String PAYED = "1"; |
|||
|
|||
/** |
|||
* 支付失败 |
|||
*/ |
|||
public static final String PAY_FAIL = "2"; |
|||
|
|||
/** |
|||
* 支付失败 |
|||
*/ |
|||
public static final String PAY_EXCEPTION = "3"; |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
package com.bnyer.img.constants; |
|||
|
|||
/** |
|||
* 用户会员vip常量 |
|||
* @author chengkun |
|||
* @date 2022/4/21 18:12 |
|||
*/ |
|||
public class UserVipTypeConstant { |
|||
|
|||
/** |
|||
* 月卡 |
|||
*/ |
|||
public static final String MONTH_CARD = "0"; |
|||
|
|||
/** |
|||
* 季卡 |
|||
*/ |
|||
public static final String SEASON_CARD = "1"; |
|||
|
|||
/** |
|||
* 年卡 |
|||
*/ |
|||
public static final String YEAR_CARD = "2"; |
|||
} |
|||
@ -0,0 +1,37 @@ |
|||
package com.bnyer.img.controller; |
|||
|
|||
import com.bnyer.common.core.utils.StringUtils; |
|||
import com.bnyer.common.core.web.controller.BaseController; |
|||
import com.bnyer.common.core.web.domain.AjaxResult; |
|||
import com.bnyer.img.service.AlipayService; |
|||
import io.swagger.annotations.Api; |
|||
import io.swagger.annotations.ApiOperation; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.web.bind.annotation.PostMapping; |
|||
import org.springframework.web.bind.annotation.RequestBody; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import org.springframework.web.bind.annotation.RestController; |
|||
|
|||
import javax.servlet.http.HttpServletRequest; |
|||
|
|||
@Api(value = "【图文平台】公共接口",tags = "【图文平台】公共接口") |
|||
@RestController |
|||
@RequestMapping("/img/common") |
|||
@Slf4j |
|||
public class CommonController extends BaseController { |
|||
|
|||
@Autowired |
|||
private AlipayService alipayService; |
|||
|
|||
//@RequiresPermissions("system:config:list")
|
|||
@ApiOperation(value = "支付宝回调通知") |
|||
@PostMapping("/alipayCallback") |
|||
public AjaxResult alipayCallback(@RequestBody HttpServletRequest request) { |
|||
String result = alipayService.alipayCallBack(request); |
|||
if (StringUtils.isNotBlank(result)){ |
|||
return AjaxResult.success(result); |
|||
} |
|||
return AjaxResult.error(); |
|||
} |
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
package com.bnyer.img.dto; |
|||
|
|||
import io.swagger.annotations.ApiModel; |
|||
import io.swagger.annotations.ApiModelProperty; |
|||
import lombok.AllArgsConstructor; |
|||
import lombok.Getter; |
|||
import lombok.NoArgsConstructor; |
|||
import lombok.Setter; |
|||
|
|||
import java.io.Serializable; |
|||
|
|||
|
|||
@Getter |
|||
@Setter |
|||
@NoArgsConstructor |
|||
@AllArgsConstructor |
|||
@ApiModel("支付宝支付参数接收类") |
|||
public class AlipayParamDto implements Serializable { |
|||
|
|||
@ApiModelProperty(value="商户订单号") |
|||
private String outTradeNo; |
|||
|
|||
@ApiModelProperty(value="订单名称") |
|||
private String subject; |
|||
|
|||
@ApiModelProperty(value="付款金额") |
|||
private String totalAmount; |
|||
|
|||
@ApiModelProperty(value="备注") |
|||
private String body; |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
package com.bnyer.img.dto; |
|||
|
|||
import io.swagger.annotations.ApiModel; |
|||
import io.swagger.annotations.ApiModelProperty; |
|||
import lombok.Getter; |
|||
import lombok.Setter; |
|||
|
|||
import javax.validation.constraints.NotBlank; |
|||
import javax.validation.constraints.NotNull; |
|||
import java.io.Serializable; |
|||
|
|||
|
|||
@Getter |
|||
@Setter |
|||
@ApiModel("用户会员vip支付接收类") |
|||
public class PayUserVipDto implements Serializable { |
|||
|
|||
@NotBlank(message = "手机号不能为空!") |
|||
@ApiModelProperty(value="手机号") |
|||
private String phone; |
|||
|
|||
@NotNull(message = "用户vipId不能为空!") |
|||
@ApiModelProperty(value="用户vip表id") |
|||
private Long userVipId; |
|||
|
|||
@NotBlank(message = "vip类型状态不能为空!") |
|||
@ApiModelProperty(value="vip类型状态(0->月卡;1->季卡;2->年卡)") |
|||
private String type; |
|||
|
|||
@NotBlank(message = "支付金额不能为空!") |
|||
@ApiModelProperty(value="支付金额") |
|||
private String price; |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
package com.bnyer.img.service; |
|||
|
|||
import com.bnyer.img.dto.AlipayParamDto; |
|||
|
|||
import javax.servlet.http.HttpServletRequest; |
|||
|
|||
/** |
|||
* @author chengkun |
|||
* @date 2022/8/30 16:42 |
|||
*/ |
|||
public interface AlipayService { |
|||
|
|||
/** |
|||
* 支付宝支付 |
|||
* @param params 支付参数 |
|||
* @return - |
|||
*/ |
|||
String aliPay(AlipayParamDto params); |
|||
|
|||
/** |
|||
* 支付宝回调 |
|||
* @param request 回调请求 |
|||
* @return - |
|||
*/ |
|||
String alipayCallBack(HttpServletRequest request); |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
package com.bnyer.img.service; |
|||
|
|||
import com.bnyer.img.domain.UserVipRecord; |
|||
import com.bnyer.img.dto.PayUserVipDto; |
|||
|
|||
public interface UserVipRecordService { |
|||
|
|||
|
|||
/** |
|||
* 下单并支付会员vip |
|||
* @param param 用户vip参数对象 |
|||
* @return - |
|||
*/ |
|||
boolean payUserVip(PayUserVipDto param); |
|||
} |
|||
@ -0,0 +1,95 @@ |
|||
package com.bnyer.img.service.impl; |
|||
|
|||
import com.alibaba.fastjson.JSON; |
|||
import com.alipay.api.AlipayApiException; |
|||
import com.alipay.api.AlipayClient; |
|||
import com.alipay.api.DefaultAlipayClient; |
|||
import com.alipay.api.internal.util.AlipaySignature; |
|||
import com.alipay.api.request.AlipayTradePagePayRequest; |
|||
import com.bnyer.img.config.AlipayConfig; |
|||
import com.bnyer.img.dto.AlipayParamDto; |
|||
import com.bnyer.img.service.AlipayService; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import javax.servlet.http.HttpServletRequest; |
|||
import java.util.HashMap; |
|||
import java.util.Iterator; |
|||
import java.util.Map; |
|||
|
|||
/** |
|||
* @author chengkun |
|||
* @date 2022/8/30 17:09 |
|||
*/ |
|||
@Service |
|||
@Slf4j |
|||
public class AlipayServiceImpl implements AlipayService { |
|||
|
|||
@Autowired |
|||
private AlipayConfig alipayConfig; |
|||
|
|||
@Override |
|||
public String aliPay(AlipayParamDto params) { |
|||
String result = null; |
|||
//1、获得初始化的AlipayClient
|
|||
AlipayClient client = new DefaultAlipayClient( |
|||
alipayConfig.getGatewayUrl(), |
|||
alipayConfig.getAppId(), |
|||
alipayConfig.getPrivateKey(), |
|||
alipayConfig.getCharset(), |
|||
alipayConfig.getPublicKey(), |
|||
alipayConfig.getSignType()); |
|||
//2、设置请求参数
|
|||
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest(); |
|||
//页面跳转同步通知页面路径
|
|||
request.setReturnUrl(alipayConfig.getReturnUrl()); |
|||
// 服务器异步通知页面路径
|
|||
request.setNotifyUrl(alipayConfig.getNotifyUrl()); |
|||
//封装参数
|
|||
request.setBizContent(JSON.toJSONString(client)); |
|||
try { |
|||
//3、请求支付宝进行付款,并获取支付结果
|
|||
result = client.pageExecute(request).getBody(); |
|||
} catch (AlipayApiException e) { |
|||
log.error("支付宝支付失败!错误原因为:", e); |
|||
return null; |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
@Override |
|||
public String alipayCallBack(HttpServletRequest request) { |
|||
Map<String, String> result = new HashMap<>(); |
|||
Map requestParams = request.getParameterMap(); |
|||
for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) { |
|||
String name = (String) iter.next(); |
|||
String[] values = (String[]) requestParams.get(name); |
|||
String valueStr = ""; |
|||
for (int i = 0; i < values.length; i++) { |
|||
valueStr = (i == values.length - 1) ? valueStr + values[i] |
|||
: valueStr + values[i] + ","; |
|||
} |
|||
//乱码解决,这段代码在出现乱码时使用。
|
|||
//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
|
|||
result.put(name, valueStr); |
|||
} |
|||
|
|||
String outTradeNo = result.get("out_trade_no"); |
|||
String appId = result.get("app_id"); |
|||
String sellerId = result.get("out_trade_no"); |
|||
String totalAmount = result.get("total_amount"); |
|||
log.info("outTradeNo=={},appId=={},sellerId=={},totalAmount=={}",outTradeNo,appId,sellerId,totalAmount); |
|||
try { |
|||
boolean flag = AlipaySignature.rsaCheckV1(result, alipayConfig.getPublicKey(), alipayConfig.getCharset(), alipayConfig.getSignType()); |
|||
if (flag) { |
|||
return "success"; |
|||
} else { |
|||
return "failure"; |
|||
} |
|||
} catch (AlipayApiException e) { |
|||
e.printStackTrace(); |
|||
return "failure"; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,98 @@ |
|||
package com.bnyer.img.service.impl; |
|||
|
|||
import cn.hutool.core.date.DateUtil; |
|||
import cn.hutool.core.util.IdUtil; |
|||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
|||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
|||
import com.bnyer.common.core.exception.ServiceException; |
|||
import com.bnyer.common.core.utils.DateUtils; |
|||
import com.bnyer.common.core.utils.StringUtils; |
|||
import com.bnyer.common.core.utils.uuid.IdUtils; |
|||
import com.bnyer.common.redis.service.RedissonService; |
|||
import com.bnyer.img.constants.RedisKeyConstant; |
|||
import com.bnyer.img.constants.UserVipOrderStatusConstant; |
|||
import com.bnyer.img.constants.UserVipTypeConstant; |
|||
import com.bnyer.img.domain.UserVip; |
|||
import com.bnyer.img.domain.UserVipRecord; |
|||
import com.bnyer.img.dto.PayUserVipDto; |
|||
import com.bnyer.img.dto.UserVipPageDto; |
|||
import com.bnyer.img.mapper.UserVipMapper; |
|||
import com.bnyer.img.mapper.UserVipRecordMapper; |
|||
import com.bnyer.img.service.UserVipRecordService; |
|||
import com.bnyer.img.service.UserVipService; |
|||
import com.bnyer.img.vo.UserVipVo; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.redisson.api.RLock; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Service; |
|||
import org.springframework.transaction.annotation.Transactional; |
|||
|
|||
import java.math.BigDecimal; |
|||
import java.time.LocalDateTime; |
|||
import java.util.Date; |
|||
import java.util.List; |
|||
import java.util.concurrent.TimeUnit; |
|||
|
|||
@Service |
|||
@Slf4j |
|||
public class UserVipServiceRecordImpl implements UserVipRecordService { |
|||
|
|||
@Autowired |
|||
private UserVipRecordMapper userVipRecordMapper; |
|||
|
|||
@Autowired |
|||
private RedissonService redissonService; |
|||
|
|||
|
|||
@Override |
|||
public boolean payUserVip(PayUserVipDto param) { |
|||
UserVipRecord userVipRecord = new UserVipRecord(); |
|||
//生成订单id
|
|||
userVipRecord.setOrderId(IdUtil.getSnowflakeNextIdStr()); |
|||
//获取分布式锁
|
|||
RLock lock = redissonService.getRLock(RedisKeyConstant.PAY_USER_VIP_LOCK_KEY + userVipRecord.getOrderId()); |
|||
try{ |
|||
if(lock.tryLock(500, 10000, TimeUnit.MILLISECONDS)){ |
|||
//调用支付
|
|||
|
|||
//保存订单
|
|||
userVipRecord.setCreateTime(new Date()); |
|||
userVipRecord.setUpdateTime(new Date()); |
|||
userVipRecord.setPrice(new BigDecimal(param.getPrice())); |
|||
userVipRecord.setStatus(UserVipOrderStatusConstant.UN_PAY); |
|||
userVipRecord.setIsShow("1"); |
|||
Date startTime = new Date(); |
|||
userVipRecord.setStartTime(startTime); |
|||
if(userVipRecord.getType().equals(UserVipTypeConstant.MONTH_CARD)){ |
|||
//计算月卡(30天)的结束时间
|
|||
userVipRecord.setEndTime(DateUtils.getDateAfter(startTime, 30)); |
|||
}else if(userVipRecord.getType().equals(UserVipTypeConstant.SEASON_CARD)){ |
|||
//结算季卡(90天)的结束时间
|
|||
userVipRecord.setEndTime(DateUtils.getDateAfter(startTime, 90)); |
|||
}else{ |
|||
//计算年卡(365天)的结束时间
|
|||
userVipRecord.setEndTime(DateUtils.getDateAfter(startTime, 365)); |
|||
} |
|||
}else{ |
|||
userVipRecord.setStatus(UserVipOrderStatusConstant.PAY_EXCEPTION); |
|||
log.error("用户会员vip支付异常,锁被占用!"); |
|||
throw new ServiceException("系统繁忙,请稍候重试!"); |
|||
} |
|||
}catch (Exception e){ |
|||
userVipRecord.setStatus(UserVipOrderStatusConstant.PAY_FAIL); |
|||
log.error("用户会员vip支付失败!错误原因为【{}】",e.getMessage()); |
|||
throw new ServiceException("系统繁忙,请勿重复操作!"); |
|||
}finally { |
|||
int insert = userVipRecordMapper.insert(userVipRecord); |
|||
if(insert > 0){ |
|||
return true; |
|||
} |
|||
//释放锁
|
|||
if(lock.isHeldByCurrentThread()){ |
|||
lock.unlock(); |
|||
log.info("用户会员vip支付操作执行完毕,释放锁成功!"); |
|||
} |
|||
} |
|||
return false; |
|||
} |
|||
} |
|||
Loading…
Reference in new issue