华为应用内支付完成会员订购,会员与商品调整
This commit is contained in:
parent
3e251b4c48
commit
9400c9985c
11
pom.xml
11
pom.xml
@ -174,6 +174,17 @@
|
|||||||
<version>${sf.version}</version>
|
<version>${sf.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.smarterFramework</groupId>
|
||||||
|
<artifactId>sf-payment</artifactId>
|
||||||
|
<version>${sf.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.smarterFramework</groupId>
|
||||||
|
<artifactId>sf-service</artifactId>
|
||||||
|
<version>${sf.version}</version>
|
||||||
|
</dependency>
|
||||||
<!-- 通用工具-->
|
<!-- 通用工具-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.smarterFramework</groupId>
|
<groupId>com.smarterFramework</groupId>
|
||||||
|
@ -71,7 +71,15 @@
|
|||||||
<artifactId>sf-order</artifactId>
|
<artifactId>sf-order</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.smarterFramework</groupId>
|
||||||
|
<artifactId>sf-payment</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.smarterFramework</groupId>
|
||||||
|
<artifactId>sf-service</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
@ -18,7 +18,7 @@ sf:
|
|||||||
# 开发环境配置
|
# 开发环境配置
|
||||||
server:
|
server:
|
||||||
# 服务器的HTTP端口,默认为8080
|
# 服务器的HTTP端口,默认为8080
|
||||||
port: 7781
|
port: 80
|
||||||
servlet:
|
servlet:
|
||||||
# 应用的访问路径
|
# 应用的访问路径
|
||||||
context-path: /
|
context-path: /
|
||||||
|
@ -3,10 +3,8 @@ package com.sf.order.controller;
|
|||||||
import com.sf.common.annotation.Log;
|
import com.sf.common.annotation.Log;
|
||||||
import com.sf.common.core.controller.BaseController;
|
import com.sf.common.core.controller.BaseController;
|
||||||
import com.sf.common.core.domain.AjaxResult;
|
import com.sf.common.core.domain.AjaxResult;
|
||||||
import com.sf.common.core.domain.entity.SysUser;
|
|
||||||
import com.sf.common.core.page.TableDataInfo;
|
import com.sf.common.core.page.TableDataInfo;
|
||||||
import com.sf.common.enums.BusinessType;
|
import com.sf.common.enums.BusinessType;
|
||||||
import com.sf.common.utils.SecurityUtils;
|
|
||||||
import com.sf.common.utils.poi.ExcelUtil;
|
import com.sf.common.utils.poi.ExcelUtil;
|
||||||
import com.sf.order.domain.OrderInfo;
|
import com.sf.order.domain.OrderInfo;
|
||||||
import com.sf.order.domain.dto.OrderCreateDto;
|
import com.sf.order.domain.dto.OrderCreateDto;
|
||||||
|
@ -3,6 +3,7 @@ package com.sf.order.domain;
|
|||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import com.sf.common.annotation.Excel;
|
import com.sf.common.annotation.Excel;
|
||||||
import com.sf.common.core.domain.BaseEntity;
|
import com.sf.common.core.domain.BaseEntity;
|
||||||
|
import lombok.Data;
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
|
|
||||||
@ -14,6 +15,7 @@ import java.util.Date;
|
|||||||
* @author ztzh
|
* @author ztzh
|
||||||
* @date 2024-04-09
|
* @date 2024-04-09
|
||||||
*/
|
*/
|
||||||
|
@Data
|
||||||
public class OrderInfo extends BaseEntity {
|
public class OrderInfo extends BaseEntity {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@ -26,7 +28,7 @@ public class OrderInfo extends BaseEntity {
|
|||||||
* 订单编号
|
* 订单编号
|
||||||
*/
|
*/
|
||||||
@Excel(name = "订单编号")
|
@Excel(name = "订单编号")
|
||||||
private String orderNo;
|
private Long orderNo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 订单状态: 0:待支付 1:已付款待发货 2:配送中 3:待取货 4:支付超时系统结束 5:客户自主取消 6:已完成
|
* 订单状态: 0:待支付 1:已付款待发货 2:配送中 3:待取货 4:支付超时系统结束 5:客户自主取消 6:已完成
|
||||||
@ -155,209 +157,27 @@ public class OrderInfo extends BaseEntity {
|
|||||||
@Excel(name = "减免金额(优惠券抵扣)")
|
@Excel(name = "减免金额(优惠券抵扣)")
|
||||||
private Long reductionAmout;
|
private Long reductionAmout;
|
||||||
|
|
||||||
public void setId(Long id) {
|
/**
|
||||||
this.id = id;
|
* * 商品数量
|
||||||
}
|
*/
|
||||||
|
private Integer goodsCount;
|
||||||
|
/**
|
||||||
|
* * 商品类型。
|
||||||
|
* * • 0:消耗型商品
|
||||||
|
* * • 1:非消耗型商品
|
||||||
|
* * • 2:自动续期订阅商品
|
||||||
|
*/
|
||||||
|
private Integer goodsType;
|
||||||
|
|
||||||
public Long getId() {
|
/**
|
||||||
return id;
|
* 商品单价
|
||||||
}
|
*/
|
||||||
|
private Long goodsPrice;
|
||||||
|
|
||||||
public void setOrderNo(String orderNo) {
|
/**
|
||||||
this.orderNo = orderNo;
|
* 商品编号
|
||||||
}
|
*/
|
||||||
|
private String goodsCode;
|
||||||
|
|
||||||
public String getOrderNo() {
|
|
||||||
return orderNo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOrderStatus(Long orderStatus) {
|
|
||||||
this.orderStatus = orderStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getOrderStatus() {
|
|
||||||
return orderStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPayType(Long payType) {
|
|
||||||
this.payType = payType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getPayType() {
|
|
||||||
return payType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPayChannel(Long payChannel) {
|
|
||||||
this.payChannel = payChannel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getPayChannel() {
|
|
||||||
return payChannel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOrderAmt(Long orderAmt) {
|
|
||||||
this.orderAmt = orderAmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getOrderAmt() {
|
|
||||||
return orderAmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFreightAmt(Long freightAmt) {
|
|
||||||
this.freightAmt = freightAmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getFreightAmt() {
|
|
||||||
return freightAmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPayAmt(Long payAmt) {
|
|
||||||
this.payAmt = payAmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getPayAmt() {
|
|
||||||
return payAmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setReallyAmt(Long reallyAmt) {
|
|
||||||
this.reallyAmt = reallyAmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getReallyAmt() {
|
|
||||||
return reallyAmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setReceiveType(Long receiveType) {
|
|
||||||
this.receiveType = receiveType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getReceiveType() {
|
|
||||||
return receiveType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGoodsId(Long goodsId) {
|
|
||||||
this.goodsId = goodsId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getGoodsId() {
|
|
||||||
return goodsId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBusinessId(Long businessId) {
|
|
||||||
this.businessId = businessId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getBusinessId() {
|
|
||||||
return businessId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setReceiveAddrId(Long receiveAddrId) {
|
|
||||||
this.receiveAddrId = receiveAddrId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getReceiveAddrId() {
|
|
||||||
return receiveAddrId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPayTime(Date payTime) {
|
|
||||||
this.payTime = payTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Date getPayTime() {
|
|
||||||
return payTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCreateUserId(Long createUserId) {
|
|
||||||
this.createUserId = createUserId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getCreateUserId() {
|
|
||||||
return createUserId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUpdateUserId(Long updateUserId) {
|
|
||||||
this.updateUserId = updateUserId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getUpdateUserId() {
|
|
||||||
return updateUserId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIsDelete(Long isDelete) {
|
|
||||||
this.isDelete = isDelete;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getIsDelete() {
|
|
||||||
return isDelete;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTrackNo(String trackNo) {
|
|
||||||
this.trackNo = trackNo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTrackNo() {
|
|
||||||
return trackNo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOrderType(Long orderType) {
|
|
||||||
this.orderType = orderType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getOrderType() {
|
|
||||||
return orderType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOutOrderNo(String outOrderNo) {
|
|
||||||
this.outOrderNo = outOrderNo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getOutOrderNo() {
|
|
||||||
return outOrderNo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPayData(String payData) {
|
|
||||||
this.payData = payData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPayData() {
|
|
||||||
return payData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setReductionAmout(Long reductionAmout) {
|
|
||||||
this.reductionAmout = reductionAmout;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getReductionAmout() {
|
|
||||||
return reductionAmout;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
|
|
||||||
.append("id", getId())
|
|
||||||
.append("orderNo", getOrderNo())
|
|
||||||
.append("orderStatus", getOrderStatus())
|
|
||||||
.append("payType", getPayType())
|
|
||||||
.append("payChannel", getPayChannel())
|
|
||||||
.append("orderAmt", getOrderAmt())
|
|
||||||
.append("freightAmt", getFreightAmt())
|
|
||||||
.append("payAmt", getPayAmt())
|
|
||||||
.append("reallyAmt", getReallyAmt())
|
|
||||||
.append("receiveType", getReceiveType())
|
|
||||||
.append("goodsId", getGoodsId())
|
|
||||||
.append("businessId", getBusinessId())
|
|
||||||
.append("receiveAddrId", getReceiveAddrId())
|
|
||||||
.append("createTime", getCreateTime())
|
|
||||||
.append("payTime", getPayTime())
|
|
||||||
.append("createUserId", getCreateUserId())
|
|
||||||
.append("updateUserId", getUpdateUserId())
|
|
||||||
.append("isDelete", getIsDelete())
|
|
||||||
.append("updateTime", getUpdateTime())
|
|
||||||
.append("trackNo", getTrackNo())
|
|
||||||
.append("orderType", getOrderType())
|
|
||||||
.append("outOrderNo", getOutOrderNo())
|
|
||||||
.append("payData", getPayData())
|
|
||||||
.append("reductionAmout", getReductionAmout())
|
|
||||||
.toString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -71,5 +71,23 @@ public class OrderListResVo {
|
|||||||
*/
|
*/
|
||||||
private Integer goodsCount;
|
private Integer goodsCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品价格
|
||||||
|
*/
|
||||||
|
private Long goodsPrice;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* * 商品类型。
|
||||||
|
* * • 0:消耗型商品
|
||||||
|
* * • 1:非消耗型商品
|
||||||
|
* * • 2:自动续期订阅商品
|
||||||
|
*/
|
||||||
|
private Integer goodsType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品编码
|
||||||
|
*/
|
||||||
|
private String goodsCode;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -72,4 +72,7 @@ public interface IOrderInfoService
|
|||||||
void orderPay(Long orderId);
|
void orderPay(Long orderId);
|
||||||
|
|
||||||
OrderInfo selectOrderInfoByOrderNo(String orderNo);
|
OrderInfo selectOrderInfoByOrderNo(String orderNo);
|
||||||
|
|
||||||
|
void insertOrder(OrderInfo orderInfo);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ public class OrderInfoServiceImpl implements IOrderInfoService {
|
|||||||
@Override
|
@Override
|
||||||
public Long 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(1L);
|
orderInfo.setPayType(1L);
|
||||||
orderInfo.setReceiveType(0L);
|
orderInfo.setReceiveType(0L);
|
||||||
orderInfo.setOrderStatus(0L);
|
orderInfo.setOrderStatus(0L);
|
||||||
@ -113,6 +113,11 @@ public class OrderInfoServiceImpl implements IOrderInfoService {
|
|||||||
return orderInfoMapper.selectOrderInfoByOrderNo(orderNo);
|
return orderInfoMapper.selectOrderInfoByOrderNo(orderNo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void insertOrder(OrderInfo orderInfo) {
|
||||||
|
orderInfoMapper.insertOrderInfo(orderInfo);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量删除订单基础信息
|
* 批量删除订单基础信息
|
||||||
*
|
*
|
||||||
|
@ -42,13 +42,16 @@
|
|||||||
<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" />
|
<result property="subscriptionCancellationTime" column="subscription_cancellation_time" />
|
||||||
|
<result property="goodsType" column="goods_type" />
|
||||||
|
<result property="goodsPrice" column="goods_price" />
|
||||||
|
<result property="goodsCode" column="goods_code" />
|
||||||
</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.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
|
SELECT a.id,a.order_no,a.order_status,a.order_amt,a.pay_time,a.goods_count,a.subscription_cancellation_time,a.goods_type,a.goods_price,a.goods_code,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>
|
||||||
|
|
||||||
@ -124,6 +127,10 @@
|
|||||||
<if test="outOrderNo != null">out_order_no,</if>
|
<if test="outOrderNo != null">out_order_no,</if>
|
||||||
<if test="payData != null">pay_data,</if>
|
<if test="payData != null">pay_data,</if>
|
||||||
<if test="reductionAmout != null">reduction_amout,</if>
|
<if test="reductionAmout != null">reduction_amout,</if>
|
||||||
|
<if test="goodsCount != null">goods_count,</if>
|
||||||
|
<if test="goodsType != null">goods_type,</if>
|
||||||
|
<if test="goodsPrice != null">goods_price,</if>
|
||||||
|
<if test="goodsCode != null">goods_code,</if>
|
||||||
</trim>
|
</trim>
|
||||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||||
<if test="id != null">#{id},</if>
|
<if test="id != null">#{id},</if>
|
||||||
@ -150,6 +157,10 @@
|
|||||||
<if test="outOrderNo != null">#{outOrderNo},</if>
|
<if test="outOrderNo != null">#{outOrderNo},</if>
|
||||||
<if test="payData != null">#{payData},</if>
|
<if test="payData != null">#{payData},</if>
|
||||||
<if test="reductionAmout != null">#{reductionAmout},</if>
|
<if test="reductionAmout != null">#{reductionAmout},</if>
|
||||||
|
<if test="goodsCount != null">#{goodsCount},</if>
|
||||||
|
<if test="goodsType != null">#{goodsType},</if>
|
||||||
|
<if test="goodsPrice != null">#{goodsPrice},</if>
|
||||||
|
<if test="goodsCode != null">#{goodsCode},</if>
|
||||||
</trim>
|
</trim>
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
|
@ -30,11 +30,20 @@
|
|||||||
<groupId>com.smarterFramework</groupId>
|
<groupId>com.smarterFramework</groupId>
|
||||||
<artifactId>sf-order</artifactId>
|
<artifactId>sf-order</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.smarterFramework</groupId>
|
||||||
|
<artifactId>sf-service</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.bouncycastle</groupId>
|
<groupId>org.bouncycastle</groupId>
|
||||||
<artifactId>bcprov-jdk18on</artifactId>
|
<artifactId>bcprov-jdk18on</artifactId>
|
||||||
<version>1.73</version>
|
<version>1.73</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.auth0</groupId>
|
||||||
|
<artifactId>java-jwt</artifactId>
|
||||||
|
<version>4.4.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
public class HuaweiPaymentConfig {
|
public class HuaweiPaymentConfig {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 客户端id:对应各平台的appKey
|
* 客户端id:(oauth用)
|
||||||
*/
|
*/
|
||||||
@Value("${huawei.payment.clientId:110693217}")
|
@Value("${huawei.payment.clientId:110693217}")
|
||||||
private String clientId;
|
private String clientId;
|
||||||
@ -27,5 +27,11 @@ public class HuaweiPaymentConfig {
|
|||||||
@Value("${huawei.payment.clientSecret:1410c01bc71c7ba587175ae79e500137c70945acc1416a38127cf98a09a6f8ba}")
|
@Value("${huawei.payment.clientSecret:1410c01bc71c7ba587175ae79e500137c70945acc1416a38127cf98a09a6f8ba}")
|
||||||
private String clientSecret;
|
private String clientSecret;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用id
|
||||||
|
*/
|
||||||
|
@Value("${huawei.payment.appId:5765880207854169373}")
|
||||||
|
private String appId;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
package com.sf.payment.constant;
|
||||||
|
|
||||||
|
import io.jsonwebtoken.Claims;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品信息
|
||||||
|
*
|
||||||
|
* @author zoukun
|
||||||
|
*/
|
||||||
|
public class GoodsConstants {
|
||||||
|
/**
|
||||||
|
* 商品类型。
|
||||||
|
* • 0:消耗型商品
|
||||||
|
*/
|
||||||
|
public static final Integer GOODS_TYPE_CONSUMABLE = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品类型。
|
||||||
|
* • 1:非消耗型商品
|
||||||
|
*/
|
||||||
|
public static final Integer GOODS_TYPE_NON_CONSUMABLE = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品类型。
|
||||||
|
* • 2:自动续期订阅商品
|
||||||
|
*/
|
||||||
|
public static final Integer GOODS_TYPE_AUTOMATIC_RENEWAL_SUBSCRIPTION = 2;
|
||||||
|
|
||||||
|
}
|
@ -2,11 +2,13 @@ package com.sf.payment.controller;
|
|||||||
|
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.sf.common.core.domain.AjaxResult;
|
import com.sf.common.core.domain.AjaxResult;
|
||||||
|
import com.sf.payment.constant.GoodsConstants;
|
||||||
import com.sf.payment.domain.HuaweiPaymentCallback;
|
import com.sf.payment.domain.HuaweiPaymentCallback;
|
||||||
import com.sf.payment.domain.HuaweiPurchasesVerifyDTO;
|
import com.sf.payment.domain.HuaweiPurchasesVerifyDTO;
|
||||||
import com.sf.payment.service.IHuaweiPaymentService;
|
import com.sf.payment.service.IHuaweiPaymentService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@ -36,7 +38,7 @@ public class HuaweiPaymentController {
|
|||||||
/**
|
/**
|
||||||
* 华为购买验证
|
* 华为购买验证
|
||||||
*/
|
*/
|
||||||
@RequestMapping("/huawei/purchases/verify")
|
@PostMapping("/huawei/purchases/verify")
|
||||||
public AjaxResult purchasesVerify(@Validated @RequestBody HuaweiPurchasesVerifyDTO verifyDTO) {
|
public AjaxResult purchasesVerify(@Validated @RequestBody HuaweiPurchasesVerifyDTO verifyDTO) {
|
||||||
log.info("进入/huawei/purchases/tokens/verify: params:" + JSONObject.toJSONString(verifyDTO));
|
log.info("进入/huawei/purchases/tokens/verify: params:" + JSONObject.toJSONString(verifyDTO));
|
||||||
huaweiPaymentService.purchasesVerify(verifyDTO);
|
huaweiPaymentService.purchasesVerify(verifyDTO);
|
||||||
|
@ -1,42 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
@ -1,73 +0,0 @@
|
|||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -21,31 +21,33 @@ public class HuaweiPurchasesVerifyDTO implements Serializable {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 商品类别,取值包括:
|
* 商品类型。
|
||||||
*
|
* • 0:消耗型商品
|
||||||
* 0:消耗型商品
|
* • 1:非消耗型商品
|
||||||
* 1:非消耗型商品
|
* • 2:自动续期订阅商品
|
||||||
* 2:订阅型商品
|
|
||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
private Integer kind;
|
private Integer type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 待下发商品的购买Token,发起购买和查询待消费商品信息时均会返回purchaseToken参数。
|
* 包含订单信息的JWS格式数据。
|
||||||
|
* 可参见对返回结果验签
|
||||||
|
* 解码验签获取相关购买数据的JSON字符串,
|
||||||
|
* 其包含的参数请参见PurchaseOrderPayload。
|
||||||
*/
|
*/
|
||||||
@NotBlank(message = "待下发商品的购买Token不能为空")
|
private String jwsPurchaseOrder;
|
||||||
private String purchaseToken;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 待下发商品ID。商品ID来源于您在AppGallery Connect中配置商品信息时设置的商品ID。
|
* 包含订阅状态信息的
|
||||||
|
* JWS格式数据。
|
||||||
|
* 可参见对返回结果验签
|
||||||
|
* 解码验签获取相关订阅状态
|
||||||
|
* 信息的JSON字符串,
|
||||||
|
* 其包含的参数请参见
|
||||||
|
* SubGroupStatusPayload。
|
||||||
*/
|
*/
|
||||||
@NotBlank(message = "待下发商品ID不能为空")
|
private String jwsSubscriptionStatus;
|
||||||
private String productId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 订单号
|
|
||||||
*/
|
|
||||||
@NotBlank(message = "订单号不能为空")
|
|
||||||
private String orderNo;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
package com.sf.payment.domain;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 功能描述:
|
||||||
|
*
|
||||||
|
* @author a_kun
|
||||||
|
* @date 2024/4/17 14:41
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class HuaweiQueryResponse {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回码。
|
||||||
|
* • 0:成功。
|
||||||
|
* • 其他:失败,具体请参见错误码
|
||||||
|
*/
|
||||||
|
private String responseCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 响应描述。
|
||||||
|
*/
|
||||||
|
private String responseMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 包含已购订单相关状态信息的JWS格式数据。可参见对返回结果验签解码验签获取相关订单状态信息的JSON字符串,其包含的参数具体请参见表PurchaseOrderPayload说明。
|
||||||
|
*/
|
||||||
|
private String jwsPurchaseOrder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 包含已购订阅相关状态信息的JWS格式数据。可参见对返回结果验签解码验签获取相关订阅状态信息的JSON字符串,其包含的参数请参见SubGroupStatusPayload
|
||||||
|
*/
|
||||||
|
private String jwsSubGroupStatus;
|
||||||
|
}
|
@ -0,0 +1,165 @@
|
|||||||
|
package com.sf.payment.domain;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 功能描述:
|
||||||
|
* 订单信息模型,支持消耗型商品、非消耗型商品和自动续期订阅商品。
|
||||||
|
* @author a_kun
|
||||||
|
* @date 2024/4/16 15:29
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class PurchaseOrderPayload {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 具体一笔订单中对应的购买订单号ID。
|
||||||
|
*/
|
||||||
|
private String purchaseOrderId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 购买token,
|
||||||
|
* 在购买消耗型/非消耗型商品场景中与具体购买订单一一对应,
|
||||||
|
* 在自动续期订阅商品场景中与订阅ID一一对应。
|
||||||
|
*/
|
||||||
|
private String purchaseToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用ID。
|
||||||
|
*/
|
||||||
|
private String applicationId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品ID。每种商品必须有唯一的ID,由应用在PMS中维护,或者应用发起购买时传入。
|
||||||
|
* 说明
|
||||||
|
* 为避免资金损失,您在对支付结果验签成功后,必须对其进行校验。
|
||||||
|
*/
|
||||||
|
private String productId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品类型。具体取值如下:
|
||||||
|
* • 0:消耗型商品
|
||||||
|
* • 1:非消耗型商品
|
||||||
|
* • 2:自动续期订阅商品
|
||||||
|
*/
|
||||||
|
private Integer productType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 购买时间,UTC时间戳,以毫秒为单位。
|
||||||
|
* 如果没有完成购买,则没有值。
|
||||||
|
*/
|
||||||
|
private Long purchaseTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发货状态。具体取值如下:
|
||||||
|
* • 1:已发货
|
||||||
|
* • 2:未发货
|
||||||
|
*/
|
||||||
|
private Integer finishStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 价格,单位:分。
|
||||||
|
* 实际价格*100以后的值。商品实际价格精确到小数点后2位,例如此参数值为501,则表示商品实际价格为5.01。
|
||||||
|
*/
|
||||||
|
private Long price;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用定价货币的币种,请参见ISO 4217标准。
|
||||||
|
* 说明
|
||||||
|
* 为避免资金损失,您在对支付结果验签成功后,必须对其进行校验。
|
||||||
|
*/
|
||||||
|
private String currency;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商户侧保留信息,由您在调用支付接口时传入。
|
||||||
|
*/
|
||||||
|
private String developerPayload;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 购买订单撤销原因。
|
||||||
|
* • 0:其他
|
||||||
|
* • 1:用户遇到问题退款
|
||||||
|
*/
|
||||||
|
private Integer purchaseOrderRevocationReasonCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 购买订单撤销时间,
|
||||||
|
* UTC时间戳,以毫秒为单位。
|
||||||
|
*/
|
||||||
|
private Long revocationTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 优惠类型。
|
||||||
|
* • 1:推介促销
|
||||||
|
*/
|
||||||
|
private Integer offerTypeCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 优惠ID。
|
||||||
|
*/
|
||||||
|
private String offerId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 国家/地区码,用于区分国家/地区信息,请参见ISO 3166
|
||||||
|
*/
|
||||||
|
private String countryCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签名时间,UTC时间戳,以毫秒为单位。
|
||||||
|
*/
|
||||||
|
private Long signedTime;
|
||||||
|
|
||||||
|
// 以下参数只在自动续期订阅商品场景返回
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅连续购买段的唯一ID,
|
||||||
|
* 当用户切换商品不会重置此ID。
|
||||||
|
*/
|
||||||
|
private String subGroupGenerationId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅连续购买段的唯一ID,
|
||||||
|
* 当用户切换订阅商品时
|
||||||
|
* 此订阅ID会发生改变。
|
||||||
|
*/
|
||||||
|
private String subscriptionId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅组ID。
|
||||||
|
*/
|
||||||
|
private String subGroupId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 此次购买的有效周期,
|
||||||
|
* 采用ISO 8601格式。
|
||||||
|
* 例如:P1W表示一周,
|
||||||
|
* P1M表示一个月。
|
||||||
|
*/
|
||||||
|
private String duration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅周期段类型。
|
||||||
|
* • 0:正常周期段
|
||||||
|
* • 1:延期周期段
|
||||||
|
*/
|
||||||
|
private Integer durationTypeCode;
|
||||||
|
|
||||||
|
/*
|
||||||
|
ISO 8601的时间持续期限表示
|
||||||
|
在ISO 8601中,时间持续期限的表示采用了一种简洁而明确的格式,例如 “P10D”,其中 “P” 表示周期(Period),后面的数字表示周期的长度,而末尾的字母表示周期的单位。这种表示法主要用于描述时间段的长度,而不关注具体的时刻。
|
||||||
|
“P” 表示周期(Period): 此字母指示接下来的时间表示将是一个时间段的描述,而非具体的日期或时刻。
|
||||||
|
后面的数字: 这个数字表示时间段的长度,可以是整数或小数。它指示了在时间单位内的周期数量。
|
||||||
|
末尾的字母表示周期的单位: 在 “P10D” 中,末尾的 “D” 表示周期的单位是天(Days)。ISO 8601定义了多种可能的时间单位,包括:
|
||||||
|
Y(年): 表示年份,例如 “P2Y” 表示2年的时间段。
|
||||||
|
M(月): 表示月份,例如 “P3M” 表示3个月的时间段。
|
||||||
|
W(周): 表示周数,例如 “P1W” 表示1周的时间段。
|
||||||
|
D(日): 表示天数,例如 “P10D” 表示10天的时间段。
|
||||||
|
T(时间分隔符): 如果时间段中包含了时间信息,日期和时间之间用 “T” 分隔,例如 “P1DT12H” 表示1天12小时的时间段。
|
||||||
|
H(小时)、M(分钟)、S(秒): 用于表示时、分、秒的时间段长度,例如 “PT2H30M” 表示2小时30分钟的时间段。
|
||||||
|
示例:
|
||||||
|
“P1Y”: 表示1年的时间段。
|
||||||
|
“P3M”: 表示3个月的时间段。
|
||||||
|
“P2W”: 表示2周的时间段。
|
||||||
|
“P4DT6H30M”: 表示4天6小时30分钟的时间段。
|
||||||
|
*/
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package com.sf.payment.domain;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 功能描述:
|
||||||
|
* 已购订阅相关状态信息
|
||||||
|
* @author a_kun
|
||||||
|
* @date 2024/4/16 15:29
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class SubGroupStatusPayload {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用ID。
|
||||||
|
*/
|
||||||
|
private String applicationId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用包名。
|
||||||
|
*/
|
||||||
|
private String packageName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅组ID。
|
||||||
|
*/
|
||||||
|
private String subGroupId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅组中最后生效的
|
||||||
|
* 订阅状态
|
||||||
|
* SubscriptionStatus,
|
||||||
|
* 比如A切换B,B切换C,
|
||||||
|
* 此处是C的订阅状态。
|
||||||
|
*/
|
||||||
|
private SubscriptionStatus lastSubscriptionStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅组最近生效的
|
||||||
|
* 历史订阅状态
|
||||||
|
* SubscriptionStatus的列表,比如A切换B,B切换C,这里包含C,B,A三个订阅状态信息。
|
||||||
|
*/
|
||||||
|
private List<SubscriptionStatus> historySubscriptionStatusList;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,91 @@
|
|||||||
|
package com.sf.payment.domain;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 功能描述:
|
||||||
|
* 当前订阅最新的未来扣费计划
|
||||||
|
* @author a_kun
|
||||||
|
* @date 2024/4/16 15:29
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class SubRenewalInfo {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅连续购买段的唯一ID,
|
||||||
|
* 当用户切换商品不会重置此ID。
|
||||||
|
*/
|
||||||
|
private String subGroupGenerationId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下周期生效场景下,下期将续期的商品ID。
|
||||||
|
*/
|
||||||
|
private String nextRenewPeriodProductId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前生效的商品ID。
|
||||||
|
*/
|
||||||
|
private String productId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动续期状态。
|
||||||
|
* • 0:关闭
|
||||||
|
* • 1:打开
|
||||||
|
*/
|
||||||
|
private Integer autoRenewStatusCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统是否还在尝试扣费。
|
||||||
|
* • true:是
|
||||||
|
* • false:否
|
||||||
|
*/
|
||||||
|
private Boolean hasInBillingRetryPeriod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 目前涨价状态码。
|
||||||
|
* • 1:用户暂未同意涨价
|
||||||
|
* • 2:用户已同意涨价
|
||||||
|
*/
|
||||||
|
private Integer priceIncreaseStatusCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 优惠类型。
|
||||||
|
* • 1:推介促销
|
||||||
|
*/
|
||||||
|
private Integer offerTypeCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 优惠ID。
|
||||||
|
*/
|
||||||
|
private String offerId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下期续费价格,单位:分,取消订阅场景下不返回。
|
||||||
|
*/
|
||||||
|
private String renewalPrice;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 币种。
|
||||||
|
*/
|
||||||
|
private String currency;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 续期时间,UTC时间戳,以毫秒为单位。。
|
||||||
|
*/
|
||||||
|
private Long renewalTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅续期失败的原因。
|
||||||
|
* • 1:用户取消
|
||||||
|
* • 2:商品无效
|
||||||
|
* • 3:签约无效
|
||||||
|
* • 4:扣费异常
|
||||||
|
* • 5:用户不同意涨价
|
||||||
|
* • 6:未知
|
||||||
|
*/
|
||||||
|
private String expirationIntent;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
package com.sf.payment.domain;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 功能描述:
|
||||||
|
* 订阅组中最后生效的订阅状态
|
||||||
|
* @author a_kun
|
||||||
|
* @date 2024/4/16 15:29
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class SubscriptionStatus {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅连续购买段的唯一ID,
|
||||||
|
* 当用户切换商品不会重置此ID。
|
||||||
|
*/
|
||||||
|
private String subGroupGenerationId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅连续购买段的唯一ID,
|
||||||
|
* 当用户切换订阅商品时
|
||||||
|
* 此订阅ID会发生改变。
|
||||||
|
*/
|
||||||
|
private String subscriptionId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 购买token,
|
||||||
|
* 在购买消耗型/非消耗型商品场景中与具体购买订单一一对应,
|
||||||
|
* 在自动续期订阅商品场景中与订阅ID一一对应。
|
||||||
|
*/
|
||||||
|
private String purchaseToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅状态。
|
||||||
|
* • 1:生效状态
|
||||||
|
* • 2:已到期
|
||||||
|
* • 3:尝试扣费
|
||||||
|
* • 5:撤销
|
||||||
|
* • 6:暂停
|
||||||
|
*/
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动续期订阅商品的过期时间,UTC时间戳,以毫秒为单位。
|
||||||
|
*/
|
||||||
|
private Long expiresTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前订阅最新的一笔购买订单。包含的参数请参见PurchaseOrderPayload。
|
||||||
|
*/
|
||||||
|
private PurchaseOrderPayload lastPurchaseOrder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前订阅最新的购买订单列表,包含续期、延期、折算等产生的购买订单。
|
||||||
|
* 购买订单包含的参数请参见PurchaseOrderPayload。
|
||||||
|
*/
|
||||||
|
private List<PurchaseOrderPayload> recentPurchaseOrderList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前订阅最新的未来扣费计划,包含的参数请参见SubRenewalInfo。
|
||||||
|
*/
|
||||||
|
private SubRenewalInfo renewalInfo;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -6,26 +6,32 @@ import cn.hutool.core.date.DateUtil;
|
|||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.http.HttpUtil;
|
import cn.hutool.http.HttpUtil;
|
||||||
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSON;
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
import com.auth0.jwt.JWT;
|
||||||
|
import com.auth0.jwt.interfaces.DecodedJWT;
|
||||||
import com.sf.common.utils.SecurityUtils;
|
import com.sf.common.utils.SecurityUtils;
|
||||||
|
import com.sf.common.utils.SnowflakeIdWorker;
|
||||||
import com.sf.order.domain.OrderInfo;
|
import com.sf.order.domain.OrderInfo;
|
||||||
import com.sf.order.service.IOrderInfoService;
|
import com.sf.order.service.IOrderInfoService;
|
||||||
import com.sf.payment.config.HuaweiPaymentConfig;
|
import com.sf.payment.config.HuaweiPaymentConfig;
|
||||||
import com.sf.payment.domain.HuaweiPurchasesVerifyDTO;
|
import com.sf.payment.constant.GoodsConstants;
|
||||||
import com.sf.payment.domain.HuaweiPurchasesVerifyResponseDTO;
|
import com.sf.payment.domain.*;
|
||||||
import com.sf.payment.domain.InAppPurchaseData;
|
|
||||||
import com.sf.payment.service.IHuaweiPaymentService;
|
import com.sf.payment.service.IHuaweiPaymentService;
|
||||||
|
import com.sf.payment.utils.HuaweiTokenGenerator;
|
||||||
|
import com.sf.service.domain.GoodsMessages;
|
||||||
|
import com.sf.service.service.IGoodsMessagesService;
|
||||||
import com.sf.system.domain.UserMember;
|
import com.sf.system.domain.UserMember;
|
||||||
import com.sf.system.service.IUserMemberService;
|
import com.sf.system.service.IUserMemberService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.Base64Utils;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.KeyFactory;
|
import java.security.KeyFactory;
|
||||||
|
import java.security.MessageDigest;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.security.Security;
|
import java.security.Security;
|
||||||
import java.security.spec.X509EncodedKeySpec;
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
@ -45,58 +51,204 @@ import java.util.Map;
|
|||||||
@Service
|
@Service
|
||||||
public class HuaweiPaymentServiceImpl implements IHuaweiPaymentService {
|
public class HuaweiPaymentServiceImpl implements IHuaweiPaymentService {
|
||||||
|
|
||||||
// token url to get the authorization
|
/**
|
||||||
|
* 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 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 ORDER_STATUS_QUERY_URL = "/order/harmony/v1/application/order/status/query";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询自动续期订阅商品的最新状态。
|
||||||
|
*/
|
||||||
|
private static final String SUBSCRIPTION_STATUS_QUERY_URL = "/subscription/harmony/v1/application/subscription/status/query";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 站点信息。(中国)
|
||||||
|
*/
|
||||||
|
private static final String ROOT_URL = "https://iap.cloud.huawei.com";
|
||||||
|
|
||||||
private static final String PUBLIC_KEY = "PUBLIC_KEY";
|
private static final String PUBLIC_KEY = "PUBLIC_KEY";
|
||||||
|
|
||||||
@Autowired
|
@Resource
|
||||||
private IOrderInfoService orderInfoService;
|
private IOrderInfoService orderInfoService;
|
||||||
|
|
||||||
@Autowired
|
@Resource
|
||||||
private IUserMemberService userMemberService;
|
private IUserMemberService userMemberService;
|
||||||
|
|
||||||
@Autowired
|
@Resource
|
||||||
|
private IGoodsMessagesService goodsMessagesService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
private HuaweiPaymentConfig huaweiPaymentConfig;
|
private HuaweiPaymentConfig huaweiPaymentConfig;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SnowflakeIdWorker snowflakeIdWorker;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void purchasesVerify(HuaweiPurchasesVerifyDTO verifyDTO) {
|
public void purchasesVerify(HuaweiPurchasesVerifyDTO verifyDTO) {
|
||||||
// construct the Authorization in Header
|
// 待发放会员商品
|
||||||
Map<String, String> headers = buildAuthorization(getAppAT(huaweiPaymentConfig.getClientId(), huaweiPaymentConfig.getClientSecret()));
|
PurchaseOrderPayload huaweiQueryResponsePurchaseOrderPayload;
|
||||||
|
// 验证 TODO 证书验签官网未实现
|
||||||
|
if (GoodsConstants.GOODS_TYPE_CONSUMABLE.equals(verifyDTO.getType())
|
||||||
|
|| GoodsConstants.GOODS_TYPE_NON_CONSUMABLE.equals(verifyDTO.getType())) {
|
||||||
|
Assert.hasText(verifyDTO.getJwsPurchaseOrder(), "订单信息不能为空");
|
||||||
|
// 消耗/非消耗商品购买验证
|
||||||
|
consumablePurchasesVerify(verifyDTO.getJwsPurchaseOrder());
|
||||||
|
} else if (GoodsConstants.GOODS_TYPE_AUTOMATIC_RENEWAL_SUBSCRIPTION.equals(verifyDTO.getType())) {
|
||||||
|
Assert.hasText(verifyDTO.getJwsSubscriptionStatus(), "订单信息不能为空");
|
||||||
|
// 订阅商品购买验证
|
||||||
|
subscriptionPurchasesVerify(verifyDTO.getJwsSubscriptionStatus());
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("商品类型错误!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private PurchaseOrderPayload subscriptionPurchasesVerify(String jwsSubscriptionStatus) {
|
||||||
|
DecodedJWT decodedJWT = JWT.decode(jwsSubscriptionStatus);
|
||||||
|
//String header = decodedJWT.getHeader();
|
||||||
|
String payload = decodedJWT.getPayload();
|
||||||
|
// 前面应该不是base64编码后的,官网说都是编码后的,但是解码会报错
|
||||||
|
//String signature = decodedJWT.getSignature();
|
||||||
|
String decodeAppPayload = new String(Base64Utils.decode(payload.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8);
|
||||||
|
// String decodeHeader = new String(Base64Utils.decode(header.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8);
|
||||||
|
// String decodeSignature = new String(Base64Utils.decode(signature.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8);
|
||||||
|
SubGroupStatusPayload appSubGroupStatusPayload = JSON.parseObject(decodeAppPayload, SubGroupStatusPayload.class);
|
||||||
|
SubscriptionStatus lastSubscriptionStatus = appSubGroupStatusPayload.getLastSubscriptionStatus();
|
||||||
|
PurchaseOrderPayload lastPurchaseOrder = lastSubscriptionStatus.getLastPurchaseOrder();
|
||||||
// pack the request body
|
// pack the request body
|
||||||
Map<String, String> bodyMap = new HashMap<>();
|
Map<String, String> bodyMap = new HashMap<>();
|
||||||
bodyMap.put("purchaseToken", verifyDTO.getPurchaseToken());
|
bodyMap.put("purchaseToken", lastPurchaseOrder.getPurchaseToken());
|
||||||
bodyMap.put("productId", verifyDTO.getProductId());
|
bodyMap.put("purchaseOrderId", lastPurchaseOrder.getPurchaseOrderId());
|
||||||
|
// construct the Authorization in Header
|
||||||
|
Map<String, String> headers = buildAuthorization(huaweiPaymentConfig.getAppId(), bodyMap);
|
||||||
|
|
||||||
String response = HttpUtil.createPost(VERIFY_TOKEN_URL)
|
// 订阅状态查询
|
||||||
|
String response = HttpUtil.createPost(ROOT_URL + SUBSCRIPTION_STATUS_QUERY_URL)
|
||||||
.addHeaders(headers)
|
.addHeaders(headers)
|
||||||
.body(JSON.toJSONString(bodyMap))
|
.body(JSON.toJSONString(bodyMap))
|
||||||
.execute().body();
|
.execute().body();
|
||||||
HuaweiPurchasesVerifyResponseDTO huaweiPurchasesVerifyResponseDTO = JSON.parseObject(response, HuaweiPurchasesVerifyResponseDTO.class);
|
log.info("订单状态查询返回信息:{}", response);
|
||||||
InAppPurchaseData inAppPurchaseData = JSON.parseObject(huaweiPurchasesVerifyResponseDTO.getPurchaseTokenData(), InAppPurchaseData.class);
|
HuaweiQueryResponse huaweiQueryResponse = JSON.parseObject(response, HuaweiQueryResponse.class);
|
||||||
// 获取服务订单
|
if (!"0".equals(huaweiQueryResponse.getResponseCode())) {
|
||||||
OrderInfo orderInfo = orderInfoService.selectOrderInfoByOrderNo(verifyDTO.getOrderNo());
|
throw new RuntimeException("订单状态查询失败");
|
||||||
// 校验订单
|
}
|
||||||
boolean checkSuccessOrder = checkSuccessOrder(huaweiPurchasesVerifyResponseDTO.getPurchaseTokenData()
|
DecodedJWT huaweiQueryResponseDecodedJWT = JWT.decode(huaweiQueryResponse.getJwsSubGroupStatus());
|
||||||
, huaweiPurchasesVerifyResponseDTO.getDataSignature()
|
String huaweiQueryResponsepayload = huaweiQueryResponseDecodedJWT.getPayload();
|
||||||
, PUBLIC_KEY
|
String decodeHuaweiQueryResponsepayload = new String(Base64Utils.decode(huaweiQueryResponsepayload.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8);
|
||||||
, huaweiPurchasesVerifyResponseDTO.getSignatureAlgorithm()
|
SubGroupStatusPayload subGroupStatusPayload = JSON.parseObject(decodeHuaweiQueryResponsepayload, SubGroupStatusPayload.class);
|
||||||
, orderInfo);
|
PurchaseOrderPayload huaweiQueryResponsePurchaseOrderPayload = subGroupStatusPayload.getLastSubscriptionStatus().getLastPurchaseOrder();
|
||||||
|
// 发货
|
||||||
|
return delivery(lastPurchaseOrder, huaweiQueryResponsePurchaseOrderPayload);
|
||||||
|
}
|
||||||
|
|
||||||
Assert.isTrue(checkSuccessOrder, "订单校验失败,请重试");
|
/**
|
||||||
Assert.isTrue(inAppPurchaseData.getPurchaseState()==0, "订单未完成购买");
|
* 发货
|
||||||
DateTime payTime = DateUtil.date(inAppPurchaseData.getPurchaseTime());
|
* @param purchaseOrder
|
||||||
UserMember userMember = userMemberService.selectUserMemberByUserId(orderInfo.getCreateUserId());
|
* @param huaweiQueryResponsePurchaseOrderPayload
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private PurchaseOrderPayload delivery(PurchaseOrderPayload purchaseOrder, PurchaseOrderPayload huaweiQueryResponsePurchaseOrderPayload) {
|
||||||
|
Assert.isTrue(purchaseOrder.getPurchaseOrderId().equals(huaweiQueryResponsePurchaseOrderPayload.getPurchaseOrderId()), "订单不一致,发货失败!");
|
||||||
|
if (2 == huaweiQueryResponsePurchaseOrderPayload.getFinishStatus()) {
|
||||||
|
// 还未发货
|
||||||
|
// 查询平台是否配置该商品
|
||||||
|
// 查询平台是否配置该商品
|
||||||
|
GoodsMessages goods = goodsMessagesService.selectGoodsMessagesByCode(huaweiQueryResponsePurchaseOrderPayload.getProductId());
|
||||||
|
Assert.notNull(goods, "未配置此商品,请检查商品配置");
|
||||||
|
Assert.isTrue(goods.getOriginalPrice().equals(huaweiQueryResponsePurchaseOrderPayload.getPrice()), "商品价格与订单价格不一致,请检查价格配置");
|
||||||
|
// 创建完成订单
|
||||||
|
createOrder(huaweiQueryResponsePurchaseOrderPayload, goods);
|
||||||
|
// 发放会员权益
|
||||||
|
distributeMembershipBenefits(huaweiQueryResponsePurchaseOrderPayload);
|
||||||
|
} else {
|
||||||
|
log.info("华为应用内支付订单已发货!{}", JSON.toJSONString(huaweiQueryResponsePurchaseOrderPayload));
|
||||||
|
}
|
||||||
|
return huaweiQueryResponsePurchaseOrderPayload;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PurchaseOrderPayload consumablePurchasesVerify(String jwsPurchaseOrder) {
|
||||||
|
DecodedJWT decodedJWT = JWT.decode(jwsPurchaseOrder);
|
||||||
|
//String header = decodedJWT.getHeader();
|
||||||
|
String payload = decodedJWT.getPayload();
|
||||||
|
// 前面应该不是base64编码后的,官网说都是编码后的,但是解码会报错
|
||||||
|
//String signature = decodedJWT.getSignature();
|
||||||
|
String decodeAppPayload = new String(Base64Utils.decode(payload.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8);
|
||||||
|
// String decodeHeader = new String(Base64Utils.decode(header.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8);
|
||||||
|
// String decodeSignature = new String(Base64Utils.decode(signature.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8);
|
||||||
|
PurchaseOrderPayload appPurchaseOrderPayload = JSON.parseObject(decodeAppPayload, PurchaseOrderPayload.class);
|
||||||
|
// pack the request body
|
||||||
|
Map<String, String> bodyMap = new HashMap<>();
|
||||||
|
bodyMap.put("purchaseToken", appPurchaseOrderPayload.getPurchaseToken());
|
||||||
|
bodyMap.put("purchaseOrderId", appPurchaseOrderPayload.getPurchaseOrderId());
|
||||||
|
// construct the Authorization in Header
|
||||||
|
Map<String, String> headers = buildAuthorization(huaweiPaymentConfig.getAppId(), bodyMap);
|
||||||
|
|
||||||
|
// 订单状态查询
|
||||||
|
String response = HttpUtil.createPost(ROOT_URL + ORDER_STATUS_QUERY_URL)
|
||||||
|
.addHeaders(headers)
|
||||||
|
.body(JSON.toJSONString(bodyMap))
|
||||||
|
.execute().body();
|
||||||
|
log.info("订单状态查询返回信息:{}", response);
|
||||||
|
HuaweiQueryResponse huaweiQueryResponse = JSON.parseObject(response, HuaweiQueryResponse.class);
|
||||||
|
if (!"0".equals(huaweiQueryResponse.getResponseCode())) {
|
||||||
|
throw new RuntimeException("订单状态查询失败");
|
||||||
|
}
|
||||||
|
DecodedJWT huaweiQueryResponseDecodedJWT = JWT.decode(huaweiQueryResponse.getJwsPurchaseOrder());
|
||||||
|
// String huaweiQueryResponseHeader = huaweiQueryResponseDecodedJWT.getHeader();
|
||||||
|
String huaweiQueryResponsepayload = huaweiQueryResponseDecodedJWT.getPayload();
|
||||||
|
// String huaweiQueryResponsesignature = huaweiQueryResponseDecodedJWT.getSignature();
|
||||||
|
|
||||||
|
//String decodehuaweiQueryResponseHeader = new String(Base64Utils.decode(huaweiQueryResponseHeader.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8);
|
||||||
|
String decodehuaweiQueryResponsepayload = new String(Base64Utils.decode(huaweiQueryResponsepayload.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8);
|
||||||
|
// String decodehuaweiQueryResponsesignature = new String(Base64Utils.decode(huaweiQueryResponsesignature.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8);
|
||||||
|
|
||||||
|
PurchaseOrderPayload huaweiQueryResponsePurchaseOrderPayload = JSON.parseObject(decodehuaweiQueryResponsepayload, PurchaseOrderPayload.class);
|
||||||
|
// 暂时只做简单验证
|
||||||
|
return delivery(appPurchaseOrderPayload, huaweiQueryResponsePurchaseOrderPayload);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createOrder(PurchaseOrderPayload appPurchaseOrderPayload, GoodsMessages goods) {
|
||||||
|
Long userId = SecurityUtils.getUserId();
|
||||||
|
OrderInfo orderInfo = new OrderInfo();
|
||||||
|
orderInfo.setOrderNo(snowflakeIdWorker.nextId());
|
||||||
|
orderInfo.setOrderStatus(6L);
|
||||||
|
orderInfo.setPayType(1L);
|
||||||
|
orderInfo.setPayChannel(2L);
|
||||||
|
orderInfo.setOrderAmt(appPurchaseOrderPayload.getPrice());
|
||||||
|
orderInfo.setPayAmt(appPurchaseOrderPayload.getPrice());
|
||||||
|
orderInfo.setReallyAmt(appPurchaseOrderPayload.getPrice());
|
||||||
|
orderInfo.setReceiveType(0L);
|
||||||
|
orderInfo.setGoodsId(goods.getId());
|
||||||
|
orderInfo.setPayTime(DateUtil.date(appPurchaseOrderPayload.getPurchaseTime()));
|
||||||
|
orderInfo.setCreateUserId(userId);
|
||||||
|
orderInfo.setUpdateUserId(userId);
|
||||||
|
orderInfo.setOutOrderNo(appPurchaseOrderPayload.getPurchaseOrderId());
|
||||||
|
orderInfo.setPayData(JSON.toJSONString(appPurchaseOrderPayload));
|
||||||
|
orderInfo.setGoodsPrice(goods.getOriginalPrice());
|
||||||
|
orderInfo.setGoodsType(goods.getGoodsType());
|
||||||
|
orderInfo.setGoodsCode(goods.getGoodsCode());
|
||||||
|
orderInfoService.insertOrder(orderInfo);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void distributeMembershipBenefits(PurchaseOrderPayload purchaseOrderPayload) {
|
||||||
|
// 发放会员权益
|
||||||
|
Long userId = SecurityUtils.getUserId();
|
||||||
|
UserMember userMember = userMemberService.selectUserMemberByUserId(userId);
|
||||||
if (userMember == null) {
|
if (userMember == null) {
|
||||||
// 添加会员信息
|
// 添加会员信息
|
||||||
boolean isSubscription = verifyDTO.getKind() == 2;
|
boolean isSubscription = GoodsConstants.GOODS_TYPE_AUTOMATIC_RENEWAL_SUBSCRIPTION.equals(purchaseOrderPayload.getProductType());
|
||||||
|
DateTime payTime = DateUtil.date(purchaseOrderPayload.getPurchaseTime());
|
||||||
userMember = new UserMember();
|
userMember = new UserMember();
|
||||||
userMember.setMemberLevel(isSubscription ? 1 : 2);
|
userMember.setMemberLevel(isSubscription ? 1 : 2);
|
||||||
userMember.setSubscriptionStatus(isSubscription ? 1 : 0);
|
userMember.setSubscriptionStatus(isSubscription ? 1 : 0);
|
||||||
userMember.setUserId(orderInfo.getCreateUserId());
|
userMember.setUserId(userId);
|
||||||
userMember.setIntegration(0L);
|
userMember.setIntegration(0L);
|
||||||
DateTime expirationTime = DateUtil.offset(payTime, DateField.MONTH, 1);
|
DateTime expirationTime = DateUtil.offset(payTime, DateField.MONTH, 1);
|
||||||
userMember.setExpirationTime(expirationTime);
|
userMember.setExpirationTime(expirationTime);
|
||||||
@ -110,48 +262,56 @@ public class HuaweiPaymentServiceImpl implements IHuaweiPaymentService {
|
|||||||
userMember.setUpdateTime(new Date());
|
userMember.setUpdateTime(new Date());
|
||||||
userMemberService.updateUserMember(userMember);
|
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
|
* Build Authorization in Header
|
||||||
*
|
*
|
||||||
* @param appAt appAt
|
|
||||||
* @return headers
|
* @return headers
|
||||||
*/
|
*/
|
||||||
public static Map<String, String> buildAuthorization(String appAt) {
|
public static Map<String, String> buildAuthorization(String appId, Map<String, String> body) {
|
||||||
String oriString = MessageFormat.format("APPAT:{0}", appAt);
|
Map<String, Object> jwtHeader = new HashMap<>(8);
|
||||||
String authorization =
|
jwtHeader.put("alg", "ES256");
|
||||||
MessageFormat.format("Basic {0}", Base64.encodeBase64String(oriString.getBytes(StandardCharsets.UTF_8)));
|
jwtHeader.put("typ", "JWT");
|
||||||
|
jwtHeader.put("kid", "0ae3e1be-374b-43a5-a297-045addbf76eb");
|
||||||
|
Map<String, Object> jwtPayload = new HashMap<>(8);
|
||||||
|
jwtPayload.put("iss", "f59509e6-dd17-4644-b832-ff05233146c8");
|
||||||
|
jwtPayload.put("aud", "iap-v1");
|
||||||
|
jwtPayload.put("iat", DateUtil.currentSeconds());
|
||||||
|
jwtPayload.put("exp", DateUtil.currentSeconds() + 1800L); // 半小时过期
|
||||||
|
jwtPayload.put("aid", appId);
|
||||||
|
jwtPayload.put("digest", getJwtPayloadDigest(body));
|
||||||
|
|
||||||
|
String token = HuaweiTokenGenerator.createToken(jwtHeader, jwtPayload);
|
||||||
|
// String authorization = MessageFormat.format("Basic {0}", Base64.encodeBase64String(oriString.getBytes(StandardCharsets.UTF_8)));
|
||||||
|
String authorization = MessageFormat.format("Bearer {0}", token);
|
||||||
Map<String, String> headers = new HashMap<>();
|
Map<String, String> headers = new HashMap<>();
|
||||||
headers.put("Authorization", authorization);
|
headers.put("Authorization", authorization);
|
||||||
headers.put("Content-Type", "application/json; charset=UTF-8");
|
headers.put("Content-Type", "application/json; charset=UTF-8");
|
||||||
return headers;
|
return headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String getJwtPayloadDigest(Map<String, String> body) {
|
||||||
|
try {
|
||||||
|
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
|
||||||
|
messageDigest.update(JSON.toJSONString(body).getBytes(StandardCharsets.UTF_8));
|
||||||
|
byte[] digestByte = messageDigest.digest();
|
||||||
|
StringBuilder stringBuffer = new StringBuilder();
|
||||||
|
String temp;
|
||||||
|
for (byte aByte : digestByte) {
|
||||||
|
temp = Integer.toHexString(aByte & 0xFF);
|
||||||
|
if (temp.length() == 1) {
|
||||||
|
stringBuffer.append("0");
|
||||||
|
}
|
||||||
|
stringBuffer.append(temp);
|
||||||
|
}
|
||||||
|
return stringBuffer.toString();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验签名信息,校验InAppPurchaseData中的productId、price、currency等信息的一致性
|
* 校验签名信息,校验InAppPurchaseData中的productId、price、currency等信息的一致性
|
||||||
*
|
*
|
||||||
@ -173,15 +333,15 @@ public class HuaweiPaymentServiceImpl implements IHuaweiPaymentService {
|
|||||||
/**
|
/**
|
||||||
* 校验InAppPurchaseData中的productId、price、currency等信息的一致性
|
* 校验InAppPurchaseData中的productId、price、currency等信息的一致性
|
||||||
*
|
*
|
||||||
* @param content 结果字符串
|
* @param content 结果字符串
|
||||||
* @param yourOrderInfo 您的订单信息,包括productId、price、currency
|
* @param orderInfo 您的订单信息,包括productId、price、currency
|
||||||
* @return 是否校验通过
|
* @return 是否校验通过
|
||||||
*/
|
*/
|
||||||
public static boolean checkProductIdAndPriceAndCurrency(String content, OrderInfo yourOrderInfo) {
|
public static boolean checkProductIdAndPriceAndCurrency(String content, OrderInfo orderInfo) {
|
||||||
InAppPurchaseData inAppPurchaseData = JSON.parseObject(content, InAppPurchaseData.class);
|
InAppPurchaseData inAppPurchaseData = JSON.parseObject(content, InAppPurchaseData.class);
|
||||||
// 校验InAppPurchaseData中的productId、price、currency等信息的一致性
|
// 校验InAppPurchaseData中的productId、price、currency等信息的一致性
|
||||||
return inAppPurchaseData.getProductId().equals(yourOrderInfo.getGoodsId())
|
return inAppPurchaseData.getProductId().equals(orderInfo.getGoodsId())
|
||||||
&& inAppPurchaseData.getPrice().equals(yourOrderInfo.getOrderAmt());
|
&& inAppPurchaseData.getPrice().equals(orderInfo.getOrderAmt());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
package com.sf.payment.utils;
|
||||||
|
import cn.hutool.core.io.resource.ClassPathResource;
|
||||||
|
import com.auth0.jwt.JWT;
|
||||||
|
import com.auth0.jwt.algorithms.Algorithm;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.KeyFactory;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.interfaces.ECPrivateKey;
|
||||||
|
import java.security.spec.InvalidKeySpecException;
|
||||||
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class HuaweiTokenGenerator {
|
||||||
|
|
||||||
|
public static String createToken(Map<String, Object> jwtHeader, Map<String, Object> jwtPayload) {
|
||||||
|
try {
|
||||||
|
// AppGallery Connect 华为应用内支付配置密钥,下载私钥文件
|
||||||
|
ClassPathResource classPathResource = new ClassPathResource("IAPKey_0ae3e1be-374b-43a5-a297-045addbf76eb.p8");
|
||||||
|
InputStream IAPKeyStream = classPathResource.getStream();
|
||||||
|
String content = IOUtils.toString(IAPKeyStream, String.valueOf(StandardCharsets.UTF_8));
|
||||||
|
String privateKey = content
|
||||||
|
.replace("-----BEGIN PRIVATE KEY-----", "")
|
||||||
|
.replaceAll("\\R+", "")
|
||||||
|
.replace("-----END PRIVATE KEY-----", "");
|
||||||
|
KeyFactory keyFactory = KeyFactory.getInstance("EC");
|
||||||
|
byte[] privateKeyBytes = Base64.getDecoder().decode(privateKey);
|
||||||
|
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
|
||||||
|
ECPrivateKey ecPrivateKey = (ECPrivateKey) keyFactory.generatePrivate(keySpec);
|
||||||
|
return JWT.create()
|
||||||
|
.withHeader(jwtHeader)
|
||||||
|
.withPayload(jwtPayload)
|
||||||
|
.sign(Algorithm.ECDSA256(ecPrivateKey));
|
||||||
|
} catch (IOException | NoSuchAlgorithmException | InvalidKeySpecException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQggG04243qynU/yWYy
|
||||||
|
XpYVy9ZWMuLKzZiwhXCBWQBCOLigCgYIKoZIzj0DAQehRANCAARNln2/d+TM2pIO
|
||||||
|
LWQzvI77gPAVEvVCSlIuiJ+J7CJSG5KCysBaEeiiD5cc4dZWnUBijF8FBh7nDLaH
|
||||||
|
VwFXfrS+
|
||||||
|
-----END PRIVATE KEY-----
|
33
sf-service/pom.xml
Normal file
33
sf-service/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-service</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>
|
@ -1,7 +1,10 @@
|
|||||||
package com.sf.goods.controller;
|
package com.sf.service.controller;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import com.sf.service.domain.GoodsMessages;
|
||||||
|
import com.sf.service.service.IGoodsMessagesService;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
@ -16,19 +19,17 @@ import com.sf.common.annotation.Log;
|
|||||||
import com.sf.common.core.controller.BaseController;
|
import com.sf.common.core.controller.BaseController;
|
||||||
import com.sf.common.core.domain.AjaxResult;
|
import com.sf.common.core.domain.AjaxResult;
|
||||||
import com.sf.common.enums.BusinessType;
|
import com.sf.common.enums.BusinessType;
|
||||||
import com.sf.goods.domain.GoodsMessages;
|
|
||||||
import com.sf.goods.service.IGoodsMessagesService;
|
|
||||||
import com.sf.common.utils.poi.ExcelUtil;
|
import com.sf.common.utils.poi.ExcelUtil;
|
||||||
import com.sf.common.core.page.TableDataInfo;
|
import com.sf.common.core.page.TableDataInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 商品信息Controller
|
* 商品信息Controller
|
||||||
*
|
*
|
||||||
* @author ztzh
|
* @author zoukun
|
||||||
* @date 2024-04-11
|
* @date 2024-04-18
|
||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/goods/goods")
|
@RequestMapping("/service/goods")
|
||||||
public class GoodsMessagesController extends BaseController
|
public class GoodsMessagesController extends BaseController
|
||||||
{
|
{
|
||||||
@Autowired
|
@Autowired
|
||||||
@ -37,7 +38,7 @@ public class GoodsMessagesController extends BaseController
|
|||||||
/**
|
/**
|
||||||
* 查询商品信息列表
|
* 查询商品信息列表
|
||||||
*/
|
*/
|
||||||
@PreAuthorize("@ss.hasPermi('goods:goods:list')")
|
@PreAuthorize("@ss.hasPermi('service:goods:list')")
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
public TableDataInfo list(GoodsMessages goodsMessages)
|
public TableDataInfo list(GoodsMessages goodsMessages)
|
||||||
{
|
{
|
||||||
@ -49,7 +50,7 @@ public class GoodsMessagesController extends BaseController
|
|||||||
/**
|
/**
|
||||||
* 导出商品信息列表
|
* 导出商品信息列表
|
||||||
*/
|
*/
|
||||||
@PreAuthorize("@ss.hasPermi('goods:goods:export')")
|
@PreAuthorize("@ss.hasPermi('service:goods:export')")
|
||||||
@Log(title = "商品信息", businessType = BusinessType.EXPORT)
|
@Log(title = "商品信息", businessType = BusinessType.EXPORT)
|
||||||
@PostMapping("/export")
|
@PostMapping("/export")
|
||||||
public void export(HttpServletResponse response, GoodsMessages goodsMessages)
|
public void export(HttpServletResponse response, GoodsMessages goodsMessages)
|
||||||
@ -62,7 +63,7 @@ public class GoodsMessagesController extends BaseController
|
|||||||
/**
|
/**
|
||||||
* 获取商品信息详细信息
|
* 获取商品信息详细信息
|
||||||
*/
|
*/
|
||||||
@PreAuthorize("@ss.hasPermi('goods:goods:query')")
|
@PreAuthorize("@ss.hasPermi('service:goods:query')")
|
||||||
@GetMapping(value = "/{id}")
|
@GetMapping(value = "/{id}")
|
||||||
public AjaxResult getInfo(@PathVariable("id") Long id)
|
public AjaxResult getInfo(@PathVariable("id") Long id)
|
||||||
{
|
{
|
||||||
@ -72,7 +73,7 @@ public class GoodsMessagesController extends BaseController
|
|||||||
/**
|
/**
|
||||||
* 新增商品信息
|
* 新增商品信息
|
||||||
*/
|
*/
|
||||||
@PreAuthorize("@ss.hasPermi('goods:goods:add')")
|
@PreAuthorize("@ss.hasPermi('service:goods:add')")
|
||||||
@Log(title = "商品信息", businessType = BusinessType.INSERT)
|
@Log(title = "商品信息", businessType = BusinessType.INSERT)
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public AjaxResult add(@RequestBody GoodsMessages goodsMessages)
|
public AjaxResult add(@RequestBody GoodsMessages goodsMessages)
|
||||||
@ -83,7 +84,7 @@ public class GoodsMessagesController extends BaseController
|
|||||||
/**
|
/**
|
||||||
* 修改商品信息
|
* 修改商品信息
|
||||||
*/
|
*/
|
||||||
@PreAuthorize("@ss.hasPermi('goods:goods:edit')")
|
@PreAuthorize("@ss.hasPermi('service:goods:edit')")
|
||||||
@Log(title = "商品信息", businessType = BusinessType.UPDATE)
|
@Log(title = "商品信息", businessType = BusinessType.UPDATE)
|
||||||
@PutMapping
|
@PutMapping
|
||||||
public AjaxResult edit(@RequestBody GoodsMessages goodsMessages)
|
public AjaxResult edit(@RequestBody GoodsMessages goodsMessages)
|
||||||
@ -94,9 +95,9 @@ public class GoodsMessagesController extends BaseController
|
|||||||
/**
|
/**
|
||||||
* 删除商品信息
|
* 删除商品信息
|
||||||
*/
|
*/
|
||||||
@PreAuthorize("@ss.hasPermi('goods:goods:remove')")
|
@PreAuthorize("@ss.hasPermi('service:goods:remove')")
|
||||||
@Log(title = "商品信息", businessType = BusinessType.DELETE)
|
@Log(title = "商品信息", businessType = BusinessType.DELETE)
|
||||||
@DeleteMapping("/{ids}")
|
@DeleteMapping("/{ids}")
|
||||||
public AjaxResult remove(@PathVariable Long[] ids)
|
public AjaxResult remove(@PathVariable Long[] ids)
|
||||||
{
|
{
|
||||||
return toAjax(goodsMessagesService.deleteGoodsMessagesByIds(ids));
|
return toAjax(goodsMessagesService.deleteGoodsMessagesByIds(ids));
|
@ -1,4 +1,4 @@
|
|||||||
package com.sf.goods.domain;
|
package com.sf.service.domain;
|
||||||
|
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
@ -8,8 +8,8 @@ import com.sf.common.core.domain.BaseEntity;
|
|||||||
/**
|
/**
|
||||||
* 商品信息对象 GOODS_MESSAGES
|
* 商品信息对象 GOODS_MESSAGES
|
||||||
*
|
*
|
||||||
* @author ztzh
|
* @author zoukun
|
||||||
* @date 2024-04-11
|
* @date 2024-04-18
|
||||||
*/
|
*/
|
||||||
public class GoodsMessages extends BaseEntity
|
public class GoodsMessages extends BaseEntity
|
||||||
{
|
{
|
||||||
@ -26,6 +26,7 @@ public class GoodsMessages extends BaseEntity
|
|||||||
private Long stockId;
|
private Long stockId;
|
||||||
|
|
||||||
/** 审核状态,1通过,0未通过 */
|
/** 审核状态,1通过,0未通过 */
|
||||||
|
@Excel(name = "审核状态,1通过,0未通过")
|
||||||
private Long reviewStatus;
|
private Long reviewStatus;
|
||||||
|
|
||||||
/** 商品标题 */
|
/** 商品标题 */
|
||||||
@ -36,16 +37,23 @@ public class GoodsMessages extends BaseEntity
|
|||||||
@Excel(name = "商品图片")
|
@Excel(name = "商品图片")
|
||||||
private String productPicture;
|
private String productPicture;
|
||||||
|
|
||||||
/** 原价格 */
|
/** 商品原价 */
|
||||||
@Excel(name = "原价格")
|
@Excel(name = "商品原价")
|
||||||
private Long originalPrice;
|
private Long originalPrice;
|
||||||
|
|
||||||
/** 商品描述 */
|
/** 商品描述 */
|
||||||
@Excel(name = "商品描述")
|
@Excel(name = "商品描述")
|
||||||
private String productDesc;
|
private String productDesc;
|
||||||
|
|
||||||
|
/** 商品类型。 * • 0:消耗型商品 * • 1:非消耗型商品 * • 2:自动续期订阅商品 */
|
||||||
|
@Excel(name = "商品类型。 * • 0:消耗型商品 * • 1:非消耗型商品 * • 2:自动续期订阅商品")
|
||||||
|
private Integer goodsType;
|
||||||
|
|
||||||
|
/** 商品规格 */
|
||||||
|
@Excel(name = "商品规格")
|
||||||
|
private String goodsSpec;
|
||||||
|
|
||||||
/** 排序 */
|
/** 排序 */
|
||||||
@Excel(name = "排序")
|
|
||||||
private Long orderNum;
|
private Long orderNum;
|
||||||
|
|
||||||
/** 逻辑删除,0:未删除,1:删除 */
|
/** 逻辑删除,0:未删除,1:删除 */
|
||||||
@ -57,13 +65,12 @@ public class GoodsMessages extends BaseEntity
|
|||||||
/** 更新人 */
|
/** 更新人 */
|
||||||
private String modified;
|
private String modified;
|
||||||
|
|
||||||
/** 商品类型 */
|
/** 商品名称 */
|
||||||
@Excel(name = "商品类型")
|
private String goodsName;
|
||||||
private String goodsType;
|
|
||||||
|
|
||||||
/** 商品规格 */
|
/** 商品型号 */
|
||||||
@Excel(name = "商品规格")
|
@Excel(name = "商品型号")
|
||||||
private String goodsSpec;
|
private String goodsModel;
|
||||||
|
|
||||||
public void setId(Long id)
|
public void setId(Long id)
|
||||||
{
|
{
|
||||||
@ -137,6 +144,24 @@ public class GoodsMessages extends BaseEntity
|
|||||||
{
|
{
|
||||||
return productDesc;
|
return productDesc;
|
||||||
}
|
}
|
||||||
|
public void setGoodsType(Integer goodsType)
|
||||||
|
{
|
||||||
|
this.goodsType = goodsType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getGoodsType()
|
||||||
|
{
|
||||||
|
return goodsType;
|
||||||
|
}
|
||||||
|
public void setGoodsSpec(String goodsSpec)
|
||||||
|
{
|
||||||
|
this.goodsSpec = goodsSpec;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGoodsSpec()
|
||||||
|
{
|
||||||
|
return goodsSpec;
|
||||||
|
}
|
||||||
public void setOrderNum(Long orderNum)
|
public void setOrderNum(Long orderNum)
|
||||||
{
|
{
|
||||||
this.orderNum = orderNum;
|
this.orderNum = orderNum;
|
||||||
@ -173,23 +198,23 @@ public class GoodsMessages extends BaseEntity
|
|||||||
{
|
{
|
||||||
return modified;
|
return modified;
|
||||||
}
|
}
|
||||||
public void setGoodsType(String goodsType)
|
public void setGoodsName(String goodsName)
|
||||||
{
|
{
|
||||||
this.goodsType = goodsType;
|
this.goodsName = goodsName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getGoodsType()
|
public String getGoodsName()
|
||||||
{
|
{
|
||||||
return goodsType;
|
return goodsName;
|
||||||
}
|
}
|
||||||
public void setGoodsSpec(String goodsSpec)
|
public void setGoodsModel(String goodsModel)
|
||||||
{
|
{
|
||||||
this.goodsSpec = goodsSpec;
|
this.goodsModel = goodsModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getGoodsSpec()
|
public String getGoodsModel()
|
||||||
{
|
{
|
||||||
return goodsSpec;
|
return goodsModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -203,14 +228,16 @@ public class GoodsMessages extends BaseEntity
|
|||||||
.append("productPicture", getProductPicture())
|
.append("productPicture", getProductPicture())
|
||||||
.append("originalPrice", getOriginalPrice())
|
.append("originalPrice", getOriginalPrice())
|
||||||
.append("productDesc", getProductDesc())
|
.append("productDesc", getProductDesc())
|
||||||
|
.append("goodsType", getGoodsType())
|
||||||
|
.append("goodsSpec", getGoodsSpec())
|
||||||
.append("orderNum", getOrderNum())
|
.append("orderNum", getOrderNum())
|
||||||
.append("isDelete", getIsDelete())
|
.append("isDelete", getIsDelete())
|
||||||
.append("created", getCreated())
|
.append("created", getCreated())
|
||||||
.append("modified", getModified())
|
.append("modified", getModified())
|
||||||
.append("createTime", getCreateTime())
|
.append("createTime", getCreateTime())
|
||||||
.append("updateTime", getUpdateTime())
|
.append("updateTime", getUpdateTime())
|
||||||
.append("goodsType", getGoodsType())
|
.append("goodsName", getGoodsName())
|
||||||
.append("goodsSpec", getGoodsSpec())
|
.append("goodsModel", getGoodsModel())
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,13 +1,13 @@
|
|||||||
package com.sf.goods.mapper;
|
package com.sf.service.mapper;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import com.sf.goods.domain.GoodsMessages;
|
import com.sf.service.domain.GoodsMessages;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 商品信息Mapper接口
|
* 商品信息Mapper接口
|
||||||
*
|
*
|
||||||
* @author ztzh
|
* @author zoukun
|
||||||
* @date 2024-04-11
|
* @date 2024-04-18
|
||||||
*/
|
*/
|
||||||
public interface GoodsMessagesMapper
|
public interface GoodsMessagesMapper
|
||||||
{
|
{
|
||||||
@ -58,4 +58,6 @@ public interface GoodsMessagesMapper
|
|||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public int deleteGoodsMessagesByIds(Long[] ids);
|
public int deleteGoodsMessagesByIds(Long[] ids);
|
||||||
|
|
||||||
|
GoodsMessages selectGoodsMessagesByCode(String goodsCode);
|
||||||
}
|
}
|
@ -1,13 +1,13 @@
|
|||||||
package com.sf.goods.service;
|
package com.sf.service.service;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import com.sf.goods.domain.GoodsMessages;
|
import com.sf.service.domain.GoodsMessages;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 商品信息Service接口
|
* 商品信息Service接口
|
||||||
*
|
*
|
||||||
* @author ztzh
|
* @author zoukun
|
||||||
* @date 2024-04-11
|
* @date 2024-04-18
|
||||||
*/
|
*/
|
||||||
public interface IGoodsMessagesService
|
public interface IGoodsMessagesService
|
||||||
{
|
{
|
||||||
@ -58,4 +58,6 @@ public interface IGoodsMessagesService
|
|||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
public int deleteGoodsMessagesById(Long id);
|
public int deleteGoodsMessagesById(Long id);
|
||||||
|
|
||||||
|
GoodsMessages selectGoodsMessagesByCode(String goodsCode);
|
||||||
}
|
}
|
@ -1,18 +1,19 @@
|
|||||||
package com.sf.goods.service.impl;
|
package com.sf.service.service.impl;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import com.sf.common.utils.DateUtils;
|
import com.sf.common.utils.DateUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import com.sf.goods.mapper.GoodsMessagesMapper;
|
import com.sf.service.mapper.GoodsMessagesMapper;
|
||||||
import com.sf.goods.domain.GoodsMessages;
|
import com.sf.service.domain.GoodsMessages;
|
||||||
import com.sf.goods.service.IGoodsMessagesService;
|
import com.sf.service.service.IGoodsMessagesService;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 商品信息Service业务层处理
|
* 商品信息Service业务层处理
|
||||||
*
|
*
|
||||||
* @author ztzh
|
* @author zoukun
|
||||||
* @date 2024-04-11
|
* @date 2024-04-18
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class GoodsMessagesServiceImpl implements IGoodsMessagesService
|
public class GoodsMessagesServiceImpl implements IGoodsMessagesService
|
||||||
@ -93,4 +94,12 @@ public class GoodsMessagesServiceImpl implements IGoodsMessagesService
|
|||||||
{
|
{
|
||||||
return goodsMessagesMapper.deleteGoodsMessagesById(id);
|
return goodsMessagesMapper.deleteGoodsMessagesById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GoodsMessages selectGoodsMessagesByCode(String goodsCode) {
|
||||||
|
if (StringUtils.hasText(goodsCode)){
|
||||||
|
return goodsMessagesMapper.selectGoodsMessagesByCode(goodsCode);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
@ -2,7 +2,7 @@
|
|||||||
<!DOCTYPE mapper
|
<!DOCTYPE mapper
|
||||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
<mapper namespace="com.sf.goods.mapper.GoodsMessagesMapper">
|
<mapper namespace="com.sf.service.mapper.GoodsMessagesMapper">
|
||||||
|
|
||||||
<resultMap type="GoodsMessages" id="GoodsMessagesResult">
|
<resultMap type="GoodsMessages" id="GoodsMessagesResult">
|
||||||
<result property="id" column="id" />
|
<result property="id" column="id" />
|
||||||
@ -13,26 +13,32 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
<result property="productPicture" column="product_picture" />
|
<result property="productPicture" column="product_picture" />
|
||||||
<result property="originalPrice" column="original_price" />
|
<result property="originalPrice" column="original_price" />
|
||||||
<result property="productDesc" column="product_desc" />
|
<result property="productDesc" column="product_desc" />
|
||||||
|
<result property="goodsType" column="goods_type" />
|
||||||
|
<result property="goodsSpec" column="goods_spec" />
|
||||||
<result property="orderNum" column="order_num" />
|
<result property="orderNum" column="order_num" />
|
||||||
<result property="isDelete" column="is_delete" />
|
<result property="isDelete" column="is_delete" />
|
||||||
<result property="created" column="created" />
|
<result property="created" column="created" />
|
||||||
<result property="modified" column="modified" />
|
<result property="modified" column="modified" />
|
||||||
<result property="createTime" column="create_time" />
|
<result property="createTime" column="create_time" />
|
||||||
<result property="updateTime" column="update_time" />
|
<result property="updateTime" column="update_time" />
|
||||||
<result property="goodsType" column="goods_type" />
|
<result property="goodsName" column="goods_name" />
|
||||||
<result property="goodsSpec" column="goods_spec" />
|
<result property="goodsModel" column="goods_model" />
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<sql id="selectGoodsMessagesVo">
|
<sql id="selectGoodsMessagesVo">
|
||||||
select id, goods_code, stock_id, review_status, product_title, product_picture, original_price, product_desc, order_num, is_delete, created, modified, create_time, update_time, goods_type, goods_spec from GOODS_MESSAGES
|
select id, goods_code, stock_id, review_status, product_title, product_picture, original_price, product_desc, goods_type, goods_spec, order_num, is_delete, created, modified, create_time, update_time, goods_name, goods_model from GOODS_MESSAGES
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
<select id="selectGoodsMessagesList" parameterType="GoodsMessages" resultMap="GoodsMessagesResult">
|
<select id="selectGoodsMessagesList" parameterType="GoodsMessages" resultMap="GoodsMessagesResult">
|
||||||
<include refid="selectGoodsMessagesVo"/>
|
<include refid="selectGoodsMessagesVo"/>
|
||||||
<where>
|
<where>
|
||||||
<if test="goodsCode != null and goodsCode != ''"> and goods_code = #{goodsCode}</if>
|
<if test="goodsCode != null and goodsCode != ''"> and goods_code = #{goodsCode}</if>
|
||||||
|
<if test="reviewStatus != null "> and review_status = #{reviewStatus}</if>
|
||||||
<if test="productTitle != null and productTitle != ''"> and product_title like concat('%', #{productTitle}, '%')</if>
|
<if test="productTitle != null and productTitle != ''"> and product_title like concat('%', #{productTitle}, '%')</if>
|
||||||
<if test="goodsType != null and goodsType != ''"> and goods_type = #{goodsType}</if>
|
<if test="params.beginOriginalPrice != null and params.beginOriginalPrice != '' and params.endOriginalPrice != null and params.endOriginalPrice != ''"> and original_price between #{params.beginOriginalPrice} and #{params.endOriginalPrice}</if>
|
||||||
|
<if test="goodsType != null "> and goods_type = #{goodsType}</if>
|
||||||
|
<if test="goodsSpec != null and goodsSpec != ''"> and goods_spec = #{goodsSpec}</if>
|
||||||
|
<if test="goodsModel != null and goodsModel != ''"> and goods_model = #{goodsModel}</if>
|
||||||
</where>
|
</where>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
@ -40,10 +46,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
<include refid="selectGoodsMessagesVo"/>
|
<include refid="selectGoodsMessagesVo"/>
|
||||||
where id = #{id}
|
where id = #{id}
|
||||||
</select>
|
</select>
|
||||||
<select id="selectGoodsMessagesByCode" parameterType="java.lang.String" resultMap="GoodsMessagesResult">
|
<select id="selectGoodsMessagesByCode" parameterType="String" resultMap="GoodsMessagesResult">
|
||||||
<include refid="selectGoodsMessagesVo"/>
|
<include refid="selectGoodsMessagesVo"/>
|
||||||
where goods_code = #{code}
|
where goods_code = #{goodsCode}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<insert id="insertGoodsMessages" parameterType="GoodsMessages" useGeneratedKeys="true" keyProperty="id">
|
<insert id="insertGoodsMessages" parameterType="GoodsMessages" useGeneratedKeys="true" keyProperty="id">
|
||||||
insert into GOODS_MESSAGES
|
insert into GOODS_MESSAGES
|
||||||
@ -55,14 +61,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
<if test="productPicture != null and productPicture != ''">product_picture,</if>
|
<if test="productPicture != null and productPicture != ''">product_picture,</if>
|
||||||
<if test="originalPrice != null">original_price,</if>
|
<if test="originalPrice != null">original_price,</if>
|
||||||
<if test="productDesc != null">product_desc,</if>
|
<if test="productDesc != null">product_desc,</if>
|
||||||
|
<if test="goodsType != null">goods_type,</if>
|
||||||
|
<if test="goodsSpec != null and goodsSpec != ''">goods_spec,</if>
|
||||||
<if test="orderNum != null">order_num,</if>
|
<if test="orderNum != null">order_num,</if>
|
||||||
<if test="isDelete != null">is_delete,</if>
|
<if test="isDelete != null">is_delete,</if>
|
||||||
<if test="created != null">created,</if>
|
<if test="created != null">created,</if>
|
||||||
<if test="modified != null">modified,</if>
|
<if test="modified != null">modified,</if>
|
||||||
<if test="createTime != null">create_time,</if>
|
<if test="createTime != null">create_time,</if>
|
||||||
<if test="updateTime != null">update_time,</if>
|
<if test="updateTime != null">update_time,</if>
|
||||||
<if test="goodsType != null and goodsType != ''">goods_type,</if>
|
<if test="goodsName != null and goodsName != ''">goods_name,</if>
|
||||||
<if test="goodsSpec != null and goodsSpec != ''">goods_spec,</if>
|
<if test="goodsModel != null">goods_model,</if>
|
||||||
</trim>
|
</trim>
|
||||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||||
<if test="goodsCode != null and goodsCode != ''">#{goodsCode},</if>
|
<if test="goodsCode != null and goodsCode != ''">#{goodsCode},</if>
|
||||||
@ -72,14 +80,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
<if test="productPicture != null and productPicture != ''">#{productPicture},</if>
|
<if test="productPicture != null and productPicture != ''">#{productPicture},</if>
|
||||||
<if test="originalPrice != null">#{originalPrice},</if>
|
<if test="originalPrice != null">#{originalPrice},</if>
|
||||||
<if test="productDesc != null">#{productDesc},</if>
|
<if test="productDesc != null">#{productDesc},</if>
|
||||||
|
<if test="goodsType != null">#{goodsType},</if>
|
||||||
|
<if test="goodsSpec != null and goodsSpec != ''">#{goodsSpec},</if>
|
||||||
<if test="orderNum != null">#{orderNum},</if>
|
<if test="orderNum != null">#{orderNum},</if>
|
||||||
<if test="isDelete != null">#{isDelete},</if>
|
<if test="isDelete != null">#{isDelete},</if>
|
||||||
<if test="created != null">#{created},</if>
|
<if test="created != null">#{created},</if>
|
||||||
<if test="modified != null">#{modified},</if>
|
<if test="modified != null">#{modified},</if>
|
||||||
<if test="createTime != null">#{createTime},</if>
|
<if test="createTime != null">#{createTime},</if>
|
||||||
<if test="updateTime != null">#{updateTime},</if>
|
<if test="updateTime != null">#{updateTime},</if>
|
||||||
<if test="goodsType != null and goodsType != ''">#{goodsType},</if>
|
<if test="goodsName != null and goodsName != ''">#{goodsName},</if>
|
||||||
<if test="goodsSpec != null and goodsSpec != ''">#{goodsSpec},</if>
|
<if test="goodsModel != null">#{goodsModel},</if>
|
||||||
</trim>
|
</trim>
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
@ -93,14 +103,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
<if test="productPicture != null and productPicture != ''">product_picture = #{productPicture},</if>
|
<if test="productPicture != null and productPicture != ''">product_picture = #{productPicture},</if>
|
||||||
<if test="originalPrice != null">original_price = #{originalPrice},</if>
|
<if test="originalPrice != null">original_price = #{originalPrice},</if>
|
||||||
<if test="productDesc != null">product_desc = #{productDesc},</if>
|
<if test="productDesc != null">product_desc = #{productDesc},</if>
|
||||||
|
<if test="goodsType != null">goods_type = #{goodsType},</if>
|
||||||
|
<if test="goodsSpec != null and goodsSpec != ''">goods_spec = #{goodsSpec},</if>
|
||||||
<if test="orderNum != null">order_num = #{orderNum},</if>
|
<if test="orderNum != null">order_num = #{orderNum},</if>
|
||||||
<if test="isDelete != null">is_delete = #{isDelete},</if>
|
<if test="isDelete != null">is_delete = #{isDelete},</if>
|
||||||
<if test="created != null">created = #{created},</if>
|
<if test="created != null">created = #{created},</if>
|
||||||
<if test="modified != null">modified = #{modified},</if>
|
<if test="modified != null">modified = #{modified},</if>
|
||||||
<if test="createTime != null">create_time = #{createTime},</if>
|
<if test="createTime != null">create_time = #{createTime},</if>
|
||||||
<if test="updateTime != null">update_time = #{updateTime},</if>
|
<if test="updateTime != null">update_time = #{updateTime},</if>
|
||||||
<if test="goodsType != null and goodsType != ''">goods_type = #{goodsType},</if>
|
<if test="goodsName != null and goodsName != ''">goods_name = #{goodsName},</if>
|
||||||
<if test="goodsSpec != null and goodsSpec != ''">goods_spec = #{goodsSpec},</if>
|
<if test="goodsModel != null">goods_model = #{goodsModel},</if>
|
||||||
</trim>
|
</trim>
|
||||||
where id = #{id}
|
where id = #{id}
|
||||||
</update>
|
</update>
|
@ -3,7 +3,7 @@ import request from '@/utils/request'
|
|||||||
// 查询商品信息列表
|
// 查询商品信息列表
|
||||||
export function listGoods(query) {
|
export function listGoods(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/goods/goods/list',
|
url: '/service/goods/list',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query
|
params: query
|
||||||
})
|
})
|
||||||
@ -12,7 +12,7 @@ export function listGoods(query) {
|
|||||||
// 查询商品信息详细
|
// 查询商品信息详细
|
||||||
export function getGoods(id) {
|
export function getGoods(id) {
|
||||||
return request({
|
return request({
|
||||||
url: '/goods/goods/' + id,
|
url: '/service/goods/' + id,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -20,7 +20,7 @@ export function getGoods(id) {
|
|||||||
// 新增商品信息
|
// 新增商品信息
|
||||||
export function addGoods(data) {
|
export function addGoods(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/goods/goods',
|
url: '/service/goods',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
@ -29,7 +29,7 @@ export function addGoods(data) {
|
|||||||
// 修改商品信息
|
// 修改商品信息
|
||||||
export function updateGoods(data) {
|
export function updateGoods(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/goods/goods',
|
url: '/service/goods',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
@ -38,7 +38,7 @@ export function updateGoods(data) {
|
|||||||
// 删除商品信息
|
// 删除商品信息
|
||||||
export function delGoods(id) {
|
export function delGoods(id) {
|
||||||
return request({
|
return request({
|
||||||
url: '/goods/goods/' + id,
|
url: '/service/goods/' + id,
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
@ -9,6 +9,16 @@
|
|||||||
@keyup.enter.native="handleQuery"
|
@keyup.enter.native="handleQuery"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="审核状态,1通过,0未通过" prop="reviewStatus">
|
||||||
|
<el-select v-model="queryParams.reviewStatus" placeholder="请选择审核状态,1通过,0未通过" clearable>
|
||||||
|
<el-option
|
||||||
|
v-for="dict in dict.type.goods_review_status"
|
||||||
|
:key="dict.value"
|
||||||
|
:label="dict.label"
|
||||||
|
:value="dict.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item label="商品标题" prop="productTitle">
|
<el-form-item label="商品标题" prop="productTitle">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="queryParams.productTitle"
|
v-model="queryParams.productTitle"
|
||||||
@ -17,8 +27,16 @@
|
|||||||
@keyup.enter.native="handleQuery"
|
@keyup.enter.native="handleQuery"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="商品类型" prop="goodsType">
|
<el-form-item label="商品原价" prop="originalPrice">
|
||||||
<el-select v-model="queryParams.goodsType" placeholder="请选择商品类型" clearable>
|
<el-input
|
||||||
|
v-model="queryParams.originalPrice"
|
||||||
|
placeholder="请输入商品原价"
|
||||||
|
clearable
|
||||||
|
@keyup.enter.native="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="商品类型。 * • 0:消耗型商品 * • 1:非消耗型商品 * • 2:自动续期订阅商品" prop="goodsType">
|
||||||
|
<el-select v-model="queryParams.goodsType" placeholder="请选择商品类型。 * • 0:消耗型商品 * • 1:非消耗型商品 * • 2:自动续期订阅商品" clearable>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="dict in dict.type.goods_type"
|
v-for="dict in dict.type.goods_type"
|
||||||
:key="dict.value"
|
:key="dict.value"
|
||||||
@ -27,6 +45,22 @@
|
|||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="商品规格" prop="goodsSpec">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.goodsSpec"
|
||||||
|
placeholder="请输入商品规格"
|
||||||
|
clearable
|
||||||
|
@keyup.enter.native="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="商品型号" prop="goodsModel">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.goodsModel"
|
||||||
|
placeholder="请输入商品型号"
|
||||||
|
clearable
|
||||||
|
@keyup.enter.native="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||||
@ -41,7 +75,7 @@
|
|||||||
icon="el-icon-plus"
|
icon="el-icon-plus"
|
||||||
size="mini"
|
size="mini"
|
||||||
@click="handleAdd"
|
@click="handleAdd"
|
||||||
v-hasPermi="['goods:goods:add']"
|
v-hasPermi="['service:goods:add']"
|
||||||
>新增</el-button>
|
>新增</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
@ -52,7 +86,7 @@
|
|||||||
size="mini"
|
size="mini"
|
||||||
:disabled="single"
|
:disabled="single"
|
||||||
@click="handleUpdate"
|
@click="handleUpdate"
|
||||||
v-hasPermi="['goods:goods:edit']"
|
v-hasPermi="['service:goods:edit']"
|
||||||
>修改</el-button>
|
>修改</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
@ -63,7 +97,7 @@
|
|||||||
size="mini"
|
size="mini"
|
||||||
:disabled="multiple"
|
:disabled="multiple"
|
||||||
@click="handleDelete"
|
@click="handleDelete"
|
||||||
v-hasPermi="['goods:goods:remove']"
|
v-hasPermi="['service:goods:remove']"
|
||||||
>删除</el-button>
|
>删除</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
@ -73,7 +107,7 @@
|
|||||||
icon="el-icon-download"
|
icon="el-icon-download"
|
||||||
size="mini"
|
size="mini"
|
||||||
@click="handleExport"
|
@click="handleExport"
|
||||||
v-hasPermi="['goods:goods:export']"
|
v-hasPermi="['service:goods:export']"
|
||||||
>导出</el-button>
|
>导出</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
@ -81,23 +115,28 @@
|
|||||||
|
|
||||||
<el-table v-loading="loading" :data="goodsList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="goodsList" @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
<el-table-column label="商品id" align="center" prop="id" />
|
<el-table-column label="主键" align="center" prop="id" />
|
||||||
<el-table-column label="商品编号" align="center" prop="goodsCode" />
|
<el-table-column label="商品编号" align="center" prop="goodsCode" />
|
||||||
|
<el-table-column label="审核状态,1通过,0未通过" align="center" prop="reviewStatus">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<dict-tag :options="dict.type.goods_review_status" :value="scope.row.reviewStatus"/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="商品标题" align="center" prop="productTitle" />
|
<el-table-column label="商品标题" align="center" prop="productTitle" />
|
||||||
<el-table-column label="商品图片" align="center" prop="productPicture" width="100">
|
<el-table-column label="商品图片" align="center" prop="productPicture" width="100">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<image-preview :src="scope.row.productPicture" :width="50" :height="50"/>
|
<image-preview :src="scope.row.productPicture" :width="50" :height="50"/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="价格" align="center" prop="originalPrice" />
|
<el-table-column label="商品原价" align="center" prop="originalPrice" />
|
||||||
<el-table-column label="商品描述" align="center" prop="productDesc" />
|
<el-table-column label="商品描述" align="center" prop="productDesc" />
|
||||||
<el-table-column label="排序" align="center" prop="orderNum" />
|
<el-table-column label="商品类型。 * • 0:消耗型商品 * • 1:非消耗型商品 * • 2:自动续期订阅商品" align="center" prop="goodsType">
|
||||||
<el-table-column label="商品类型" align="center" prop="goodsType">
|
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<dict-tag :options="dict.type.goods_type" :value="scope.row.goodsType"/>
|
<dict-tag :options="dict.type.goods_type" :value="scope.row.goodsType"/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="商品规格" align="center" prop="goodsSpec" />
|
<el-table-column label="商品规格" align="center" prop="goodsSpec" />
|
||||||
|
<el-table-column label="商品型号" align="center" prop="goodsModel" />
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button
|
<el-button
|
||||||
@ -105,14 +144,14 @@
|
|||||||
type="text"
|
type="text"
|
||||||
icon="el-icon-edit"
|
icon="el-icon-edit"
|
||||||
@click="handleUpdate(scope.row)"
|
@click="handleUpdate(scope.row)"
|
||||||
v-hasPermi="['goods:goods:edit']"
|
v-hasPermi="['service:goods:edit']"
|
||||||
>修改</el-button>
|
>修改</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
size="mini"
|
size="mini"
|
||||||
type="text"
|
type="text"
|
||||||
icon="el-icon-delete"
|
icon="el-icon-delete"
|
||||||
@click="handleDelete(scope.row)"
|
@click="handleDelete(scope.row)"
|
||||||
v-hasPermi="['goods:goods:remove']"
|
v-hasPermi="['service:goods:remove']"
|
||||||
>删除</el-button>
|
>删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@ -132,33 +171,60 @@
|
|||||||
<el-form-item label="商品编号" prop="goodsCode">
|
<el-form-item label="商品编号" prop="goodsCode">
|
||||||
<el-input v-model="form.goodsCode" placeholder="请输入商品编号" />
|
<el-input v-model="form.goodsCode" placeholder="请输入商品编号" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="库存表编号" prop="stockId">
|
||||||
|
<el-input v-model="form.stockId" placeholder="请输入库存表编号" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="审核状态,1通过,0未通过" prop="reviewStatus">
|
||||||
|
<el-radio-group v-model="form.reviewStatus">
|
||||||
|
<el-radio
|
||||||
|
v-for="dict in dict.type.goods_review_status"
|
||||||
|
:key="dict.value"
|
||||||
|
:label="parseInt(dict.value)"
|
||||||
|
>{{dict.label}}</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item label="商品标题" prop="productTitle">
|
<el-form-item label="商品标题" prop="productTitle">
|
||||||
<el-input v-model="form.productTitle" placeholder="请输入商品标题" />
|
<el-input v-model="form.productTitle" placeholder="请输入商品标题" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="商品图片" prop="productPicture">
|
<el-form-item label="商品图片" prop="productPicture">
|
||||||
<image-upload v-model="form.productPicture"/>
|
<image-upload v-model="form.productPicture"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="原价格" prop="originalPrice">
|
<el-form-item label="商品原价" prop="originalPrice">
|
||||||
<el-input v-model="form.originalPrice" placeholder="请输入原价格" />
|
<el-input v-model="form.originalPrice" placeholder="请输入商品原价" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="商品描述" prop="productDesc">
|
<el-form-item label="商品描述" prop="productDesc">
|
||||||
<el-input v-model="form.productDesc" type="textarea" placeholder="请输入内容" />
|
<el-input v-model="form.productDesc" type="textarea" placeholder="请输入内容" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="排序" prop="orderNum">
|
<el-form-item label="商品类型。 * • 0:消耗型商品 * • 1:非消耗型商品 * • 2:自动续期订阅商品" prop="goodsType">
|
||||||
<el-input v-model="form.orderNum" placeholder="请输入排序" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="商品类型" prop="goodsType">
|
|
||||||
<el-radio-group v-model="form.goodsType">
|
<el-radio-group v-model="form.goodsType">
|
||||||
<el-radio
|
<el-radio
|
||||||
v-for="dict in dict.type.goods_type"
|
v-for="dict in dict.type.goods_type"
|
||||||
:key="dict.value"
|
:key="dict.value"
|
||||||
:label="dict.value"
|
:label="parseInt(dict.value)"
|
||||||
>{{dict.label}}</el-radio>
|
>{{dict.label}}</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="商品规格" prop="goodsSpec">
|
<el-form-item label="商品规格" prop="goodsSpec">
|
||||||
<el-input v-model="form.goodsSpec" placeholder="请输入商品规格" />
|
<el-input v-model="form.goodsSpec" placeholder="请输入商品规格" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="排序" prop="orderNum">
|
||||||
|
<el-input v-model="form.orderNum" placeholder="请输入排序" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="逻辑删除,0:未删除,1:删除" prop="isDelete">
|
||||||
|
<el-input v-model="form.isDelete" placeholder="请输入逻辑删除,0:未删除,1:删除" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="创建人" prop="created">
|
||||||
|
<el-input v-model="form.created" placeholder="请输入创建人" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="更新人" prop="modified">
|
||||||
|
<el-input v-model="form.modified" placeholder="请输入更新人" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="商品名称" prop="goodsName">
|
||||||
|
<el-input v-model="form.goodsName" placeholder="请输入商品名称" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="商品型号" prop="goodsModel">
|
||||||
|
<el-input v-model="form.goodsModel" placeholder="请输入商品型号" />
|
||||||
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<div slot="footer" class="dialog-footer">
|
<div slot="footer" class="dialog-footer">
|
||||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||||
@ -169,11 +235,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { listGoods, getGoods, delGoods, addGoods, updateGoods } from "@/api/goods/goods";
|
import { listGoods, getGoods, delGoods, addGoods, updateGoods } from "@/api/service/goods";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Goods",
|
name: "Goods",
|
||||||
dicts: ['sys_notice_status', 'goods_type'],
|
dicts: ['goods_review_status', 'goods_type'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
// 遮罩层
|
// 遮罩层
|
||||||
@ -199,8 +265,12 @@ export default {
|
|||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
goodsCode: null,
|
goodsCode: null,
|
||||||
|
reviewStatus: null,
|
||||||
productTitle: null,
|
productTitle: null,
|
||||||
|
originalPrice: null,
|
||||||
goodsType: null,
|
goodsType: null,
|
||||||
|
goodsSpec: null,
|
||||||
|
goodsModel: null
|
||||||
},
|
},
|
||||||
// 表单参数
|
// 表单参数
|
||||||
form: {},
|
form: {},
|
||||||
@ -216,7 +286,13 @@ export default {
|
|||||||
{ required: true, message: "商品图片不能为空", trigger: "blur" }
|
{ required: true, message: "商品图片不能为空", trigger: "blur" }
|
||||||
],
|
],
|
||||||
originalPrice: [
|
originalPrice: [
|
||||||
{ required: true, message: "原价格不能为空", trigger: "blur" }
|
{ required: true, message: "商品原价不能为空", trigger: "blur" }
|
||||||
|
],
|
||||||
|
goodsType: [
|
||||||
|
{ required: true, message: "商品类型。 * • 0:消耗型商品 * • 1:非消耗型商品 * • 2:自动续期订阅商品不能为空", trigger: "change" }
|
||||||
|
],
|
||||||
|
goodsSpec: [
|
||||||
|
{ required: true, message: "商品规格不能为空", trigger: "blur" }
|
||||||
],
|
],
|
||||||
orderNum: [
|
orderNum: [
|
||||||
{ required: true, message: "排序不能为空", trigger: "blur" }
|
{ required: true, message: "排序不能为空", trigger: "blur" }
|
||||||
@ -224,12 +300,9 @@ export default {
|
|||||||
createTime: [
|
createTime: [
|
||||||
{ required: true, message: "创建时间不能为空", trigger: "blur" }
|
{ required: true, message: "创建时间不能为空", trigger: "blur" }
|
||||||
],
|
],
|
||||||
goodsType: [
|
goodsName: [
|
||||||
{ required: true, message: "商品类型不能为空", trigger: "change" }
|
{ required: true, message: "商品名称不能为空", trigger: "blur" }
|
||||||
],
|
],
|
||||||
goodsSpec: [
|
|
||||||
{ required: true, message: "商品规格不能为空", trigger: "blur" }
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@ -262,14 +335,16 @@ export default {
|
|||||||
productPicture: null,
|
productPicture: null,
|
||||||
originalPrice: null,
|
originalPrice: null,
|
||||||
productDesc: null,
|
productDesc: null,
|
||||||
|
goodsType: null,
|
||||||
|
goodsSpec: null,
|
||||||
orderNum: null,
|
orderNum: null,
|
||||||
isDelete: null,
|
isDelete: null,
|
||||||
created: null,
|
created: null,
|
||||||
modified: null,
|
modified: null,
|
||||||
createTime: null,
|
createTime: null,
|
||||||
updateTime: null,
|
updateTime: null,
|
||||||
goodsType: null,
|
goodsName: null,
|
||||||
goodsSpec: null
|
goodsModel: null
|
||||||
};
|
};
|
||||||
this.resetForm("form");
|
this.resetForm("form");
|
||||||
},
|
},
|
||||||
@ -339,7 +414,7 @@ export default {
|
|||||||
},
|
},
|
||||||
/** 导出按钮操作 */
|
/** 导出按钮操作 */
|
||||||
handleExport() {
|
handleExport() {
|
||||||
this.download('goods/goods/export', {
|
this.download('service/goods/export', {
|
||||||
...this.queryParams
|
...this.queryParams
|
||||||
}, `goods_${new Date().getTime()}.xlsx`)
|
}, `goods_${new Date().getTime()}.xlsx`)
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user