订单模块调整与华为支付初始化
This commit is contained in:
parent
d0b1a07bdb
commit
3e251b4c48
@ -66,6 +66,13 @@
|
|||||||
<artifactId>sf-oauth</artifactId>
|
<artifactId>sf-oauth</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.smarterFramework</groupId>
|
||||||
|
<artifactId>sf-order</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
@ -0,0 +1,113 @@
|
|||||||
|
package com.sf.web.controller.system;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import com.sf.common.annotation.Log;
|
||||||
|
import com.sf.common.core.controller.BaseController;
|
||||||
|
import com.sf.common.core.domain.AjaxResult;
|
||||||
|
import com.sf.common.enums.BusinessType;
|
||||||
|
import com.sf.system.domain.UserMember;
|
||||||
|
import com.sf.system.service.IUserMemberService;
|
||||||
|
import com.sf.common.utils.poi.ExcelUtil;
|
||||||
|
import com.sf.common.core.page.TableDataInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会员Controller
|
||||||
|
*
|
||||||
|
* @author ztzh
|
||||||
|
* @date 2024-04-16
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/system/member")
|
||||||
|
public class UserMemberController extends BaseController
|
||||||
|
{
|
||||||
|
@Autowired
|
||||||
|
private IUserMemberService userMemberService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询会员列表
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('system:member:list')")
|
||||||
|
@GetMapping("/list")
|
||||||
|
public TableDataInfo list(UserMember userMember)
|
||||||
|
{
|
||||||
|
startPage();
|
||||||
|
List<UserMember> list = userMemberService.selectUserMemberList(userMember);
|
||||||
|
return getDataTable(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出会员列表
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('system:member:export')")
|
||||||
|
@Log(title = "会员", businessType = BusinessType.EXPORT)
|
||||||
|
@PostMapping("/export")
|
||||||
|
public void export(HttpServletResponse response, UserMember userMember)
|
||||||
|
{
|
||||||
|
List<UserMember> list = userMemberService.selectUserMemberList(userMember);
|
||||||
|
ExcelUtil<UserMember> util = new ExcelUtil<UserMember>(UserMember.class);
|
||||||
|
util.exportExcel(response, list, "会员数据");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取会员详细信息
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('system:member:query')")
|
||||||
|
@GetMapping(value = "/{id}")
|
||||||
|
public AjaxResult getInfo(@PathVariable("id") Long id)
|
||||||
|
{
|
||||||
|
return success(userMemberService.selectUserMemberById(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取会员详细信息,通过用户id
|
||||||
|
*/
|
||||||
|
@GetMapping(value = "/byUser")
|
||||||
|
public AjaxResult getInfoByUser(Long userId)
|
||||||
|
{
|
||||||
|
return success(userMemberService.selectUserMemberByUserId(userId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增会员
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('system:member:add')")
|
||||||
|
@Log(title = "会员", businessType = BusinessType.INSERT)
|
||||||
|
@PostMapping
|
||||||
|
public AjaxResult add(@RequestBody UserMember userMember)
|
||||||
|
{
|
||||||
|
return toAjax(userMemberService.insertUserMember(userMember));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改会员
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('system:member:edit')")
|
||||||
|
@Log(title = "会员", businessType = BusinessType.UPDATE)
|
||||||
|
@PutMapping
|
||||||
|
public AjaxResult edit(@RequestBody UserMember userMember)
|
||||||
|
{
|
||||||
|
return toAjax(userMemberService.updateUserMember(userMember));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除会员
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('system:member:remove')")
|
||||||
|
@Log(title = "会员", businessType = BusinessType.DELETE)
|
||||||
|
@DeleteMapping("/{ids}")
|
||||||
|
public AjaxResult remove(@PathVariable Long[] ids)
|
||||||
|
{
|
||||||
|
return toAjax(userMemberService.deleteUserMemberByIds(ids));
|
||||||
|
}
|
||||||
|
}
|
@ -72,6 +72,18 @@
|
|||||||
<groupId>com.smarterFramework</groupId>
|
<groupId>com.smarterFramework</groupId>
|
||||||
<artifactId>sf-common</artifactId>
|
<artifactId>sf-common</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- swagger3-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.springfox</groupId>
|
||||||
|
<artifactId>springfox-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 防止进入swagger页面报类型转换错误,排除3.0.0中的引用,手动增加1.6.2版本 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.swagger</groupId>
|
||||||
|
<artifactId>swagger-models</artifactId>
|
||||||
|
<version>1.6.2</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
33
sf-order/pom.xml
Normal file
33
sf-order/pom.xml
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>smarterFramework</artifactId>
|
||||||
|
<groupId>com.smarterFramework</groupId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>sf-order</artifactId>
|
||||||
|
|
||||||
|
<description>
|
||||||
|
订单模块
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<!-- 通用工具-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.smarterFramework</groupId>
|
||||||
|
<artifactId>sf-common</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.smarterFramework</groupId>
|
||||||
|
<artifactId>sf-framework</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
@ -13,7 +13,6 @@ import com.sf.order.domain.dto.OrderCreateDto;
|
|||||||
import com.sf.order.domain.req.OrderListReqVo;
|
import com.sf.order.domain.req.OrderListReqVo;
|
||||||
import com.sf.order.domain.res.OrderListResVo;
|
import com.sf.order.domain.res.OrderListResVo;
|
||||||
import com.sf.order.service.IOrderInfoService;
|
import com.sf.order.service.IOrderInfoService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@ -39,10 +38,7 @@ public class OrderInfoController extends BaseController {
|
|||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
public TableDataInfo list(OrderListReqVo vo) {
|
public TableDataInfo list(OrderListReqVo vo) {
|
||||||
startPage();
|
startPage();
|
||||||
SysUser user = SecurityUtils.getLoginUser().getUser();
|
|
||||||
vo.setUserId(user.getUserId());
|
|
||||||
List<OrderListResVo> list = orderInfoService.queryList(vo);
|
List<OrderListResVo> list = orderInfoService.queryList(vo);
|
||||||
logger.info("prderList"+list);
|
|
||||||
return getDataTable(list);
|
return getDataTable(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +68,7 @@ public class OrderInfoController extends BaseController {
|
|||||||
@Log(title = "创建订单基础信息", businessType = BusinessType.INSERT)
|
@Log(title = "创建订单基础信息", businessType = BusinessType.INSERT)
|
||||||
@PostMapping(value = "/createOrder")
|
@PostMapping(value = "/createOrder")
|
||||||
public AjaxResult createOrder(@RequestBody OrderCreateDto orderCreateDto) {
|
public AjaxResult createOrder(@RequestBody OrderCreateDto orderCreateDto) {
|
||||||
return toAjax(orderInfoService.createOrder(orderCreateDto));
|
return AjaxResult.success(orderInfoService.createOrder(orderCreateDto));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -87,7 +83,6 @@ public class OrderInfoController extends BaseController {
|
|||||||
/**
|
/**
|
||||||
* 支付订单
|
* 支付订单
|
||||||
*/
|
*/
|
||||||
@Operation(summary = "支付订单")
|
|
||||||
@PostMapping(value = "/pay/{orderId}")
|
@PostMapping(value = "/pay/{orderId}")
|
||||||
private String orderPay(@PathVariable(value = "orderId") Long orderId) {
|
private String orderPay(@PathVariable(value = "orderId") Long orderId) {
|
||||||
orderInfoService.orderPay(orderId);
|
orderInfoService.orderPay(orderId);
|
@ -26,16 +26,12 @@ public class OrderInfo extends BaseEntity {
|
|||||||
* 订单编号
|
* 订单编号
|
||||||
*/
|
*/
|
||||||
@Excel(name = "订单编号")
|
@Excel(name = "订单编号")
|
||||||
private Long orderNo;
|
private String orderNo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 订单状态:
|
* 订单状态: 0:待支付 1:已付款待发货 2:配送中 3:待取货 4:支付超时系统结束 5:客户自主取消 6:已完成
|
||||||
* 0:待支付
|
|
||||||
* 1:已付款
|
|
||||||
* 2:支付超时系统结束
|
|
||||||
* 3:已完成
|
|
||||||
*/
|
*/
|
||||||
@Excel(name = "订单状态: 0:待支付 1:已付款 2:支付超时系统结束 3:已完成 ")
|
@Excel(name = "订单状态: 0:待支付 1:已付款待发货 2:配送中 3:待取货 4:支付超时系统结束 5:客户自主取消 6:已完成 ")
|
||||||
private Long orderStatus;
|
private Long orderStatus;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -105,8 +101,8 @@ public class OrderInfo extends BaseEntity {
|
|||||||
/**
|
/**
|
||||||
* 支付时间
|
* 支付时间
|
||||||
*/
|
*/
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
@Excel(name = "支付时间", width = 30, dateFormat = "yyyy-MM-dd")
|
@Excel(name = "支付时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date payTime;
|
private Date payTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -145,7 +141,7 @@ public class OrderInfo extends BaseEntity {
|
|||||||
* 平台外部订单号
|
* 平台外部订单号
|
||||||
*/
|
*/
|
||||||
@Excel(name = "平台外部订单号")
|
@Excel(name = "平台外部订单号")
|
||||||
private Long outOrderNo;
|
private String outOrderNo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 平台支付返回值
|
* 平台支付返回值
|
||||||
@ -167,11 +163,11 @@ public class OrderInfo extends BaseEntity {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOrderNo(Long orderNo) {
|
public void setOrderNo(String orderNo) {
|
||||||
this.orderNo = orderNo;
|
this.orderNo = orderNo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getOrderNo() {
|
public String getOrderNo() {
|
||||||
return orderNo;
|
return orderNo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,11 +307,11 @@ public class OrderInfo extends BaseEntity {
|
|||||||
return orderType;
|
return orderType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOutOrderNo(Long outOrderNo) {
|
public void setOutOrderNo(String outOrderNo) {
|
||||||
this.outOrderNo = outOrderNo;
|
this.outOrderNo = outOrderNo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getOutOrderNo() {
|
public String getOutOrderNo() {
|
||||||
return outOrderNo;
|
return outOrderNo;
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
|||||||
package com.sf.order.domain.dto;
|
package com.sf.order.domain.dto;
|
||||||
|
|
||||||
|
import com.sf.common.annotation.Excel;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
@ -15,12 +16,13 @@ public class OrderCreateDto {
|
|||||||
@NotNull(message = "商品id不能为空")
|
@NotNull(message = "商品id不能为空")
|
||||||
private Long goodsId;
|
private Long goodsId;
|
||||||
|
|
||||||
|
@Schema(description = "平台外部订单号")
|
||||||
|
private String outOrderNo;
|
||||||
|
|
||||||
@Schema(description = "数量")
|
@Schema(description = "数量")
|
||||||
@NotNull(message = "数量不能唯恐")
|
|
||||||
private Long count;
|
private Long count;
|
||||||
|
|
||||||
@Schema(description = "金额")
|
@Schema(description = "金额")
|
||||||
@NotNull(message = "金额不能为空")
|
|
||||||
private Long amount;
|
private Long amount;
|
||||||
|
|
||||||
@Schema(description = "用户id")
|
@Schema(description = "用户id")
|
||||||
@ -56,4 +58,12 @@ public class OrderCreateDto {
|
|||||||
public void setUserId(Long userId) {
|
public void setUserId(Long userId) {
|
||||||
this.userId = userId;
|
this.userId = userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getOutOrderNo() {
|
||||||
|
return outOrderNo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOutOrderNo(String outOrderNo) {
|
||||||
|
this.outOrderNo = outOrderNo;
|
||||||
|
}
|
||||||
}
|
}
|
@ -14,7 +14,7 @@ public class OrderListReqVo extends BaseEntity {
|
|||||||
private Long userId;
|
private Long userId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 订单类型
|
* 订单状态
|
||||||
*/
|
*/
|
||||||
private Long orderStatus;
|
private Long orderStatus;
|
||||||
|
|
@ -1,8 +1,12 @@
|
|||||||
package com.sf.order.domain.res;
|
package com.sf.order.domain.res;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import com.sf.common.annotation.Excel;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 活动信息详情
|
* 活动信息详情
|
||||||
*
|
*
|
||||||
@ -21,11 +25,7 @@ public class OrderListResVo {
|
|||||||
private String orderNo;
|
private String orderNo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 订单状态:
|
* 订单状态: 0:待支付 1:已付款待发货 2:配送中 3:待取货 4:支付超时系统结束 5:客户自主取消 6:已完成
|
||||||
* 0:待支付
|
|
||||||
* 1:已付款
|
|
||||||
* 2:支付超时系统结束
|
|
||||||
* 3:已完成
|
|
||||||
*/
|
*/
|
||||||
private Long orderStatus;
|
private Long orderStatus;
|
||||||
|
|
||||||
@ -34,6 +34,18 @@ public class OrderListResVo {
|
|||||||
*/
|
*/
|
||||||
private Long orderAmt;
|
private Long orderAmt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付时间
|
||||||
|
*/
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date payTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅订单取消时间
|
||||||
|
*/
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date subscriptionCancellationTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 商品标题
|
* 商品标题
|
||||||
*/
|
*/
|
||||||
@ -43,13 +55,21 @@ public class OrderListResVo {
|
|||||||
*/
|
*/
|
||||||
private String productPicture;
|
private String productPicture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品描述
|
||||||
|
*/
|
||||||
|
private String productDesc;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 商品规格
|
* 商品规格
|
||||||
*/
|
*/
|
||||||
private String goodsSpec;
|
private String goodsSpec;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 商品数量
|
* 商品数量
|
||||||
*/
|
*/
|
||||||
private Integer goodsCount = 1;
|
private Integer goodsCount;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -64,4 +64,6 @@ public interface OrderInfoMapper {
|
|||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public int deleteOrderInfoByIds(Long[] ids);
|
public int deleteOrderInfoByIds(Long[] ids);
|
||||||
|
|
||||||
|
OrderInfo selectOrderInfoByOrderNo(String orderNo);
|
||||||
}
|
}
|
@ -43,7 +43,7 @@ public interface IOrderInfoService
|
|||||||
* @param orderInfo 订单基础信息
|
* @param orderInfo 订单基础信息
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public int createOrder(OrderCreateDto orderInfo);
|
public Long createOrder(OrderCreateDto orderInfo);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改订单基础信息
|
* 修改订单基础信息
|
||||||
@ -70,4 +70,6 @@ public interface IOrderInfoService
|
|||||||
public int deleteOrderInfoById(Long id);
|
public int deleteOrderInfoById(Long id);
|
||||||
|
|
||||||
void orderPay(Long orderId);
|
void orderPay(Long orderId);
|
||||||
|
|
||||||
|
OrderInfo selectOrderInfoByOrderNo(String orderNo);
|
||||||
}
|
}
|
@ -21,8 +21,7 @@ import java.util.List;
|
|||||||
* @date 2024-04-09
|
* @date 2024-04-09
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class OrderInfoServiceImpl implements IOrderInfoService
|
public class OrderInfoServiceImpl implements IOrderInfoService {
|
||||||
{
|
|
||||||
@Resource
|
@Resource
|
||||||
private OrderInfoMapper orderInfoMapper;
|
private OrderInfoMapper orderInfoMapper;
|
||||||
@Resource
|
@Resource
|
||||||
@ -35,8 +34,7 @@ public class OrderInfoServiceImpl implements IOrderInfoService
|
|||||||
* @return 订单基础信息
|
* @return 订单基础信息
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public OrderInfo selectOrderInfoById(Long id)
|
public OrderInfo selectOrderInfoById(Long id) {
|
||||||
{
|
|
||||||
return orderInfoMapper.selectOrderInfoById(id);
|
return orderInfoMapper.selectOrderInfoById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,12 +45,11 @@ public class OrderInfoServiceImpl implements IOrderInfoService
|
|||||||
* @return 订单基础信息
|
* @return 订单基础信息
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<OrderInfo> selectOrderInfoList(OrderInfo orderInfo)
|
public List<OrderInfo> selectOrderInfoList(OrderInfo orderInfo) {
|
||||||
{
|
|
||||||
return orderInfoMapper.selectOrderInfoList(orderInfo);
|
return orderInfoMapper.selectOrderInfoList(orderInfo);
|
||||||
}
|
}
|
||||||
public List<OrderListResVo> queryList(OrderListReqVo vo)
|
|
||||||
{
|
public List<OrderListResVo> queryList(OrderListReqVo vo) {
|
||||||
return orderInfoMapper.queryList(vo);
|
return orderInfoMapper.queryList(vo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,11 +60,10 @@ public class OrderInfoServiceImpl implements IOrderInfoService
|
|||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int createOrder(OrderCreateDto orderCreateDto)
|
public Long createOrder(OrderCreateDto orderCreateDto) {
|
||||||
{
|
|
||||||
OrderInfo orderInfo = new OrderInfo();
|
OrderInfo orderInfo = new OrderInfo();
|
||||||
orderInfo.setOrderNo(snowflakeIdWorker.nextId());
|
orderInfo.setOrderNo(snowflakeIdWorker.nextId() + "");
|
||||||
orderInfo.setPayType(0L);
|
orderInfo.setPayType(1L);
|
||||||
orderInfo.setReceiveType(0L);
|
orderInfo.setReceiveType(0L);
|
||||||
orderInfo.setOrderStatus(0L);
|
orderInfo.setOrderStatus(0L);
|
||||||
orderInfo.setCreateUserId(orderCreateDto.getUserId());
|
orderInfo.setCreateUserId(orderCreateDto.getUserId());
|
||||||
@ -77,7 +73,9 @@ public class OrderInfoServiceImpl implements IOrderInfoService
|
|||||||
orderInfo.setPayAmt(orderCreateDto.getAmount());
|
orderInfo.setPayAmt(orderCreateDto.getAmount());
|
||||||
orderInfo.setCreateTime(DateUtils.getNowDate());
|
orderInfo.setCreateTime(DateUtils.getNowDate());
|
||||||
orderInfo.setUpdateTime(DateUtils.getNowDate());
|
orderInfo.setUpdateTime(DateUtils.getNowDate());
|
||||||
return orderInfoMapper.insertOrderInfo(orderInfo);
|
orderInfo.setOutOrderNo(orderCreateDto.getOutOrderNo());
|
||||||
|
orderInfoMapper.insertOrderInfo(orderInfo);
|
||||||
|
return snowflakeIdWorker.nextId();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -87,11 +85,11 @@ public class OrderInfoServiceImpl implements IOrderInfoService
|
|||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int updateOrderInfo(OrderInfo orderInfo)
|
public int updateOrderInfo(OrderInfo orderInfo) {
|
||||||
{
|
|
||||||
orderInfo.setUpdateTime(DateUtils.getNowDate());
|
orderInfo.setUpdateTime(DateUtils.getNowDate());
|
||||||
return orderInfoMapper.updateOrderInfo(orderInfo);
|
return orderInfoMapper.updateOrderInfo(orderInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void orderPay(Long orderId) {
|
public void orderPay(Long orderId) {
|
||||||
OrderInfo updateOrder = this.selectOrderInfoById(orderId);
|
OrderInfo updateOrder = this.selectOrderInfoById(orderId);
|
||||||
@ -104,11 +102,17 @@ public class OrderInfoServiceImpl implements IOrderInfoService
|
|||||||
updateOrder.setOrderStatus(1L);
|
updateOrder.setOrderStatus(1L);
|
||||||
updateOrder.setPayTime(DateUtils.getNowDate());
|
updateOrder.setPayTime(DateUtils.getNowDate());
|
||||||
// 修改订单状态
|
// 修改订单状态
|
||||||
if (1>this.updateOrderInfo(updateOrder)) {
|
if (1 > this.updateOrderInfo(updateOrder)) {
|
||||||
throw new ServiceException("支付异常,请联系管理员!");
|
throw new ServiceException("支付异常,请联系管理员!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OrderInfo selectOrderInfoByOrderNo(String orderNo) {
|
||||||
|
|
||||||
|
return orderInfoMapper.selectOrderInfoByOrderNo(orderNo);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量删除订单基础信息
|
* 批量删除订单基础信息
|
||||||
*
|
*
|
||||||
@ -116,8 +120,7 @@ public class OrderInfoServiceImpl implements IOrderInfoService
|
|||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int deleteOrderInfoByIds(Long[] ids)
|
public int deleteOrderInfoByIds(Long[] ids) {
|
||||||
{
|
|
||||||
return orderInfoMapper.deleteOrderInfoByIds(ids);
|
return orderInfoMapper.deleteOrderInfoByIds(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,8 +131,7 @@ public class OrderInfoServiceImpl implements IOrderInfoService
|
|||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int deleteOrderInfoById(Long id)
|
public int deleteOrderInfoById(Long id) {
|
||||||
{
|
|
||||||
return orderInfoMapper.deleteOrderInfoById(id);
|
return orderInfoMapper.deleteOrderInfoById(id);
|
||||||
}
|
}
|
||||||
|
|
@ -35,18 +35,21 @@
|
|||||||
<result property="orderNo" column="order_no" />
|
<result property="orderNo" column="order_no" />
|
||||||
<result property="orderStatus" column="order_status" />
|
<result property="orderStatus" column="order_status" />
|
||||||
<result property="orderAmt" column="order_amt" />
|
<result property="orderAmt" column="order_amt" />
|
||||||
|
<result property="payTime" column="pay_time" />
|
||||||
<result property="productTitle" column="product_title" />
|
<result property="productTitle" column="product_title" />
|
||||||
<result property="productPicture" column="product_picture" />
|
<result property="productPicture" column="product_picture" />
|
||||||
|
<result property="productDesc" column="product_desc" />
|
||||||
<result property="goodsSpec" column="goods_spec" />
|
<result property="goodsSpec" column="goods_spec" />
|
||||||
<result property="goodsCount" column="goods_count" />
|
<result property="goodsCount" column="goods_count" />
|
||||||
|
<result property="subscriptionCancellationTime" column="subscription_cancellation_time" />
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<sql id="selectOrderInfoVo">
|
<sql id="selectOrderInfoVo">
|
||||||
select id, order_no, order_status, pay_type, pay_channel, order_amt, freight_amt, pay_amt, really_amt, receive_type, goods_id, business_id, receive_addr_id, create_time, pay_time, create_user_id, update_user_id, is_delete, update_time, track_no, order_type, out_order_no, pay_data, reduction_amout from ORDER_INFO
|
select id, order_no, order_status, pay_type, pay_channel, order_amt, freight_amt, pay_amt, really_amt, receive_type, goods_id, business_id, receive_addr_id, create_time, pay_time, create_user_id, update_user_id, is_delete, update_time, track_no, order_type, out_order_no, pay_data, reduction_amout from Order_info
|
||||||
</sql>
|
</sql>
|
||||||
<sql id="OrderListInfoVo">
|
<sql id="OrderListInfoVo">
|
||||||
SELECT a.order_no,a.order_status,a.order_amt,b.product_title,b.product_picture,b.product_desc,b.goods_spec
|
SELECT a.id,a.order_no,a.order_status,a.order_amt,a.pay_time,a.count as goods_count,a.subscription_cancellation_time,b.product_title,b.product_picture,b.product_desc,b.goods_spec
|
||||||
FROM ORDER_INFO a LEFT JOIN GOODS_MESSAGES b ON a.goods_id = b.id
|
FROM Order_info a LEFT JOIN GOODS_MESSAGES b ON a.goods_id = b.id
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
<select id="selectOrderInfoList" parameterType="OrderInfo" resultMap="OrderInfoResult">
|
<select id="selectOrderInfoList" parameterType="OrderInfo" resultMap="OrderInfoResult">
|
||||||
@ -88,9 +91,14 @@
|
|||||||
<include refid="selectOrderInfoVo"/>
|
<include refid="selectOrderInfoVo"/>
|
||||||
where id = #{id}
|
where id = #{id}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="selectOrderInfoByOrderNo" resultMap="OrderInfoResult">
|
||||||
|
<include refid="selectOrderInfoVo"/>
|
||||||
|
where order_no = #{orderNo}
|
||||||
|
</select>
|
||||||
|
|
||||||
<insert id="insertOrderInfo" parameterType="OrderInfo">
|
<insert id="insertOrderInfo" parameterType="OrderInfo">
|
||||||
insert into ORDER_INFO
|
insert into Order_info
|
||||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||||
<if test="id != null">id,</if>
|
<if test="id != null">id,</if>
|
||||||
<if test="orderNo != null">order_no,</if>
|
<if test="orderNo != null">order_no,</if>
|
||||||
@ -146,7 +154,7 @@
|
|||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
<update id="updateOrderInfo" parameterType="OrderInfo">
|
<update id="updateOrderInfo" parameterType="OrderInfo">
|
||||||
update ORDER_INFO
|
update Order_info
|
||||||
<trim prefix="SET" suffixOverrides=",">
|
<trim prefix="SET" suffixOverrides=",">
|
||||||
<if test="orderNo != null">order_no = #{orderNo},</if>
|
<if test="orderNo != null">order_no = #{orderNo},</if>
|
||||||
<if test="orderStatus != null">order_status = #{orderStatus},</if>
|
<if test="orderStatus != null">order_status = #{orderStatus},</if>
|
||||||
@ -176,11 +184,11 @@
|
|||||||
</update>
|
</update>
|
||||||
|
|
||||||
<delete id="deleteOrderInfoById" parameterType="Long">
|
<delete id="deleteOrderInfoById" parameterType="Long">
|
||||||
delete from ORDER_INFO where id = #{id}
|
delete from Order_info where id = #{id}
|
||||||
</delete>
|
</delete>
|
||||||
|
|
||||||
<delete id="deleteOrderInfoByIds" parameterType="String">
|
<delete id="deleteOrderInfoByIds" parameterType="String">
|
||||||
delete from ORDER_INFO where id in
|
delete from Order_info where id in
|
||||||
<foreach item="id" collection="array" open="(" separator="," close=")">
|
<foreach item="id" collection="array" open="(" separator="," close=")">
|
||||||
#{id}
|
#{id}
|
||||||
</foreach>
|
</foreach>
|
41
sf-payment/pom.xml
Normal file
41
sf-payment/pom.xml
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>smarterFramework</artifactId>
|
||||||
|
<groupId>com.smarterFramework</groupId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>sf-payment</artifactId>
|
||||||
|
|
||||||
|
<description>
|
||||||
|
支付模块
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<!-- 通用工具-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.smarterFramework</groupId>
|
||||||
|
<artifactId>sf-common</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.smarterFramework</groupId>
|
||||||
|
<artifactId>sf-framework</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.smarterFramework</groupId>
|
||||||
|
<artifactId>sf-order</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.bouncycastle</groupId>
|
||||||
|
<artifactId>bcprov-jdk18on</artifactId>
|
||||||
|
<version>1.73</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,31 @@
|
|||||||
|
package com.sf.payment.config;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 功能描述:
|
||||||
|
*
|
||||||
|
* @author a_kun
|
||||||
|
* @date 2024/4/17 9:23
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Configuration
|
||||||
|
public class HuaweiPaymentConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端id:对应各平台的appKey
|
||||||
|
*/
|
||||||
|
@Value("${huawei.payment.clientId:110693217}")
|
||||||
|
private String clientId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端Secret:对应各平台的appSecret
|
||||||
|
*/
|
||||||
|
@Value("${huawei.payment.clientSecret:1410c01bc71c7ba587175ae79e500137c70945acc1416a38127cf98a09a6f8ba}")
|
||||||
|
private String clientSecret;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package com.sf.payment.controller;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.sf.common.core.domain.AjaxResult;
|
||||||
|
import com.sf.payment.domain.HuaweiPaymentCallback;
|
||||||
|
import com.sf.payment.domain.HuaweiPurchasesVerifyDTO;
|
||||||
|
import com.sf.payment.service.IHuaweiPaymentService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author zoukun
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/payment")
|
||||||
|
public class HuaweiPaymentController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IHuaweiPaymentService huaweiPaymentService;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 华为支付回调地址
|
||||||
|
*/
|
||||||
|
@RequestMapping("/callback/huawei")
|
||||||
|
public AjaxResult callback(@RequestBody HuaweiPaymentCallback callback) {
|
||||||
|
log.info("进入callback: params:" + JSONObject.toJSONString(callback));
|
||||||
|
AjaxResult ajax = AjaxResult.success();
|
||||||
|
return ajax;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 华为购买验证
|
||||||
|
*/
|
||||||
|
@RequestMapping("/huawei/purchases/verify")
|
||||||
|
public AjaxResult purchasesVerify(@Validated @RequestBody HuaweiPurchasesVerifyDTO verifyDTO) {
|
||||||
|
log.info("进入/huawei/purchases/tokens/verify: params:" + JSONObject.toJSONString(verifyDTO));
|
||||||
|
huaweiPaymentService.purchasesVerify(verifyDTO);
|
||||||
|
return AjaxResult.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
package com.sf.payment.domain;
|
||||||
|
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权所需的token
|
||||||
|
*
|
||||||
|
* @author zoukun
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class AuthToken implements Serializable {
|
||||||
|
private String accessToken;
|
||||||
|
private int expireIn;
|
||||||
|
private String refreshToken;
|
||||||
|
private int refreshTokenExpireIn;
|
||||||
|
private String uid;
|
||||||
|
private String openId;
|
||||||
|
private String accessCode;
|
||||||
|
private String unionId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 华为返回 生成的Access Token中包含的scope。
|
||||||
|
*/
|
||||||
|
private String scope;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 华为返回 固定返回Bearer,标识返回Access Token的类型
|
||||||
|
*/
|
||||||
|
private String tokenType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 华为返回 返回JWT格式数据,包含用户基本帐号、用户邮箱等信息。
|
||||||
|
* 参照https://developer.huawei.com/consumer/cn/doc/HMSCore-References/account-verify-id-token_hms_reference-0000001050050577#section3142132691914
|
||||||
|
*/
|
||||||
|
private String idToken;
|
||||||
|
}
|
73
sf-payment/src/main/java/com/sf/payment/domain/AuthUser.java
Normal file
73
sf-payment/src/main/java/com/sf/payment/domain/AuthUser.java
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package com.sf.payment.domain;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权成功后的用户信息,根据授权平台的不同,获取的数据完整性也不同
|
||||||
|
*
|
||||||
|
* @author zoukun
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class AuthUser implements Serializable {
|
||||||
|
/**
|
||||||
|
* 用户第三方系统的唯一id。
|
||||||
|
*/
|
||||||
|
private String uuid;
|
||||||
|
/**
|
||||||
|
* 用户名
|
||||||
|
*/
|
||||||
|
private String username;
|
||||||
|
/**
|
||||||
|
* 用户昵称
|
||||||
|
*/
|
||||||
|
private String nickname;
|
||||||
|
/**
|
||||||
|
* 用户头像
|
||||||
|
*/
|
||||||
|
private String avatar;
|
||||||
|
/**
|
||||||
|
* 用户网址
|
||||||
|
*/
|
||||||
|
private String blog;
|
||||||
|
/**
|
||||||
|
* 所在公司
|
||||||
|
*/
|
||||||
|
private String company;
|
||||||
|
/**
|
||||||
|
* 位置
|
||||||
|
*/
|
||||||
|
private String location;
|
||||||
|
/**
|
||||||
|
* 用户邮箱
|
||||||
|
*/
|
||||||
|
private String email;
|
||||||
|
/**
|
||||||
|
* 用户手机号
|
||||||
|
*/
|
||||||
|
private String mobileNumber;
|
||||||
|
/**
|
||||||
|
* 用户备注(各平台中的用户个人介绍)
|
||||||
|
*/
|
||||||
|
private String remark;
|
||||||
|
/**
|
||||||
|
* 用户来源
|
||||||
|
*/
|
||||||
|
private String source;
|
||||||
|
/**
|
||||||
|
* 用户授权的token信息
|
||||||
|
*/
|
||||||
|
private AuthToken token;
|
||||||
|
/**
|
||||||
|
* 第三方平台返回的原始用户信息
|
||||||
|
*/
|
||||||
|
private JSONObject rawUserInfo;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package com.sf.payment.domain;
|
||||||
|
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权回调时的参数类
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class HuaweiPaymentCallback implements Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 访问AuthorizeUrl后回调时带的参数code
|
||||||
|
*/
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端id:对应各平台的appKey
|
||||||
|
*/
|
||||||
|
private String clientId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端Secret:对应各平台的appSecret
|
||||||
|
*/
|
||||||
|
private String clientSecret;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
package com.sf.payment.domain;
|
||||||
|
|
||||||
|
import apijson.NotNull;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 华为验证购买tokenDTO
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class HuaweiPurchasesVerifyDTO implements Serializable {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品类别,取值包括:
|
||||||
|
*
|
||||||
|
* 0:消耗型商品
|
||||||
|
* 1:非消耗型商品
|
||||||
|
* 2:订阅型商品
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
private Integer kind;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 待下发商品的购买Token,发起购买和查询待消费商品信息时均会返回purchaseToken参数。
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "待下发商品的购买Token不能为空")
|
||||||
|
private String purchaseToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 待下发商品ID。商品ID来源于您在AppGallery Connect中配置商品信息时设置的商品ID。
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "待下发商品ID不能为空")
|
||||||
|
private String productId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单号
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "订单号不能为空")
|
||||||
|
private String orderNo;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
package com.sf.payment.domain;
|
||||||
|
|
||||||
|
import apijson.NotNull;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 华为验证购买tokenD返回
|
||||||
|
*
|
||||||
|
* @author zk
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class HuaweiPurchasesVerifyResponseDTO implements Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回码。
|
||||||
|
*
|
||||||
|
* 0:成功。
|
||||||
|
* 其他:失败,具体请参见错误码。
|
||||||
|
*/
|
||||||
|
private String responseCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 响应描述。
|
||||||
|
*/
|
||||||
|
private String responseMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 包含购买数据的JSON字符串,具体请参见表InappPurchaseDetails。
|
||||||
|
*
|
||||||
|
* 该字段原样参与签名。
|
||||||
|
*/
|
||||||
|
private String purchaseTokenData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* purchaseTokenData基于应用RSA IAP私钥的签名信息,签名算法为signatureAlgorithm。
|
||||||
|
* 应用请参见对返回结果验签使用IAP公钥对PurchaseTokenData的JSON字符串进行验签。
|
||||||
|
*/
|
||||||
|
private String dataSignature;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 签名算法。
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "待下发商品ID不能为空")
|
||||||
|
private String signatureAlgorithm;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,233 @@
|
|||||||
|
package com.sf.payment.domain;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 功能描述:
|
||||||
|
*
|
||||||
|
* @author a_kun
|
||||||
|
* @date 2024/4/16 15:29
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class InAppPurchaseData {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用ID。
|
||||||
|
*/
|
||||||
|
private Long applicationId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消耗型商品或者非消耗型商品:固定为false。
|
||||||
|
*
|
||||||
|
* 订阅型商品:
|
||||||
|
*
|
||||||
|
* true:订阅处于活动状态并且将在下一个结算日期自动续订。
|
||||||
|
* false:用户已经取消订阅。 用户可以在下一个结算日期之前访问订阅内容,并且在该日期后将无法访问,除非重新启用自动续订。 如果提供了宽限期,只要宽限期未过,此值就会对所有订阅保持设置为true。 下一次结算日期每天都会自动延长,直至宽限期结束,或者用户更改付款方式。
|
||||||
|
*/
|
||||||
|
private Boolean autoRenewing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单ID,唯一标识一笔需要收费的收据,由华为应用内支付服务器在创建订单以及订阅型商品续费时生成。
|
||||||
|
*
|
||||||
|
* 每一笔新的收据都会使用不同的orderId。
|
||||||
|
*/
|
||||||
|
private String orderId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品类别,取值包括:
|
||||||
|
*
|
||||||
|
* 0:消耗型商品
|
||||||
|
* 1:非消耗型商品
|
||||||
|
* 2:订阅型商品
|
||||||
|
*/
|
||||||
|
private Integer kind;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品ID。每种商品必须有唯一的ID,由应用在PMS中维护,或者应用发起购买时传入。
|
||||||
|
* 说明
|
||||||
|
* 为避免资金损失,您在对支付结果验签成功后,必须对其进行校验。
|
||||||
|
*/
|
||||||
|
private String productId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品名称。
|
||||||
|
*/
|
||||||
|
private String productName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品购买时间,UTC时间戳,以毫秒为单位。
|
||||||
|
*/
|
||||||
|
private Long purchaseTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单交易状态。
|
||||||
|
*
|
||||||
|
* -1:初始化
|
||||||
|
* 0:已购买
|
||||||
|
* 1:已取消
|
||||||
|
* 2:已撤销或已退款
|
||||||
|
* 3:待处理
|
||||||
|
*/
|
||||||
|
private Integer purchaseState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 商户侧保留信息,由您在调用支付接口时传入。
|
||||||
|
*/
|
||||||
|
private String developerPayload;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*消耗状态,仅一次性商品存在,取值包括:
|
||||||
|
*
|
||||||
|
* 0:未消耗
|
||||||
|
* 1:已消耗
|
||||||
|
*/
|
||||||
|
private Integer consumptionState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*确认状态,取值包括:
|
||||||
|
*
|
||||||
|
* 0 :未确认
|
||||||
|
* 1:已确认
|
||||||
|
* 没有值表示不需要确认
|
||||||
|
*/
|
||||||
|
private Integer confirmed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于唯一标识商品和用户对应关系的购买令牌,在支付完成时由华为应用内支付服务器生成。
|
||||||
|
* 说明
|
||||||
|
* 该字段是唯一标识商品和用户对应关系的,在订阅型商品正常续订时不会改变。
|
||||||
|
* 当前92位,后续存在扩展可能,如要进行存储,建议您预留128位的长度。
|
||||||
|
* 如要进行存储,为保证安全,建议加密存储。
|
||||||
|
*/
|
||||||
|
private String purchaseToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用定价货币的币种,请参见ISO 4217标准。
|
||||||
|
* 说明
|
||||||
|
* 为避免资金损失,您在对支付结果验签成功后,必须对其进行校验。
|
||||||
|
*/
|
||||||
|
private String currency;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品实际价格*100以后的值。商品实际价格精确到小数点后2位,例如此参数值为501,则表示商品实际价格为5.01。
|
||||||
|
*/
|
||||||
|
private Long price;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付方式,取值请参见payType说明。
|
||||||
|
*/
|
||||||
|
private String payType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 交易单号,用户支付成功后生成。
|
||||||
|
*/
|
||||||
|
private String payOrderId;
|
||||||
|
|
||||||
|
// 以下参数只在订阅场景返回
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上次续期收款的订单ID,由支付服务器在续期扣费时生成。首次购买订阅型商品时的lastOrderId与orderId数值相同。
|
||||||
|
*/
|
||||||
|
private String lastOrderId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅型商品所属的订阅组ID。
|
||||||
|
*/
|
||||||
|
private String productGroup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 原购买的时间,即本订阅型商品首次成功收费的时间,UTC时间戳,以毫秒为单位。。
|
||||||
|
*/
|
||||||
|
private Long oriPurchaseTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅ID。
|
||||||
|
* 说明
|
||||||
|
* subscriptionId是用户与商品之间的一一对应关系,在订阅型商品正常续订时不会改变。
|
||||||
|
*/
|
||||||
|
private String subscriptionId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 原订阅ID。有值表示当前订阅是从其他商品切换来的,该值可以关联切换前的商品订阅信息
|
||||||
|
*/
|
||||||
|
private String oriSubscriptionId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 购买数量。
|
||||||
|
*/
|
||||||
|
private Integer quantity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已经付费订阅的天数,免费试用和促销期周期除外。。
|
||||||
|
*/
|
||||||
|
private Long daysLasted;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 成功标准续期(没有设置促销的续期)的期数,为0或者不存在表示还没有成功续期。
|
||||||
|
*/
|
||||||
|
private Long numOfPeriods;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 成功促销续期期数。
|
||||||
|
*/
|
||||||
|
private Long numOfDiscount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅型商品过期时间,UTC时间戳,以毫秒为单位。
|
||||||
|
*
|
||||||
|
* 对于一个成功收费的自动续订收据,该时间表示续期日期或者超期日期。如果商品最近的收据的该时间是一个过去的时间,则订阅已经过期。
|
||||||
|
*/
|
||||||
|
private Long expirationDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对于已经过期的订阅,表示过期原因,取值包括:
|
||||||
|
*
|
||||||
|
* 1:用户取消
|
||||||
|
* 2:商品不可用
|
||||||
|
* 3:用户签约信息异常
|
||||||
|
* 4:Billing错误
|
||||||
|
* 5:用户未同意涨价
|
||||||
|
* 6:未知错误
|
||||||
|
* 同时有多个异常时,优先级为:1 > 2 > 3…
|
||||||
|
*/
|
||||||
|
private Integer expirationIntent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅撤销时间,UTC时间戳,以毫秒为单位,发生退款且服务立即不可用。在顾客投诉,通过客服撤销订阅,或者顾客升级、跨级到同组其他商品并且立即生效场景下,需要撤销原有订阅的上次收据时有值。
|
||||||
|
* 说明
|
||||||
|
* 已经撤销的收据等同于没有完成购买。
|
||||||
|
*/
|
||||||
|
private Long cancelTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取消原因。
|
||||||
|
*
|
||||||
|
* 3: 应用调用IAP接口取消
|
||||||
|
* 2:顾客升级、跨级等。
|
||||||
|
* 1:顾客因为在App内遇到了问题而取消了订阅。
|
||||||
|
* 0:其他原因取消,比如顾客错误地订阅了商品。
|
||||||
|
* 说明
|
||||||
|
* 如果为空且cancelTime有值,表示是升级等操作导致的取消。
|
||||||
|
*/
|
||||||
|
private Integer cancelReason;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 续期状态。
|
||||||
|
*
|
||||||
|
* 1:当前周期到期时自动续期
|
||||||
|
* 0:用户停止了续期
|
||||||
|
* 仅针对自动续期订阅,对有效和过期的订阅均有效,并不代表顾客的订阅状态。通常,取值为0时,应用可以给顾客提供其他的订阅选项,
|
||||||
|
* 例如推荐一个同组更低级别的商品。该值为0通常代表着顾客主动取消了该订阅。
|
||||||
|
*/
|
||||||
|
private Integer renewStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户取消订阅的时间,UTC时间戳,以毫秒为单位。在该时间进行了订阅续期停止的设定,商品在有效期内仍然有效,但后续的续期会终止,无退款。
|
||||||
|
*/
|
||||||
|
private Integer cancellationTime;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package com.sf.payment.service;
|
||||||
|
|
||||||
|
|
||||||
|
import com.sf.payment.domain.HuaweiPurchasesVerifyDTO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 功能描述:
|
||||||
|
*
|
||||||
|
* @author a_kun
|
||||||
|
* @date 2024/4/12 10:21
|
||||||
|
*/
|
||||||
|
public interface IHuaweiPaymentService {
|
||||||
|
void purchasesVerify(HuaweiPurchasesVerifyDTO verifyDTO);
|
||||||
|
}
|
@ -0,0 +1,235 @@
|
|||||||
|
package com.sf.payment.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.date.DateField;
|
||||||
|
import cn.hutool.core.date.DateTime;
|
||||||
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.hutool.http.HttpUtil;
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.sf.common.utils.SecurityUtils;
|
||||||
|
import com.sf.order.domain.OrderInfo;
|
||||||
|
import com.sf.order.service.IOrderInfoService;
|
||||||
|
import com.sf.payment.config.HuaweiPaymentConfig;
|
||||||
|
import com.sf.payment.domain.HuaweiPurchasesVerifyDTO;
|
||||||
|
import com.sf.payment.domain.HuaweiPurchasesVerifyResponseDTO;
|
||||||
|
import com.sf.payment.domain.InAppPurchaseData;
|
||||||
|
import com.sf.payment.service.IHuaweiPaymentService;
|
||||||
|
import com.sf.system.domain.UserMember;
|
||||||
|
import com.sf.system.service.IUserMemberService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.KeyFactory;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.security.Security;
|
||||||
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 功能描述:
|
||||||
|
*
|
||||||
|
* @author a_kun
|
||||||
|
* @date 2024/4/12 10:21
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class HuaweiPaymentServiceImpl implements IHuaweiPaymentService {
|
||||||
|
|
||||||
|
// token url to get the authorization
|
||||||
|
private static final String TOKEN_URL = "https://oauth-login.cloud.huawei.com/oauth2/v3/token";
|
||||||
|
private static final String VERIFY_TOKEN_URL = "https://orders-drcn.iap.cloud.huawei.com.cn/applications/purchases/tokens/verify";
|
||||||
|
|
||||||
|
private static final String PUBLIC_KEY = "PUBLIC_KEY";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IOrderInfoService orderInfoService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IUserMemberService userMemberService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private HuaweiPaymentConfig huaweiPaymentConfig;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void purchasesVerify(HuaweiPurchasesVerifyDTO verifyDTO) {
|
||||||
|
// construct the Authorization in Header
|
||||||
|
Map<String, String> headers = buildAuthorization(getAppAT(huaweiPaymentConfig.getClientId(), huaweiPaymentConfig.getClientSecret()));
|
||||||
|
|
||||||
|
// pack the request body
|
||||||
|
Map<String, String> bodyMap = new HashMap<>();
|
||||||
|
bodyMap.put("purchaseToken", verifyDTO.getPurchaseToken());
|
||||||
|
bodyMap.put("productId", verifyDTO.getProductId());
|
||||||
|
|
||||||
|
String response = HttpUtil.createPost(VERIFY_TOKEN_URL)
|
||||||
|
.addHeaders(headers)
|
||||||
|
.body(JSON.toJSONString(bodyMap))
|
||||||
|
.execute().body();
|
||||||
|
HuaweiPurchasesVerifyResponseDTO huaweiPurchasesVerifyResponseDTO = JSON.parseObject(response, HuaweiPurchasesVerifyResponseDTO.class);
|
||||||
|
InAppPurchaseData inAppPurchaseData = JSON.parseObject(huaweiPurchasesVerifyResponseDTO.getPurchaseTokenData(), InAppPurchaseData.class);
|
||||||
|
// 获取服务订单
|
||||||
|
OrderInfo orderInfo = orderInfoService.selectOrderInfoByOrderNo(verifyDTO.getOrderNo());
|
||||||
|
// 校验订单
|
||||||
|
boolean checkSuccessOrder = checkSuccessOrder(huaweiPurchasesVerifyResponseDTO.getPurchaseTokenData()
|
||||||
|
, huaweiPurchasesVerifyResponseDTO.getDataSignature()
|
||||||
|
, PUBLIC_KEY
|
||||||
|
, huaweiPurchasesVerifyResponseDTO.getSignatureAlgorithm()
|
||||||
|
, orderInfo);
|
||||||
|
|
||||||
|
Assert.isTrue(checkSuccessOrder, "订单校验失败,请重试");
|
||||||
|
Assert.isTrue(inAppPurchaseData.getPurchaseState()==0, "订单未完成购买");
|
||||||
|
DateTime payTime = DateUtil.date(inAppPurchaseData.getPurchaseTime());
|
||||||
|
UserMember userMember = userMemberService.selectUserMemberByUserId(orderInfo.getCreateUserId());
|
||||||
|
if (userMember == null) {
|
||||||
|
// 添加会员信息
|
||||||
|
boolean isSubscription = verifyDTO.getKind() == 2;
|
||||||
|
userMember = new UserMember();
|
||||||
|
userMember.setMemberLevel(isSubscription ? 1 : 2);
|
||||||
|
userMember.setSubscriptionStatus(isSubscription ? 1 : 0);
|
||||||
|
userMember.setUserId(orderInfo.getCreateUserId());
|
||||||
|
userMember.setIntegration(0L);
|
||||||
|
DateTime expirationTime = DateUtil.offset(payTime, DateField.MONTH, 1);
|
||||||
|
userMember.setExpirationTime(expirationTime);
|
||||||
|
userMember.setCreateTime(new Date());
|
||||||
|
userMember.setUpdateTime(new Date());
|
||||||
|
userMemberService.insertUserMember(userMember);
|
||||||
|
} else {
|
||||||
|
// 更新
|
||||||
|
DateTime expirationTime = DateUtil.offset(userMember.getExpirationTime(), DateField.MONTH, 1);
|
||||||
|
userMember.setExpirationTime(expirationTime);
|
||||||
|
userMember.setUpdateTime(new Date());
|
||||||
|
userMemberService.updateUserMember(userMember);
|
||||||
|
}
|
||||||
|
// 更新订单状态
|
||||||
|
orderInfo.setPayTime(payTime);
|
||||||
|
orderInfo.setOrderStatus(3L);
|
||||||
|
orderInfo.setPayChannel(2L);
|
||||||
|
orderInfo.setPayAmt(orderInfo.getOrderAmt());
|
||||||
|
orderInfo.setReallyAmt(orderInfo.getOrderAmt());
|
||||||
|
orderInfo.setOrderStatus(3L);
|
||||||
|
orderInfo.setPayData(huaweiPurchasesVerifyResponseDTO.getPurchaseTokenData());
|
||||||
|
orderInfoService.updateOrderInfo(orderInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets App Level AccessToken.
|
||||||
|
*/
|
||||||
|
public static String getAppAT(String clientId, String clientSecret) {
|
||||||
|
// fetch accessToken
|
||||||
|
Map<String, Object> form = new HashMap<>(8);
|
||||||
|
form.put("grant_type", "client_credentials");
|
||||||
|
form.put("client_secret", clientSecret);
|
||||||
|
form.put("client_id", clientId);
|
||||||
|
String atResponse = HttpUtil.post(TOKEN_URL, form);
|
||||||
|
log.info("getAppAT Response : {}", atResponse);
|
||||||
|
JSONObject parseObject = JSON.parseObject(atResponse);
|
||||||
|
return parseObject.getString("access_token");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build Authorization in Header
|
||||||
|
*
|
||||||
|
* @param appAt appAt
|
||||||
|
* @return headers
|
||||||
|
*/
|
||||||
|
public static Map<String, String> buildAuthorization(String appAt) {
|
||||||
|
String oriString = MessageFormat.format("APPAT:{0}", appAt);
|
||||||
|
String authorization =
|
||||||
|
MessageFormat.format("Basic {0}", Base64.encodeBase64String(oriString.getBytes(StandardCharsets.UTF_8)));
|
||||||
|
Map<String, String> headers = new HashMap<>();
|
||||||
|
headers.put("Authorization", authorization);
|
||||||
|
headers.put("Content-Type", "application/json; charset=UTF-8");
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验签名信息,校验InAppPurchaseData中的productId、price、currency等信息的一致性
|
||||||
|
*
|
||||||
|
* @param content 结果字符串
|
||||||
|
* @param sign 签名字符串
|
||||||
|
* @param publicKey IAP公钥
|
||||||
|
* @return 是否校验通过
|
||||||
|
*/
|
||||||
|
public static boolean checkSuccessOrder(String content, String sign, String publicKey, String signatureAlgorithm, OrderInfo orderInfo) {
|
||||||
|
// 校验签名信息
|
||||||
|
boolean checkRes = checkSign(content, sign, publicKey, StrUtil.blankToDefault(signatureAlgorithm, "SHA256WithRSA"));
|
||||||
|
if (checkRes) {
|
||||||
|
// 校验InAppPurchaseData中的productId、price、currency等信息的一致性
|
||||||
|
checkRes = checkProductIdAndPriceAndCurrency(content, orderInfo);
|
||||||
|
}
|
||||||
|
return checkRes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验InAppPurchaseData中的productId、price、currency等信息的一致性
|
||||||
|
*
|
||||||
|
* @param content 结果字符串
|
||||||
|
* @param yourOrderInfo 您的订单信息,包括productId、price、currency
|
||||||
|
* @return 是否校验通过
|
||||||
|
*/
|
||||||
|
public static boolean checkProductIdAndPriceAndCurrency(String content, OrderInfo yourOrderInfo) {
|
||||||
|
InAppPurchaseData inAppPurchaseData = JSON.parseObject(content, InAppPurchaseData.class);
|
||||||
|
// 校验InAppPurchaseData中的productId、price、currency等信息的一致性
|
||||||
|
return inAppPurchaseData.getProductId().equals(yourOrderInfo.getGoodsId())
|
||||||
|
&& inAppPurchaseData.getPrice().equals(yourOrderInfo.getOrderAmt());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验签名信息
|
||||||
|
*
|
||||||
|
* @param content 结果字符串
|
||||||
|
* @param sign 签名字符串
|
||||||
|
* @param publicKey IAP公钥
|
||||||
|
* @param signatureAlgorithm 签名算法字段,可从接口返回数据中获取,例如:OwnedPurchasesResult.getSignatureAlgorithm()
|
||||||
|
* @return 是否校验通过
|
||||||
|
*/
|
||||||
|
public static boolean checkSign(String content, String sign, String publicKey, String signatureAlgorithm) {
|
||||||
|
if (sign == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (publicKey == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 当signatureAlgorithm为空时使用默认签名算法
|
||||||
|
if (signatureAlgorithm == null || signatureAlgorithm.length() == 0) {
|
||||||
|
signatureAlgorithm = "SHA256WithRSA";
|
||||||
|
System.out.println("doCheck, algorithm: SHA256WithRSA");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
|
||||||
|
// 生成"RSA"的KeyFactory对象
|
||||||
|
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||||
|
byte[] decodedKey = Base64.decodeBase64(publicKey);
|
||||||
|
// 生成公钥
|
||||||
|
PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(decodedKey));
|
||||||
|
java.security.Signature signature = null;
|
||||||
|
// 根据SHA256WithRSA算法获取签名对象实例
|
||||||
|
signature = java.security.Signature.getInstance(signatureAlgorithm);
|
||||||
|
// 初始化验证签名的公钥
|
||||||
|
signature.initVerify(pubKey);
|
||||||
|
// 把原始报文更新到签名对象中
|
||||||
|
signature.update(content.getBytes(StandardCharsets.UTF_8));
|
||||||
|
// 将sign解码
|
||||||
|
byte[] bsign = Base64.decodeBase64(sign);
|
||||||
|
// 进行验签
|
||||||
|
return signature.verify(bsign);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
throw e;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
110
sf-system/src/main/java/com/sf/system/domain/UserMember.java
Normal file
110
sf-system/src/main/java/com/sf/system/domain/UserMember.java
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
package com.sf.system.domain;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
|
import com.sf.common.annotation.Excel;
|
||||||
|
import com.sf.common.core.domain.BaseEntity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会员对象 User_member
|
||||||
|
*
|
||||||
|
* @author ztzh
|
||||||
|
* @date 2024-04-16
|
||||||
|
*/
|
||||||
|
public class UserMember extends BaseEntity
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** $column.columnComment */
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/** 用户会员等级(0普通会员 1订阅会员 2月度会员) */
|
||||||
|
@Excel(name = "用户会员等级", readConverterExp = "0=普通会员,1=订阅会员,2=月度会员")
|
||||||
|
private Integer memberLevel;
|
||||||
|
|
||||||
|
/** 会员等级为订阅会员时的订阅状态,未订阅就是取消了(0未订阅 1已订阅) */
|
||||||
|
@Excel(name = "会员等级为订阅会员时的订阅状态,未订阅就是取消了", readConverterExp = "0=未订阅,1=已订阅")
|
||||||
|
private Integer subscriptionStatus;
|
||||||
|
|
||||||
|
/** 关联的用户id */
|
||||||
|
@Excel(name = "关联的用户id")
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
/** 积分 */
|
||||||
|
@Excel(name = "积分")
|
||||||
|
private Long integration;
|
||||||
|
|
||||||
|
/** 过期时间 */
|
||||||
|
private Date expirationTime;
|
||||||
|
|
||||||
|
public void setId(Long id)
|
||||||
|
{
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId()
|
||||||
|
{
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
public void setMemberLevel(Integer memberLevel)
|
||||||
|
{
|
||||||
|
this.memberLevel = memberLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getMemberLevel()
|
||||||
|
{
|
||||||
|
return memberLevel;
|
||||||
|
}
|
||||||
|
public void setSubscriptionStatus(Integer subscriptionStatus)
|
||||||
|
{
|
||||||
|
this.subscriptionStatus = subscriptionStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getSubscriptionStatus()
|
||||||
|
{
|
||||||
|
return subscriptionStatus;
|
||||||
|
}
|
||||||
|
public void setUserId(Long userId)
|
||||||
|
{
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getUserId()
|
||||||
|
{
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
public void setIntegration(Long integration)
|
||||||
|
{
|
||||||
|
this.integration = integration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getIntegration()
|
||||||
|
{
|
||||||
|
return integration;
|
||||||
|
}
|
||||||
|
public void setExpirationTime(Date expirationTime)
|
||||||
|
{
|
||||||
|
this.expirationTime = expirationTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getExpirationTime()
|
||||||
|
{
|
||||||
|
return expirationTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||||
|
.append("id", getId())
|
||||||
|
.append("memberLevel", getMemberLevel())
|
||||||
|
.append("subscriptionStatus", getSubscriptionStatus())
|
||||||
|
.append("userId", getUserId())
|
||||||
|
.append("createTime", getCreateTime())
|
||||||
|
.append("updateTime", getUpdateTime())
|
||||||
|
.append("integration", getIntegration())
|
||||||
|
.append("expirationTime", getExpirationTime())
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
package com.sf.system.mapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import com.sf.system.domain.UserMember;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会员Mapper接口
|
||||||
|
*
|
||||||
|
* @author ztzh
|
||||||
|
* @date 2024-04-16
|
||||||
|
*/
|
||||||
|
public interface UserMemberMapper
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 查询会员
|
||||||
|
*
|
||||||
|
* @param id 会员主键
|
||||||
|
* @return 会员
|
||||||
|
*/
|
||||||
|
public UserMember selectUserMemberById(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询会员列表
|
||||||
|
*
|
||||||
|
* @param userMember 会员
|
||||||
|
* @return 会员集合
|
||||||
|
*/
|
||||||
|
public List<UserMember> selectUserMemberList(UserMember userMember);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增会员
|
||||||
|
*
|
||||||
|
* @param userMember 会员
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public int insertUserMember(UserMember userMember);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改会员
|
||||||
|
*
|
||||||
|
* @param userMember 会员
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public int updateUserMember(UserMember userMember);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除会员
|
||||||
|
*
|
||||||
|
* @param id 会员主键
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public int deleteUserMemberById(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除会员
|
||||||
|
*
|
||||||
|
* @param ids 需要删除的数据主键集合
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public int deleteUserMemberByIds(Long[] ids);
|
||||||
|
|
||||||
|
UserMember selectUserMemberByUserId(Long userId);
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
package com.sf.system.service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import com.sf.system.domain.UserMember;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会员Service接口
|
||||||
|
*
|
||||||
|
* @author ztzh
|
||||||
|
* @date 2024-04-16
|
||||||
|
*/
|
||||||
|
public interface IUserMemberService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 查询会员
|
||||||
|
*
|
||||||
|
* @param id 会员主键
|
||||||
|
* @return 会员
|
||||||
|
*/
|
||||||
|
public UserMember selectUserMemberById(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询会员列表
|
||||||
|
*
|
||||||
|
* @param userMember 会员
|
||||||
|
* @return 会员集合
|
||||||
|
*/
|
||||||
|
public List<UserMember> selectUserMemberList(UserMember userMember);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增会员
|
||||||
|
*
|
||||||
|
* @param userMember 会员
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public int insertUserMember(UserMember userMember);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改会员
|
||||||
|
*
|
||||||
|
* @param userMember 会员
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public int updateUserMember(UserMember userMember);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除会员
|
||||||
|
*
|
||||||
|
* @param ids 需要删除的会员主键集合
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public int deleteUserMemberByIds(Long[] ids);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除会员信息
|
||||||
|
*
|
||||||
|
* @param id 会员主键
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public int deleteUserMemberById(Long id);
|
||||||
|
|
||||||
|
UserMember selectUserMemberByUserId(Long userId);
|
||||||
|
}
|
@ -0,0 +1,101 @@
|
|||||||
|
package com.sf.system.service.impl;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import com.sf.common.utils.DateUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import com.sf.system.mapper.UserMemberMapper;
|
||||||
|
import com.sf.system.domain.UserMember;
|
||||||
|
import com.sf.system.service.IUserMemberService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会员Service业务层处理
|
||||||
|
*
|
||||||
|
* @author ztzh
|
||||||
|
* @date 2024-04-16
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class UserMemberServiceImpl implements IUserMemberService
|
||||||
|
{
|
||||||
|
@Autowired
|
||||||
|
private UserMemberMapper userMemberMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询会员
|
||||||
|
*
|
||||||
|
* @param id 会员主键
|
||||||
|
* @return 会员
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public UserMember selectUserMemberById(Long id)
|
||||||
|
{
|
||||||
|
return userMemberMapper.selectUserMemberById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询会员列表
|
||||||
|
*
|
||||||
|
* @param userMember 会员
|
||||||
|
* @return 会员
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<UserMember> selectUserMemberList(UserMember userMember)
|
||||||
|
{
|
||||||
|
return userMemberMapper.selectUserMemberList(userMember);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增会员
|
||||||
|
*
|
||||||
|
* @param userMember 会员
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int insertUserMember(UserMember userMember)
|
||||||
|
{
|
||||||
|
userMember.setCreateTime(DateUtils.getNowDate());
|
||||||
|
return userMemberMapper.insertUserMember(userMember);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改会员
|
||||||
|
*
|
||||||
|
* @param userMember 会员
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int updateUserMember(UserMember userMember)
|
||||||
|
{
|
||||||
|
userMember.setUpdateTime(DateUtils.getNowDate());
|
||||||
|
return userMemberMapper.updateUserMember(userMember);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除会员
|
||||||
|
*
|
||||||
|
* @param ids 需要删除的会员主键
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int deleteUserMemberByIds(Long[] ids)
|
||||||
|
{
|
||||||
|
return userMemberMapper.deleteUserMemberByIds(ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除会员信息
|
||||||
|
*
|
||||||
|
* @param id 会员主键
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int deleteUserMemberById(Long id)
|
||||||
|
{
|
||||||
|
return userMemberMapper.deleteUserMemberById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserMember selectUserMemberByUserId(Long userId) {
|
||||||
|
return userMemberMapper.selectUserMemberByUserId(userId);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,89 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.sf.system.mapper.UserMemberMapper">
|
||||||
|
|
||||||
|
<resultMap type="UserMember" id="UserMemberResult">
|
||||||
|
<result property="id" column="id" />
|
||||||
|
<result property="memberLevel" column="member_level" />
|
||||||
|
<result property="subscriptionStatus" column="subscription_status" />
|
||||||
|
<result property="userId" column="user_id" />
|
||||||
|
<result property="createTime" column="create_time" />
|
||||||
|
<result property="updateTime" column="update_time" />
|
||||||
|
<result property="integration" column="integration" />
|
||||||
|
<result property="expirationTime" column="expiration_time" />
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<sql id="selectUserMemberVo">
|
||||||
|
select id, member_level, subscription_status, user_id, create_time, update_time, integration, expiration_time from User_member
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<select id="selectUserMemberList" parameterType="UserMember" resultMap="UserMemberResult">
|
||||||
|
<include refid="selectUserMemberVo"/>
|
||||||
|
<where>
|
||||||
|
<if test="memberLevel != null "> and member_level = #{memberLevel}</if>
|
||||||
|
<if test="subscriptionStatus != null "> and subscription_status = #{subscriptionStatus}</if>
|
||||||
|
<if test="userId != null "> and user_id = #{userId}</if>
|
||||||
|
<if test="integration != null "> and integration = #{integration}</if>
|
||||||
|
<if test="expirationTime != null "> and expiration_time = #{expirationTime}</if>
|
||||||
|
</where>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectUserMemberById" parameterType="Long" resultMap="UserMemberResult">
|
||||||
|
<include refid="selectUserMemberVo"/>
|
||||||
|
where id = #{id}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectUserMemberByUserId" resultMap="UserMemberResult">
|
||||||
|
<include refid="selectUserMemberVo"/>
|
||||||
|
where user_id = #{userId}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<insert id="insertUserMember" parameterType="UserMember" useGeneratedKeys="true" keyProperty="id">
|
||||||
|
insert into User_member
|
||||||
|
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||||
|
<if test="memberLevel != null">member_level,</if>
|
||||||
|
<if test="subscriptionStatus != null">subscription_status,</if>
|
||||||
|
<if test="userId != null">user_id,</if>
|
||||||
|
<if test="createTime != null">create_time,</if>
|
||||||
|
<if test="updateTime != null">update_time,</if>
|
||||||
|
<if test="integration != null">integration,</if>
|
||||||
|
<if test="expirationTime != null">expiration_time,</if>
|
||||||
|
</trim>
|
||||||
|
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||||
|
<if test="memberLevel != null">#{memberLevel},</if>
|
||||||
|
<if test="subscriptionStatus != null">#{subscriptionStatus},</if>
|
||||||
|
<if test="userId != null">#{userId},</if>
|
||||||
|
<if test="createTime != null">#{createTime},</if>
|
||||||
|
<if test="updateTime != null">#{updateTime},</if>
|
||||||
|
<if test="integration != null">#{integration},</if>
|
||||||
|
<if test="expirationTime != null">#{expirationTime},</if>
|
||||||
|
</trim>
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<update id="updateUserMember" parameterType="UserMember">
|
||||||
|
update User_member
|
||||||
|
<trim prefix="SET" suffixOverrides=",">
|
||||||
|
<if test="memberLevel != null">member_level = #{memberLevel},</if>
|
||||||
|
<if test="subscriptionStatus != null">subscription_status = #{subscriptionStatus},</if>
|
||||||
|
<if test="userId != null">user_id = #{userId},</if>
|
||||||
|
<if test="createTime != null">create_time = #{createTime},</if>
|
||||||
|
<if test="updateTime != null">update_time = #{updateTime},</if>
|
||||||
|
<if test="integration != null">integration = #{integration},</if>
|
||||||
|
<if test="expirationTime != null">expiration_time = #{expirationTime},</if>
|
||||||
|
</trim>
|
||||||
|
where id = #{id}
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<delete id="deleteUserMemberById" parameterType="Long">
|
||||||
|
delete from User_member where id = #{id}
|
||||||
|
</delete>
|
||||||
|
|
||||||
|
<delete id="deleteUserMemberByIds" parameterType="String">
|
||||||
|
delete from User_member where id in
|
||||||
|
<foreach item="id" collection="array" open="(" separator="," close=")">
|
||||||
|
#{id}
|
||||||
|
</foreach>
|
||||||
|
</delete>
|
||||||
|
</mapper>
|
Loading…
x
Reference in New Issue
Block a user