Merge branch 'master' of http://120.76.84.145:10101/gitblit/r/java/XinQuanHealing
# Conflicts:
# xinquan-api/xinquan-api-course/src/main/java/com/xinquan/course/api/domain/Course.java
# xinquan-auth/src/main/resources/bootstrap.yml
# xinquan-gateway/src/main/resources/bootstrap.yml
3 文件已重命名
30个文件已修改
25个文件已添加
| | |
| | | *.log |
| | | *.xml.versionsBackup |
| | | *.swp |
| | | *.yml |
| | | |
| | | |
| | | !*/build/*.java |
| | | !*/build/*.html |
New file |
| | |
| | | version : '3.8' |
| | | services: |
| | | xinquan-nacos: |
| | | container_name: xinquan-nacos |
| | | image: nacos/nacos-server |
| | | build: |
| | | context: ./nacos |
| | | environment: |
| | | - MODE=standalone |
| | | volumes: |
| | | - ./nacos/logs/:/home/nacos/logs |
| | | - ./nacos/conf/application.properties:/home/nacos/conf/application.properties |
| | | ports: |
| | | - "8848:8848" |
| | | - "9848:9848" |
| | | - "9849:9849" |
| | | depends_on: |
| | | - xinquan-mysql |
| | | xinquan-mysql: |
| | | container_name: xinquan-mysql |
| | | image: mysql:5.7 |
| | | build: |
| | | context: ./mysql |
| | | ports: |
| | | - "3306:3306" |
| | | volumes: |
| | | - ./mysql/conf:/etc/mysql/conf.d |
| | | - ./mysql/logs:/logs |
| | | - ./mysql/data:/var/lib/mysql |
| | | command: [ |
| | | 'mysqld', |
| | | '--innodb-buffer-pool-size=80M', |
| | | '--character-set-server=utf8mb4', |
| | | '--collation-server=utf8mb4_unicode_ci', |
| | | '--default-time-zone=+8:00', |
| | | '--lower-case-table-names=1' |
| | | ] |
| | | environment: |
| | | MYSQL_DATABASE: 'ry-cloud' |
| | | MYSQL_ROOT_PASSWORD: password |
| | | xinquan-redis: |
| | | container_name: xinquan-redis |
| | | image: redis |
| | | build: |
| | | context: ./redis |
| | | ports: |
| | | - "6379:6379" |
| | | volumes: |
| | | - ./redis/conf/redis.conf:/home/xinquan/redis/redis.conf |
| | | - ./redis/data:/data |
| | | command: redis-server /home/xinquan/redis/redis.conf |
| | | xinquan-nginx: |
| | | container_name: xinquan-nginx |
| | | image: nginx |
| | | build: |
| | | context: ./nginx |
| | | ports: |
| | | - "80:80" |
| | | volumes: |
| | | - ./nginx/html/dist:/home/xinquan/projects/xinquan-ui |
| | | - ./nginx/conf/nginx.conf:/etc/nginx/nginx.conf |
| | | - ./nginx/logs:/var/log/nginx |
| | | - ./nginx/conf.d:/etc/nginx/conf.d |
| | | depends_on: |
| | | - xinquan-gateway |
| | | links: |
| | | - xinquan-gateway |
| | | xinquan-gateway: |
| | | container_name: xinquan-gateway |
| | | build: |
| | | context: ./xinquan/gateway |
| | | dockerfile: dockerfile |
| | | ports: |
| | | - "8080:8080" |
| | | depends_on: |
| | | - xinquan-redis |
| | | links: |
| | | - xinquan-redis |
| | | xinquan-auth: |
| | | container_name: xinquan-auth |
| | | build: |
| | | context: ./xinquan/auth |
| | | dockerfile: dockerfile |
| | | ports: |
| | | - "9200:9200" |
| | | depends_on: |
| | | - xinquan-redis |
| | | links: |
| | | - xinquan-redis |
| | | xinquan-modules-system: |
| | | container_name: xinquan-modules-system |
| | | build: |
| | | context: ./xinquan/modules/system |
| | | dockerfile: dockerfile |
| | | ports: |
| | | - "9201:9201" |
| | | depends_on: |
| | | - xinquan-redis |
| | | - xinquan-mysql |
| | | links: |
| | | - xinquan-redis |
| | | - xinquan-mysql |
| | | xinquan-modules-gen: |
| | | container_name: xinquan-modules-gen |
| | | build: |
| | | context: ./xinquan/modules/gen |
| | | dockerfile: dockerfile |
| | | ports: |
| | | - "9202:9202" |
| | | depends_on: |
| | | - xinquan-mysql |
| | | links: |
| | | - xinquan-mysql |
| | | xinquan-modules-job: |
| | | container_name: xinquan-modules-job |
| | | build: |
| | | context: ./xinquan/modules/job |
| | | dockerfile: dockerfile |
| | | ports: |
| | | - "9203:9203" |
| | | depends_on: |
| | | - xinquan-mysql |
| | | links: |
| | | - xinquan-mysql |
| | | xinquan-modules-file: |
| | | container_name: xinquan-modules-file |
| | | build: |
| | | context: ./xinquan/modules/file |
| | | dockerfile: dockerfile |
| | | ports: |
| | | - "9300:9300" |
| | | volumes: |
| | | - ./xinquan/uploadPath:/home/xinquan/uploadPath |
| | | xinquan-visual-monitor: |
| | | container_name: xinquan-visual-monitor |
| | | build: |
| | | context: ./xinquan/visual/monitor |
| | | dockerfile: dockerfile |
| | | ports: |
| | | - "9100:9100" |
File was renamed from xinquan-modules/xinquan-course/src/main/java/com/xinquan/course/domain/Course.java |
| | |
| | | package com.xinquan.course.domain; |
| | | package com.xinquan.course.api.domain; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import com.xinquan.common.core.web.domain.BaseModel; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | |
| | | import com.xinquan.user.api.domain.AppUser; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import java.math.BigDecimal; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | |
| | | @TableField("charge_type") |
| | | private Integer chargeType; |
| | | |
| | | @ApiModelProperty(value = "通用价格") |
| | | @TableField("general_price") |
| | | private BigDecimal generalPrice; |
| | | |
| | | @ApiModelProperty(value = "IOS内购价格") |
| | | @TableField("ios_price") |
| | | private BigDecimal iosPrice; |
| | | |
| | | @ApiModelProperty(value = "排序权重") |
| | | @TableField("sort_num") |
| | | private Integer sortNum; |
| | |
| | | package com.xinquan.course.api.feign; |
| | | |
| | | import com.xinquan.common.core.constant.SecurityConstants; |
| | | import com.xinquan.common.core.constant.ServiceNameConstants; |
| | | import com.xinquan.common.core.domain.R; |
| | | import com.xinquan.course.api.domain.Course; |
| | | import com.xinquan.course.api.factory.RemoteCourseFallbackFactory; |
| | | import org.springframework.cloud.openfeign.FeignClient; |
| | | import org.springframework.web.bind.annotation.RequestHeader; |
| | | |
| | | /** |
| | | * @author mitao |
| | | * @date 2024/8/21 |
| | | */ |
| | | @FeignClient(contextId = "remoteFileService", value = ServiceNameConstants.COURSE_SERVICE, fallbackFactory = RemoteCourseFallbackFactory.class) |
| | | @FeignClient(contextId = "remoteCourseService", value = ServiceNameConstants.COURSE_SERVICE, fallbackFactory = RemoteCourseFallbackFactory.class) |
| | | public interface RemoteCourseService { |
| | | |
| | | R<Course> getCourseById(Long targetId, |
| | | @RequestHeader(SecurityConstants.FROM_SOURCE) String source); |
| | | } |
File was renamed from xinquan-modules/xinquan-meditation/src/main/java/com/xinquan/meditation/domain/Meditation.java |
| | |
| | | package com.xinquan.meditation.domain; |
| | | package com.xinquan.meditation.api.domain; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
New file |
| | |
| | | package com.xinquan.meditation.api.factory; |
| | | |
| | | import com.xinquan.common.core.domain.R; |
| | | import com.xinquan.meditation.api.domain.Meditation; |
| | | import com.xinquan.meditation.api.feign.RemoteMeditationService; |
| | | import org.springframework.cloud.openfeign.FallbackFactory; |
| | | |
| | | /** |
| | | * @author mitao |
| | | * @date 2024/9/9 |
| | | */ |
| | | public class RemoteMeditationFallbackFactory implements FallbackFactory<RemoteMeditationService> { |
| | | |
| | | @Override |
| | | public RemoteMeditationService create(Throwable cause) { |
| | | return new RemoteMeditationService() { |
| | | @Override |
| | | public R<Meditation> getMeditationById(Long targetId, String source) { |
| | | return R.fail("获取冥想音频失败"); |
| | | } |
| | | }; |
| | | } |
| | | } |
New file |
| | |
| | | package com.xinquan.meditation.api.feign; |
| | | |
| | | import com.xinquan.common.core.constant.SecurityConstants; |
| | | import com.xinquan.common.core.constant.ServiceNameConstants; |
| | | import com.xinquan.common.core.domain.R; |
| | | import com.xinquan.meditation.api.domain.Meditation; |
| | | import com.xinquan.meditation.api.factory.RemoteMeditationFallbackFactory; |
| | | import org.springframework.cloud.openfeign.FeignClient; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.RequestHeader; |
| | | import org.springframework.web.bind.annotation.RequestParam; |
| | | |
| | | /** |
| | | * @author mitao |
| | | * @date 2024/9/9 |
| | | */ |
| | | @FeignClient(contextId = "remoteMeditationService", value = ServiceNameConstants.MEDITATION_SERVICE, fallbackFactory = RemoteMeditationFallbackFactory.class) |
| | | public interface RemoteMeditationService { |
| | | |
| | | /** |
| | | * 根据id获取冥想音频 |
| | | * |
| | | * @param targetId 冥想音频id |
| | | * @return 冥想音频 |
| | | */ |
| | | @GetMapping("/inner/meditation/meditation/getMeditationById") |
| | | R<Meditation> getMeditationById(@RequestParam("targetId") Long targetId, |
| | | @RequestHeader(SecurityConstants.FROM_SOURCE) String source); |
| | | } |
File was renamed from xinquan-modules/xinquan-order/src/main/java/com/xinquan/order/domain/Order.java |
| | |
| | | package com.xinquan.order.domain; |
| | | package com.xinquan.order.api.domain; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
New file |
| | |
| | | package com.xinquan.order.api.factory; |
| | | |
| | | import com.xinquan.common.core.domain.R; |
| | | import com.xinquan.order.api.domain.Order; |
| | | import com.xinquan.order.api.feign.RemoteOrderService; |
| | | import java.util.List; |
| | | import org.springframework.cloud.openfeign.FallbackFactory; |
| | | |
| | | /** |
| | | * @author mitao |
| | | * @date 2024/9/9 |
| | | */ |
| | | public class RemoteOrderFallbackFactory implements FallbackFactory<RemoteOrderService> { |
| | | |
| | | @Override |
| | | public RemoteOrderService create(Throwable cause) { |
| | | return new RemoteOrderService() { |
| | | @Override |
| | | public R<List<Order>> getOrderListByType(Long userId, Integer orderFrom, |
| | | String source) { |
| | | return R.fail("获取订单列表失败"); |
| | | } |
| | | }; |
| | | } |
| | | } |
New file |
| | |
| | | package com.xinquan.order.api.feign; |
| | | |
| | | import com.xinquan.common.core.constant.SecurityConstants; |
| | | import com.xinquan.common.core.constant.ServiceNameConstants; |
| | | import com.xinquan.common.core.domain.R; |
| | | import com.xinquan.order.api.domain.Order; |
| | | import com.xinquan.order.api.factory.RemoteOrderFallbackFactory; |
| | | import java.util.List; |
| | | import org.springframework.cloud.openfeign.FeignClient; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestHeader; |
| | | import org.springframework.web.bind.annotation.RequestParam; |
| | | |
| | | /** |
| | | * @author mitao |
| | | * @date 2024/9/9 |
| | | */ |
| | | @FeignClient(contextId = "remoteOrderService", value = ServiceNameConstants.ORDER_SERVICE, fallbackFactory = RemoteOrderFallbackFactory.class) |
| | | public interface RemoteOrderService { |
| | | |
| | | @PostMapping("/inner/order/order/getOrderListByType") |
| | | R<List<Order>> getOrderListByType(@RequestParam("userId") Long userId, |
| | | @RequestParam("orderFrom") Integer orderFrom, |
| | | @RequestHeader(SecurityConstants.FROM_SOURCE) String source); |
| | | } |
| | |
| | | file-extension: yml |
| | | # 共享配置 |
| | | shared-configs: |
| | | - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} |
| | | - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} |
| | | - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} |
| | | meditation: |
| | | secret: V8EZaYQ2gGzFaH7GPLZbw7KGYMRZ8MpF |
| | |
| | | * 默认密码 |
| | | */ |
| | | public static final String DEFAULT_PASSWORD = "123456"; |
| | | /** |
| | | * 支付回调地址 |
| | | */ |
| | | public static final String PAYMENT_NOTIFY_URL = "/client/order/notify"; |
| | | } |
New file |
| | |
| | | package com.xinquan.common.core.enums; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum ChargeTypeEnum { |
| | | FREE(1, "免费"), |
| | | FREE_FOR_VIP(2, "会员免费"), |
| | | SEPARATE_CHARGE(3, "单独收费"); |
| | | |
| | | private final Integer code; |
| | | private final String desc; |
| | | |
| | | public static ChargeTypeEnum getEnumByCode(Integer code) { |
| | | for (ChargeTypeEnum e : ChargeTypeEnum.values()) { |
| | | if (e.code.equals(code)) { |
| | | return e; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | } |
New file |
| | |
| | | package com.xinquan.common.core.enums; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum OrderFromEnum { |
| | | MEDITATION(1, "冥想订单"), |
| | | COURSE(2, "课程订单"), |
| | | VIP(3, "会员订单"); |
| | | |
| | | private final Integer code; |
| | | private final String desc; |
| | | |
| | | public static OrderFromEnum getEnumByCode(Integer code) { |
| | | for (OrderFromEnum e : OrderFromEnum.values()) { |
| | | if (e.code.equals(code)) { |
| | | return e; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | } |
New file |
| | |
| | | package com.xinquan.common.core.enums; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum PaymentStatusEnum { |
| | | TO_BE_PAID(1, "待支付"), |
| | | COMPLETED(2, "已完成"), |
| | | CANCELED(3, "已取消"); |
| | | |
| | | private final Integer code; |
| | | private final String desc; |
| | | |
| | | public static PaymentStatusEnum getEnumByCode(Integer code) { |
| | | for (PaymentStatusEnum e : PaymentStatusEnum.values()) { |
| | | if (e.code.equals(code)) { |
| | | return e; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | } |
New file |
| | |
| | | package com.xinquan.common.core.enums; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum PaymentTypeEnum { |
| | | WECHAT_PAY(1, "微信支付"), |
| | | ALI_PAY(2, "支付宝支付"), |
| | | IOS_PAY(3, "IOS内购支付"), |
| | | BALANCE_PAY(4, "余额支付"); |
| | | |
| | | private final Integer code; |
| | | private final String desc; |
| | | |
| | | public static PaymentTypeEnum getEnumByCode(Integer code) { |
| | | for (PaymentTypeEnum e : PaymentTypeEnum.values()) { |
| | | if (e.code.equals(code)) { |
| | | return e; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | } |
| | |
| | | spring: |
| | | application: |
| | | # 应用名称 |
| | | name: xinquan-auth |
| | | name: xinquan-gateway |
| | | main: |
| | | allow-bean-definition-overriding: true |
| | | profiles: |
| | |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import java.math.BigDecimal; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | |
| | | @ApiModelProperty(value = "价格设定 1=免费 2=会员免费 3=单独收费") |
| | | private Integer chargeType; |
| | | |
| | | @ApiModelProperty(value = "通用价格") |
| | | private BigDecimal generalPrice; |
| | | |
| | | @ApiModelProperty(value = "IOS内购价格") |
| | | private BigDecimal iosPrice; |
| | | |
| | | @ApiModelProperty(value = "排序权重") |
| | | private Integer sortNum; |
| | |
| | | package com.xinquan.course.mapper; |
| | | |
| | | import com.xinquan.course.domain.Course; |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.xinquan.course.api.domain.Course; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.xinquan.common.core.utils.page.PageDTO; |
| | | import com.xinquan.course.domain.Course; |
| | | import com.xinquan.course.api.domain.Course; |
| | | import com.xinquan.course.domain.vo.ClientCourseVO; |
| | | |
| | | /** |
| | |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.xinquan.common.core.utils.page.CollUtils; |
| | | import com.xinquan.common.core.utils.page.PageDTO; |
| | | import com.xinquan.course.domain.Course; |
| | | import com.xinquan.course.api.domain.Course; |
| | | import com.xinquan.course.domain.vo.ClientCourseVO; |
| | | import com.xinquan.course.mapper.CourseMapper; |
| | | import com.xinquan.course.service.CourseService; |
| | |
| | | <mapper namespace="com.xinquan.course.mapper.CourseMapper"> |
| | | |
| | | <!-- 通用查询映射结果 --> |
| | | <resultMap id="BaseResultMap" type="com.xinquan.course.domain.Course"> |
| | | <resultMap id="BaseResultMap" type="com.xinquan.course.api.domain.Course"> |
| | | <id column="id" property="id" /> |
| | | <result column="del_flag" property="delFlag" /> |
| | | <result column="create_by" property="createBy" /> |
| | |
| | | <result column="listing_status" property="listingStatus" /> |
| | | <result column="recommend" property="recommend" /> |
| | | <result column="charge_type" property="chargeType" /> |
| | | <result column="general_price" property="generalPrice"/> |
| | | <result column="ios_price" property="iosPrice"/> |
| | | <result column="sort_num" property="sortNum" /> |
| | | <result column="tutor" property="tutor" /> |
| | | <result column="cover_url" property="coverUrl" /> |
| | |
| | | create_time, |
| | | update_by, |
| | | update_time, |
| | | id, course_type, cate_id, course_title, description, listing_status, recommend, charge_type, sort_num, tutor, cover_url, detail_url, brief_introduction, wx_qr_code, address, address_detail, longitude, latitude |
| | | id, course_type, cate_id, course_title, description, listing_status, recommend, charge_type, general_price,ios_price,sort_num, tutor, cover_url, detail_url, brief_introduction, wx_qr_code, address, address_detail, longitude, latitude |
| | | </sql> |
| | | |
| | | </mapper> |
New file |
| | |
| | | # Tomcat |
| | | server: |
| | | port: 9202 |
| | | |
| | | # Spring |
| | | spring: |
| | | application: |
| | | # 应用名称 |
| | | name: xinquan-gen |
| | | profiles: |
| | | # 环境配置 |
| | | active: dev |
| | | --- |
| | | spring: |
| | | config: |
| | | activate: |
| | | on-profile: dev |
| | | cloud: |
| | | nacos: |
| | | discovery: |
| | | # 服务注册地址 |
| | | server-addr: 192.168.110.64:8848 |
| | | service: ${spring.application.name} |
| | | group: DEFAULT_GROUP |
| | | namespace: 8ebd2324-30b4-477b-af79-b46e717c4fbe |
| | | config: |
| | | # 配置中心地址 |
| | | server-addr: 192.168.110.64:8848 |
| | | namespace: 8ebd2324-30b4-477b-af79-b46e717c4fbe |
| | | group: DEFAULT_GROUP |
| | | name: ${spring.application.name} |
| | | # 配置文件格式 |
| | | file-extension: yml |
| | | # 共享配置 |
| | | shared-configs: |
| | | - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} |
New file |
| | |
| | | # Tomcat |
| | | server: |
| | | port: 9203 |
| | | |
| | | # Spring |
| | | spring: |
| | | application: |
| | | # 应用名称 |
| | | name: xinquan-job |
| | | profiles: |
| | | # 环境配置 |
| | | active: dev |
| | | cloud: |
| | | nacos: |
| | | discovery: |
| | | # 服务注册地址 |
| | | server-addr: 127.0.0.1:8848 |
| | | config: |
| | | # 配置中心地址 |
| | | server-addr: 127.0.0.1:8848 |
| | | # 配置文件格式 |
| | | file-extension: yml |
| | | # 共享配置 |
| | | shared-configs: |
| | | - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} |
| | |
| | | @ApiImplicitParam(name = "pageSize", value = "分页参数,每页数量", dataType = "Integer", required = true) |
| | | }) |
| | | public R<PageDTO<ClientMeditationVO>> search(@RequestParam String condition, |
| | | @RequestParam Integer |
| | | pageCurr, @RequestParam Integer pageSize) { |
| | | @RequestParam Integer pageCurr, @RequestParam Integer pageSize) { |
| | | return R.ok(meditationService.search(condition, pageCurr, pageSize)); |
| | | } |
| | | |
New file |
| | |
| | | package com.xinquan.meditation.controller.inner; |
| | | |
| | | |
| | | import com.xinquan.common.core.domain.R; |
| | | import com.xinquan.meditation.api.domain.Meditation; |
| | | import com.xinquan.meditation.service.MeditationService; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RequestParam; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | /** |
| | | * <p> |
| | | * 首页背景音乐用户关系表 前端控制器 |
| | | * </p> |
| | | * |
| | | * @author mitao |
| | | * @since 2024-08-23 |
| | | */ |
| | | @RestController |
| | | @RequiredArgsConstructor |
| | | @RequestMapping("/inner/meditation/meditation") |
| | | public class InnerMeditationController { |
| | | |
| | | private final MeditationService meditationService; |
| | | |
| | | /** |
| | | * 根据id获取冥想音频 |
| | | * |
| | | * @param targetId 冥想音频id |
| | | * @return 冥想音频 |
| | | */ |
| | | @GetMapping("/getMeditationById") |
| | | R<Meditation> getMeditationById(@RequestParam("targetId") Long targetId) { |
| | | return R.ok(meditationService.getById(targetId)); |
| | | } |
| | | } |
| | | |
| | |
| | | package com.xinquan.meditation.domain; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import com.xinquan.common.core.web.domain.BaseModel; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import java.time.LocalDateTime; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import com.xinquan.common.core.web.domain.BaseModel; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import java.time.LocalTime; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | |
| | | |
| | | @ApiModelProperty(value = "播放时间段开始") |
| | | @TableField("start_play_time") |
| | | private LocalDateTime startPlayTime; |
| | | @JsonFormat(pattern = "HH:mm:ss") |
| | | private LocalTime startPlayTime; |
| | | |
| | | @ApiModelProperty(value = "播放时间段结束") |
| | | @TableField("end_play_time") |
| | | private LocalDateTime endPlayTime; |
| | | @JsonFormat(pattern = "HH:mm:ss") |
| | | private LocalTime endPlayTime; |
| | | |
| | | @ApiModelProperty(value = "每日冥想背景图片") |
| | | @TableField("image_url") |
| | |
| | | * 创建时间 |
| | | */ |
| | | @ApiModelProperty(value = "记录创建时间,前端忽略") |
| | | // @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | | @TableField(value = "create_time", fill = FieldFill.INSERT) |
| | | private LocalDateTime createTime; |
| | | } |
| | |
| | | |
| | | @ApiModelProperty(value = "是否收藏 1:是 2:否") |
| | | private Integer favorite; |
| | | |
| | | @ApiModelProperty(value = "提问数") |
| | | private Long questionCount; |
| | | } |
| | |
| | | package com.xinquan.meditation.domain.vo; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import java.io.Serializable; |
| | | import java.time.LocalDateTime; |
| | | import java.time.LocalTime; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | |
| | | private Long meditationId; |
| | | |
| | | @ApiModelProperty(value = "播放时间段开始") |
| | | private LocalDateTime startPlayTime; |
| | | @JsonFormat(pattern = "HH:mm:ss") |
| | | private LocalTime startPlayTime; |
| | | |
| | | @ApiModelProperty(value = "播放时间段结束") |
| | | private LocalDateTime endPlayTime; |
| | | @JsonFormat(pattern = "HH:mm:ss") |
| | | private LocalTime endPlayTime; |
| | | |
| | | @ApiModelProperty(value = "每日冥想背景图片") |
| | | private String imageUrl; |
| | |
| | | @ApiModelProperty(value = "价格设定 1=免费 2=会员免费 3=单独收费") |
| | | private Integer chargeType; |
| | | |
| | | @ApiModelProperty(value = "是否已付费 1:是 2:否") |
| | | private Integer paidStatus = 2; |
| | | |
| | | @ApiModelProperty(value = "通用价格", notes = "价格设定为单独收费") |
| | | private BigDecimal generalPrice; |
| | | |
| | |
| | | package com.xinquan.meditation.mapper; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.xinquan.meditation.domain.Meditation; |
| | | import com.xinquan.meditation.api.domain.Meditation; |
| | | import com.xinquan.meditation.domain.vo.ClientMeditationVO; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.xinquan.common.core.utils.page.PageDTO; |
| | | import com.xinquan.meditation.domain.Meditation; |
| | | import com.xinquan.meditation.api.domain.Meditation; |
| | | import com.xinquan.meditation.domain.vo.ClientMeditationAndCateVO; |
| | | import com.xinquan.meditation.domain.vo.ClientMeditationDetailsVO; |
| | | import com.xinquan.meditation.domain.vo.ClientMeditationQuestionVO; |
| | |
| | | package com.xinquan.meditation.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.xinquan.common.core.utils.DateUtils; |
| | | import com.xinquan.common.core.utils.page.BeanUtils; |
| | | import com.xinquan.meditation.domain.Meditation; |
| | | import com.xinquan.meditation.api.domain.Meditation; |
| | | import com.xinquan.meditation.domain.MeditationEveryday; |
| | | import com.xinquan.meditation.domain.vo.ClientMeditationEverydayVO; |
| | | import com.xinquan.meditation.domain.vo.ClientMeditationVO; |
| | | import com.xinquan.meditation.mapper.MeditationEverydayMapper; |
| | | import com.xinquan.meditation.mapper.MeditationMapper; |
| | | import com.xinquan.meditation.service.MeditationEverydayService; |
| | | import java.time.LocalDateTime; |
| | | import java.util.Optional; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.stereotype.Service; |
| | |
| | | public ClientMeditationEverydayVO getTodayMeditation() { |
| | | ClientMeditationEverydayVO vo = null; |
| | | // 当前时间 |
| | | LocalDateTime now = LocalDateTime.now(); |
| | | String now = DateUtils.dateTimeNow("HH:mm:ss"); |
| | | // 查询播放时间段在当前时间的每日冥想 |
| | | Optional<MeditationEveryday> meditationEverydayOpt = this.lambdaQuery() |
| | | .le(MeditationEveryday::getStartPlayTime, now) |
| | | .ge(MeditationEveryday::getEndPlayTime, now) |
| | | .gt(MeditationEveryday::getEndPlayTime, now) |
| | | .orderByDesc(MeditationEveryday::getUpdateTime) |
| | | .last("limit 1").oneOpt(); |
| | | if (!meditationEverydayOpt.isPresent()) { |
| | |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.xinquan.common.core.constant.SecurityConstants; |
| | | import com.xinquan.common.core.enums.DisabledEnum; |
| | | import com.xinquan.common.core.enums.OrderFromEnum; |
| | | import com.xinquan.common.core.exception.ServiceException; |
| | | import com.xinquan.common.core.utils.page.BeanUtils; |
| | | import com.xinquan.common.core.utils.page.CollUtils; |
| | | import com.xinquan.common.core.utils.page.PageDTO; |
| | | import com.xinquan.common.security.utils.SecurityUtils; |
| | | import com.xinquan.meditation.domain.Meditation; |
| | | import com.xinquan.meditation.api.domain.Meditation; |
| | | import com.xinquan.meditation.domain.MeditationCategory; |
| | | import com.xinquan.meditation.domain.MeditationMusic; |
| | | import com.xinquan.meditation.domain.MeditationQuestion; |
| | |
| | | import com.xinquan.meditation.service.MeditationQuestionLikeService; |
| | | import com.xinquan.meditation.service.MeditationService; |
| | | import com.xinquan.meditation.service.MeditationUserFavoriteService; |
| | | import com.xinquan.order.api.domain.Order; |
| | | import com.xinquan.order.api.feign.RemoteOrderService; |
| | | import com.xinquan.user.api.domain.AppUser; |
| | | import com.xinquan.user.api.domain.dto.AppUserDTO; |
| | | import com.xinquan.user.api.feign.RemoteAppUserService; |
| | |
| | | private final MeditationQuestionMapper meditationQuestionMapper; |
| | | private final MeditationQuestionLikeService meditationQuestionLikeService; |
| | | private final MeditationUserFavoriteService meditationUserFavoriteService; |
| | | |
| | | private final RemoteOrderService remoteOrderService; |
| | | /** |
| | | * 获取私人订制 |
| | | * |
| | |
| | | .collect(Collectors.toSet()); |
| | | // 查询冥想列表 |
| | | voList = baseMapper.getMeditationListByTagId(tagIdSet, sanskritFlag); |
| | | } |
| | | voList = handlePaidMeditation(voList); |
| | | return voList; |
| | | } |
| | | |
| | | /** |
| | | * 处理已付费冥想音频 |
| | | * |
| | | * @param voList |
| | | * @return |
| | | */ |
| | | private List<ClientMeditationVO> handlePaidMeditation(List<ClientMeditationVO> voList) { |
| | | // 远程调用订单服务,查询用户已付费冥想 |
| | | Long userId = SecurityUtils.getUserId(); |
| | | List<Order> orderList = remoteOrderService.getOrderListByType(userId, |
| | | OrderFromEnum.MEDITATION.getCode(), |
| | | SecurityConstants.INNER).getData(); |
| | | List<Long> meditationIdList = orderList.stream().map(Order::getBusinessId) |
| | | .collect(Collectors.toList()); |
| | | if (CollUtils.isNotEmpty(meditationIdList)) { |
| | | voList = voList.stream() |
| | | .filter(meditationVO -> meditationIdList.contains(meditationVO.getId())) |
| | | .peek(meditationVO -> meditationVO.setPaidStatus(1)) |
| | | .collect(Collectors.toList()); |
| | | } |
| | | return voList; |
| | | } |
| | |
| | | // 对象拷贝 |
| | | voList = BeanUtils.copyList(list, ClientMeditationVO.class); |
| | | } |
| | | handlePaidMeditation(voList); |
| | | return voList; |
| | | } |
| | | |
| | |
| | | });*/ |
| | | // 将实体类转换为VO |
| | | pageDTO = PageDTO.of(page, ClientMeditationVO.class); |
| | | handlePaidMeditation(pageDTO.getList()); |
| | | return pageDTO; |
| | | } |
| | | |
| | |
| | | .eq(MeditationUserFavorite::getMeditationId, id) |
| | | .eq(MeditationUserFavorite::getAppUserId, SecurityUtils.getUserId()) |
| | | .count() > 0 ? 1 : 2); |
| | | // 获取提问数 |
| | | vo.setQuestionCount(meditationQuestionMapper.selectCount( |
| | | Wrappers.lambdaQuery(MeditationQuestion.class) |
| | | .eq(MeditationQuestion::getMeditationId, id))); |
| | | return vo; |
| | | } |
| | | |
| | |
| | | .last("limit 1").oneOpt(); |
| | | if (userOperationOpt.isPresent()) { |
| | | meditationUserFavoriteService.removeById(userOperationOpt.get()); |
| | | // 增加收藏数 |
| | | // 减少收藏数 |
| | | meditation.setFavoriteCount(meditation.getFavoriteCount() - 1); |
| | | } else { |
| | | // 增加收藏记录 |
| | |
| | | meditationUserFavorite.setMeditationId(id); |
| | | meditationUserFavorite.setAppUserId(SecurityUtils.getUserId()); |
| | | meditationUserFavoriteService.save(meditationUserFavorite); |
| | | // 减少收藏数 |
| | | // 增加收藏数 |
| | | meditation.setFavoriteCount(meditation.getFavoriteCount() + 1); |
| | | } |
| | | this.updateById(meditation); |
| | |
| | | <mapper namespace="com.xinquan.meditation.mapper.MeditationMapper"> |
| | | |
| | | <!-- 通用查询映射结果 --> |
| | | <resultMap id="BaseResultMap" type="com.xinquan.meditation.domain.Meditation"> |
| | | <resultMap id="BaseResultMap" type="com.xinquan.meditation.api.domain.Meditation"> |
| | | <id column="id" property="id" /> |
| | | <result column="del_flag" property="delFlag" /> |
| | | <result column="create_by" property="createBy" /> |
| | |
| | | <result column="detail_description" property="detailDescription" /> |
| | | <result column="cover_description" property="coverDescription" /> |
| | | <result column="tutor_audio_url" property="tutorAudioUrl" /> |
| | | <result column="tutor_audio_duration" property="tutorAudioDuration"/> |
| | | <result column="favorite_count" property="favoriteCount" /> |
| | | </resultMap> |
| | | |
| | |
| | | <id column="id" property="id" /> |
| | | <result column="meditation_id" property="meditationId" /> |
| | | <result column="music_url" property="musicUrl" /> |
| | | <result column="music_duration" property="musicDuration"/> |
| | | </resultMap> |
| | | |
| | | <!-- 通用查询结果列 --> |
| | |
| | | |
| | | |
| | | import com.xinquan.common.core.domain.R; |
| | | import com.xinquan.order.domain.vo.ClientPlaceOrderVO; |
| | | import com.xinquan.order.service.OrderService; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiImplicitParam; |
| | | import io.swagger.annotations.ApiImplicitParams; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RequestParam; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | /** |
| | |
| | | |
| | | private OrderService orderService; |
| | | |
| | | @PostMapping("/createOrder") |
| | | @ApiOperation(value = "创建订单") |
| | | public R<?> createOrder() { |
| | | return R.ok(); |
| | | /** |
| | | * 创建待支付订单 |
| | | * |
| | | * @param targetId 目标id |
| | | * @param orderFrom 订单来源 1=冥想音频 2=课程 |
| | | * @param receiverId 被赠送课程APP用户id |
| | | * @param balanceFlag 是否使用余额抵扣 1=是 2=否 |
| | | * @param payType 支付方式 1=微信 2=支付宝 |
| | | * @return 下单返回数据视图对象 |
| | | * @see com.xinquan.order.domain.vo.ClientPlaceOrderVO |
| | | */ |
| | | @PostMapping("/placeOrder") |
| | | @ApiOperation(value = "创建待支付订单", notes = "微信|支付宝") |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(name = "targetId", value = "目标id", dataType = "Long", required = true), |
| | | @ApiImplicitParam(name = "orderFrom", value = "订单来源 1=冥想音频 2=课程", dataType = "Integer", required = true), |
| | | @ApiImplicitParam(name = "receiverId", value = "被赠送课程APP用户id", dataType = "Long", required = false), |
| | | @ApiImplicitParam(name = "balanceFlag", value = "是否使用余额抵扣 1=是 2=否", dataType = "Integer", required = true), |
| | | @ApiImplicitParam(name = "payType", value = "支付方式 1=微信 2=支付宝", dataType = "Integer", required = true) |
| | | }) |
| | | public R<ClientPlaceOrderVO> placeOrder( |
| | | @RequestParam(value = "targetId") Long targetId, |
| | | @RequestParam(value = "orderFrom") Integer orderFrom, |
| | | @RequestParam(value = "receiverId", required = false) Long receiverId, |
| | | @RequestParam(value = "balanceFlag") Integer balanceFlag, |
| | | @RequestParam(value = "payType") Integer payType) { |
| | | try { |
| | | return R.ok( |
| | | orderService.placeOrder(targetId, orderFrom, receiverId, |
| | | balanceFlag, payType)); |
| | | } catch (Exception e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | } |
| | | |
New file |
| | |
| | | package com.xinquan.order.controller.client; |
| | | |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | /** |
| | | * 支付回调控制器 |
| | | * |
| | | * @author mitao |
| | | * @date 2024/9/9 |
| | | */ |
| | | @RestController |
| | | @RequestMapping("/client/order/notify") |
| | | public class NotifyController { |
| | | |
| | | } |
New file |
| | |
| | | package com.xinquan.order.controller.inner; |
| | | |
| | | |
| | | import com.xinquan.common.core.domain.R; |
| | | import com.xinquan.common.security.annotation.InnerAuth; |
| | | import com.xinquan.order.api.domain.Order; |
| | | import com.xinquan.order.service.OrderService; |
| | | import java.util.List; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RequestParam; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | /** |
| | | * <p> |
| | | * 订单表 前端控制器 |
| | | * </p> |
| | | * |
| | | * @author mitao |
| | | * @since 2024-08-21 |
| | | */ |
| | | @RestController |
| | | @RequiredArgsConstructor |
| | | @RequestMapping("/inner/order/order") |
| | | public class InnerOrderController { |
| | | |
| | | private final OrderService orderService; |
| | | |
| | | /** |
| | | * 根据类型获取已完成的订单列表 |
| | | * |
| | | * @param userId 用户id |
| | | * @param orderFrom 订单来源 |
| | | * @return |
| | | */ |
| | | @InnerAuth |
| | | @PostMapping("/getOrderListByType") |
| | | R<List<Order>> getOrderListByType(@RequestParam("userId") Long userId, |
| | | @RequestParam("orderFrom") Integer orderFrom) { |
| | | return R.ok(orderService.getOrderListByType(userId, orderFrom)); |
| | | } |
| | | |
| | | } |
| | | |
| | |
| | | package com.xinquan.order.domain; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import java.math.BigDecimal; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import com.xinquan.common.core.web.domain.BaseModel; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import java.math.BigDecimal; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | |
| | | @TableField("order_id") |
| | | private Long orderId; |
| | | |
| | | @ApiModelProperty(value = "支付类型 1=微信支付 2=支付宝支付 3=余额支付 4=IOS内购支付") |
| | | @ApiModelProperty(value = "支付类型 1=微信支付 2=支付宝支付 3=IOS内购支付 4=余额支付") |
| | | @TableField("payment_type") |
| | | private Integer paymentType; |
| | | |
| | |
| | | @TableField("pay_amount") |
| | | private BigDecimal payAmount; |
| | | |
| | | @ApiModelProperty(value = "支付商户订单号") |
| | | @ApiModelProperty(value = "第三方支付订单号") |
| | | @TableField("pay_order_no") |
| | | private String payOrderNo; |
| | | |
| | | |
| | | @ApiModelProperty(value = "支付状态 1=待支付 2=已完成 3=已取消") |
| | | @TableField("payment_status") |
| | | private Integer paymentStatus; |
| | | } |
New file |
| | |
| | | package com.xinquan.order.domain.vo; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import java.io.Serializable; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * @author mitao |
| | | * @date 2024/9/9 |
| | | */ |
| | | @Data |
| | | @ApiModel("下单返回数据视图对象") |
| | | public class ClientPlaceOrderVO implements Serializable { |
| | | |
| | | private static final long serialVersionUID = -7087327695114447889L; |
| | | @ApiModelProperty("订单id") |
| | | private Long id; |
| | | |
| | | @ApiModelProperty(value = "订单编号") |
| | | private String orderNo; |
| | | |
| | | @ApiModelProperty(value = "金额为零无需支付 1是 2否") |
| | | private Integer zeroFlag; |
| | | |
| | | @ApiModelProperty("支付宝支付链接") |
| | | private String qrcodeUrl; |
| | | |
| | | @ApiModelProperty("微信支付信息,用于唤起微信支付") |
| | | private String payInfo; |
| | | } |
| | |
| | | package com.xinquan.order.mapper; |
| | | |
| | | import com.xinquan.order.domain.Order; |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.xinquan.order.api.domain.Order; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | package com.xinquan.order.service; |
| | | |
| | | import com.xinquan.order.domain.Order; |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.xinquan.order.api.domain.Order; |
| | | import com.xinquan.order.domain.vo.ClientPlaceOrderVO; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | */ |
| | | public interface OrderService extends IService<Order> { |
| | | |
| | | /** |
| | | * 创建待支付订单 |
| | | * |
| | | * @param targetId 目标id |
| | | * @param orderFrom 订单来源 1=冥想音频 2=课程 |
| | | * @param receiverId 被赠送课程APP用户id |
| | | * @param balanceFlag 是否使用余额抵扣 1=是 2=否 |
| | | * @param payType 支付方式 1=微信 2=支付宝 |
| | | * @return 下单返回数据视图对象 |
| | | * @see com.xinquan.order.domain.vo.ClientPlaceOrderVO |
| | | */ |
| | | ClientPlaceOrderVO placeOrder(Long targetId, Integer orderFrom, Long receiverId, |
| | | Integer balanceFlag, Integer payType) throws Exception; |
| | | |
| | | /** |
| | | * 根据类型获取已完成的订单列表 |
| | | * |
| | | * @param userId 用户id |
| | | * @param orderFrom 订单来源 |
| | | * @return |
| | | */ |
| | | List<Order> getOrderListByType(Long userId, Integer orderFrom); |
| | | } |
| | |
| | | package com.xinquan.order.service.impl; |
| | | |
| | | import com.xinquan.order.domain.Order; |
| | | import com.xinquan.order.mapper.OrderMapper; |
| | | import com.xinquan.order.service.OrderService; |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.xinquan.common.core.constant.Constants; |
| | | import com.xinquan.common.core.constant.SecurityConstants; |
| | | import com.xinquan.common.core.enums.ChargeTypeEnum; |
| | | import com.xinquan.common.core.enums.DisabledEnum; |
| | | import com.xinquan.common.core.enums.PaymentStatusEnum; |
| | | import com.xinquan.common.core.enums.PaymentTypeEnum; |
| | | import com.xinquan.common.core.exception.ServiceException; |
| | | import com.xinquan.common.core.utils.ip.IpUtils; |
| | | import com.xinquan.common.security.utils.SecurityUtils; |
| | | import com.xinquan.course.api.domain.Course; |
| | | import com.xinquan.course.api.feign.RemoteCourseService; |
| | | import com.xinquan.meditation.api.domain.Meditation; |
| | | import com.xinquan.meditation.api.feign.RemoteMeditationService; |
| | | import com.xinquan.order.api.domain.Order; |
| | | import com.xinquan.order.domain.OrderPaymentRecord; |
| | | import com.xinquan.order.domain.vo.ClientPlaceOrderVO; |
| | | import com.xinquan.order.mapper.OrderMapper; |
| | | import com.xinquan.order.service.OrderPaymentRecordService; |
| | | import com.xinquan.order.service.OrderService; |
| | | import com.xinquan.order.utils.JuHeFuUtil; |
| | | import com.xinquan.order.utils.OrderUtil; |
| | | import com.xinquan.user.api.domain.AppUser; |
| | | import com.xinquan.user.api.domain.dto.AppUserDTO; |
| | | import com.xinquan.user.api.feign.RemoteAppUserService; |
| | | import java.math.BigDecimal; |
| | | import java.util.List; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.jetbrains.annotations.NotNull; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | * @since 2024-08-21 |
| | | */ |
| | | @Service |
| | | @RequiredArgsConstructor |
| | | public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService { |
| | | |
| | | private final RemoteMeditationService remoteMeditationService; |
| | | private final RemoteCourseService remoteCourseService; |
| | | private final RemoteAppUserService remoteAppUserService; |
| | | private final OrderPaymentRecordService orderPaymentRecordService; |
| | | |
| | | /** |
| | | * 创建待支付订单 |
| | | * |
| | | * @param targetId 目标id |
| | | * @param orderFrom 订单来源 1=冥想音频 2=课程 |
| | | * @param receiverId 被赠送课程APP用户id |
| | | * @param balanceFlag 是否使用余额抵扣 1=是 2=否 |
| | | * @param payType 支付方式 1=微信 2=支付宝 |
| | | * @return 下单返回数据视图对象 |
| | | * @see com.xinquan.order.domain.vo.ClientPlaceOrderVO |
| | | */ |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public ClientPlaceOrderVO placeOrder(Long targetId, Integer orderFrom, Long receiverId, |
| | | Integer balanceFlag, Integer payType) throws Exception { |
| | | // 获取当前登录用户id |
| | | Long userId = SecurityUtils.getUserId(); |
| | | // 获取用户信息 |
| | | AppUser appUser = getAppUserById(userId); |
| | | ClientPlaceOrderVO clientPlaceOrderVO = new ClientPlaceOrderVO(); |
| | | Order order = new Order(); |
| | | // 购买冥想音频 |
| | | if (orderFrom == 1) { |
| | | Meditation meditation = remoteMeditationService.getMeditationById(targetId, |
| | | SecurityConstants.INNER).getData(); |
| | | String meditationTitle = meditation.getMeditationTitle(); |
| | | String detailDescription = meditation.getDetailDescription(); |
| | | String wxOpenId = appUser.getWxOpenId(); |
| | | // 创建订单 |
| | | String orderNo = OrderUtil.getOrderNoForPrefix("MX"); |
| | | order.setOrderFrom(orderFrom); |
| | | order.setBizOrderNo(orderNo); |
| | | order.setBusinessId(meditation.getId()); |
| | | order.setAppUserId(userId); |
| | | order.setTotalAmount(meditation.getGeneralPrice()); |
| | | this.save(order); |
| | | Long orderId = order.getId(); |
| | | clientPlaceOrderVO.setOrderNo(orderNo); |
| | | clientPlaceOrderVO.setId(orderId); |
| | | // 如果冥想音频价格设定为单独收费,且需要使用余额抵扣 |
| | | if (balanceFlag.equals(1) && meditation.getChargeType() |
| | | .equals(ChargeTypeEnum.SEPARATE_CHARGE.getCode())) { |
| | | BigDecimal needPayAmount = handleBalancePayment(appUser, |
| | | meditation.getGeneralPrice(), |
| | | orderId); |
| | | |
| | | if (needPayAmount.compareTo(BigDecimal.ZERO) <= 0) { |
| | | clientPlaceOrderVO.setZeroFlag(DisabledEnum.YES.getCode()); |
| | | return clientPlaceOrderVO; |
| | | } |
| | | // 创建支付订单 |
| | | createPayment(payType, orderNo, needPayAmount, meditationTitle, detailDescription, |
| | | wxOpenId, orderId, clientPlaceOrderVO); |
| | | } else { |
| | | // 创建支付订单 |
| | | createPayment(payType, orderNo, meditation.getGeneralPrice(), meditationTitle, |
| | | detailDescription, wxOpenId, orderId, clientPlaceOrderVO); |
| | | } |
| | | } else { |
| | | // 购买课程 |
| | | Course course = remoteCourseService.getCourseById(targetId, |
| | | SecurityConstants.INNER).getData(); |
| | | String courseTitle = course.getCourseTitle(); |
| | | String wxOpenId = appUser.getWxOpenId(); |
| | | String description = course.getDescription(); |
| | | |
| | | // 创建订单 |
| | | String orderNo = OrderUtil.getOrderNoForPrefix("KC"); |
| | | order.setOrderFrom(orderFrom); |
| | | order.setBizOrderNo(orderNo); |
| | | order.setBusinessId(course.getId()); |
| | | order.setAppUserId(userId); |
| | | order.setTotalAmount(course.getGeneralPrice()); |
| | | this.save(order); |
| | | Long orderId = order.getId(); |
| | | clientPlaceOrderVO.setOrderNo(orderNo); |
| | | clientPlaceOrderVO.setId(orderId); |
| | | |
| | | if (balanceFlag.equals(1) && course.getChargeType() |
| | | .equals(ChargeTypeEnum.SEPARATE_CHARGE.getCode())) { |
| | | BigDecimal needPayAmount = handleBalancePayment(appUser, course.getGeneralPrice(), |
| | | orderId); |
| | | |
| | | if (needPayAmount.compareTo(BigDecimal.ZERO) <= 0) { |
| | | clientPlaceOrderVO.setZeroFlag(DisabledEnum.YES.getCode()); |
| | | return clientPlaceOrderVO; |
| | | } |
| | | // 创建支付订单 |
| | | createPayment(payType, orderNo, needPayAmount, courseTitle, description, |
| | | wxOpenId, orderId, clientPlaceOrderVO); |
| | | } else { |
| | | // 创建支付订单 |
| | | createPayment(payType, orderNo, course.getGeneralPrice(), courseTitle, |
| | | description, wxOpenId, orderId, clientPlaceOrderVO); |
| | | } |
| | | } |
| | | return clientPlaceOrderVO; |
| | | } |
| | | |
| | | /** |
| | | * 处理余额抵扣 |
| | | * |
| | | * @param appUser app用户 |
| | | * @param generalPrice 通用价格 |
| | | * @param orderId 订单号 |
| | | * @return 需要支付的金额 |
| | | */ |
| | | @NotNull |
| | | private BigDecimal handleBalancePayment(AppUser appUser, BigDecimal generalPrice, |
| | | Long orderId) { |
| | | if (appUser.getBalance().compareTo(BigDecimal.ZERO) < 0) { |
| | | throw new ServiceException("用户可用余额不足,请重新选择支付方案"); |
| | | } |
| | | // 更新用户余额 |
| | | remoteAppUserService.updateAppUser( |
| | | AppUserDTO.builder().balance( |
| | | appUser.getBalance().subtract(generalPrice)) |
| | | .build(), SecurityConstants.INNER); |
| | | |
| | | OrderPaymentRecord balancePaymentRecord = new OrderPaymentRecord(); |
| | | balancePaymentRecord.setOrderId(orderId); |
| | | balancePaymentRecord.setPaymentType(PaymentTypeEnum.BALANCE_PAY.getCode()); |
| | | balancePaymentRecord.setPaymentStatus(PaymentStatusEnum.COMPLETED.getCode()); |
| | | orderPaymentRecordService.save(balancePaymentRecord); |
| | | |
| | | // 计算除去余额还需支付的金额 |
| | | return generalPrice |
| | | .subtract(appUser.getBalance()); |
| | | } |
| | | |
| | | /** |
| | | * 获取登录用户信息 |
| | | * |
| | | * @param userId APP用户id |
| | | * @return AppUser |
| | | */ |
| | | private AppUser getAppUserById(Long userId) { |
| | | return remoteAppUserService.getUserByCondition( |
| | | AppUserDTO.builder().id(userId).build(), |
| | | SecurityConstants.INNER).getData(); |
| | | } |
| | | |
| | | /** |
| | | * 创建支付订单 |
| | | * |
| | | * @param payType 支付方式 1=微信 2=支付宝 |
| | | * @param orderNo 订单编号 |
| | | * @param needPayAmount 支付金额 |
| | | * @param goodsTitle 商品标题 |
| | | * @param goodsDesc 商品描述 |
| | | * @param wxOpenId 微信openId |
| | | * @param orderId 订单id |
| | | * @param clientPlaceOrderVO 下单返回数据视图对象 |
| | | * @throws Exception |
| | | */ |
| | | private void createPayment(Integer payType, String orderNo, BigDecimal needPayAmount, |
| | | String goodsTitle, String goodsDesc, String wxOpenId, Long orderId, |
| | | ClientPlaceOrderVO clientPlaceOrderVO) throws Exception { |
| | | // 截取前42个字符 商品描述信息,微信小程序和微信公众号该字段,最大长度 42 个字符 |
| | | goodsDesc = goodsDesc.substring(0, 42); |
| | | // 调用第三方支付获取支付信息 |
| | | JSONObject payInfo = JuHeFuUtil.createPayment(orderNo, payType, |
| | | needPayAmount.toString(), goodsTitle, goodsDesc, |
| | | IpUtils.getIpAddr(), wxOpenId, Constants.PAYMENT_NOTIFY_URL); |
| | | // 第三方支付记录 |
| | | OrderPaymentRecord paymentRecord = new OrderPaymentRecord(); |
| | | paymentRecord.setOrderId(orderId); |
| | | |
| | | if (payType == 1) { |
| | | clientPlaceOrderVO.setPayInfo(payInfo.getString("pay_info")); |
| | | paymentRecord.setPaymentType(PaymentTypeEnum.WECHAT_PAY.getCode()); |
| | | } else { |
| | | clientPlaceOrderVO.setQrcodeUrl(payInfo.getString("qrcode_url")); |
| | | paymentRecord.setPaymentType(PaymentTypeEnum.ALI_PAY.getCode()); |
| | | } |
| | | |
| | | paymentRecord.setPaymentStatus(PaymentStatusEnum.TO_BE_PAID.getCode()); |
| | | orderPaymentRecordService.save(paymentRecord); |
| | | // 设置订单是否需要支付标识 |
| | | clientPlaceOrderVO.setZeroFlag(DisabledEnum.NO.getCode()); |
| | | } |
| | | |
| | | /** |
| | | * 根据类型获取已完成的订单列表 |
| | | * |
| | | * @param userId 用户id |
| | | * @param orderFrom 订单来源 |
| | | * @return |
| | | */ |
| | | @Override |
| | | public List<Order> getOrderListByType(Long userId, Integer orderFrom) { |
| | | return this.lambdaQuery().eq(Order::getAppUserId, userId).eq(Order::getOrderFrom, orderFrom) |
| | | .eq(Order::getPaymentStatus, PaymentStatusEnum.COMPLETED.getCode()).list(); |
| | | } |
| | | } |
| | |
| | | * @return JSONObject |
| | | * @throws Exception |
| | | */ |
| | | public JSONObject createPayment(String orderNo, Integer payChannel, String payAmt, |
| | | public static JSONObject createPayment(String orderNo, Integer payChannel, String payAmt, |
| | | String goodsTitle, String goodsDesc, String deviceIp, String openId, |
| | | String notifyUrl) throws Exception { |
| | | JSONObject data = new JSONObject(); |
| | |
| | | * @param orderNo 订单号 |
| | | * @return |
| | | */ |
| | | public boolean refund(String paymentId, String orderNo) throws Exception { |
| | | public static boolean refund(String paymentId, String orderNo) throws Exception { |
| | | JSONObject data = new JSONObject(); |
| | | data.put("payment_id", paymentId); |
| | | data.put("order_no", orderNo); |
| | |
| | | * @return |
| | | * @throws Exception |
| | | */ |
| | | public boolean merchantPay(String orderNo, String payAmt, String cardName, String cardId, |
| | | public static boolean merchantPay(String orderNo, String payAmt, String cardName, String cardId, |
| | | String cardType) |
| | | throws Exception { |
| | | JSONObject data = new JSONObject(); |
New file |
| | |
| | | package com.xinquan.order.utils; |
| | | |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * 订单处理工具类 |
| | | */ |
| | | public class OrderUtil { |
| | | |
| | | /* 订单号 */ |
| | | private static long orderNum = 0l; |
| | | |
| | | /* 日期 */ |
| | | private static String date; |
| | | |
| | | /** |
| | | * 生成不重复的订单号 【纯数字】 |
| | | * |
| | | * @return |
| | | */ |
| | | public static synchronized String getOrderNo() { |
| | | String str = new SimpleDateFormat("yyMMddHHmm").format(new Date()); |
| | | if (date == null || !date.equals(str)) { |
| | | date = str; |
| | | orderNum = 0l; |
| | | } |
| | | orderNum++; |
| | | long orderNo = Long.parseLong((date)) * 10000; |
| | | orderNo += orderNum; |
| | | return orderNo + ""; |
| | | } |
| | | |
| | | /** |
| | | * 生成不重复的订单号 【含前缀】 |
| | | * |
| | | * @param prefix |
| | | * @return |
| | | */ |
| | | public static synchronized String getOrderNoForPrefix(String prefix) { |
| | | return prefix + getOrderNo(); |
| | | } |
| | | |
| | | /** |
| | | * 生成不重复的订单号 【含后缀】 |
| | | * |
| | | * @param suffix |
| | | * @return |
| | | */ |
| | | public static synchronized String getOrderNoForSuffix(String suffix) { |
| | | return getOrderNo() + suffix; |
| | | } |
| | | |
| | | } |
| | |
| | | <mapper namespace="com.xinquan.order.mapper.OrderMapper"> |
| | | |
| | | <!-- 通用查询映射结果 --> |
| | | <resultMap id="BaseResultMap" type="com.xinquan.order.domain.Order"> |
| | | <resultMap id="BaseResultMap" type="com.xinquan.order.api.domain.Order"> |
| | | <id column="id" property="id" /> |
| | | <result column="del_flag" property="delFlag" /> |
| | | <result column="create_by" property="createBy" /> |
| | |
| | | <result column="payment_type" property="paymentType" /> |
| | | <result column="pay_amount" property="payAmount" /> |
| | | <result column="pay_order_no" property="payOrderNo" /> |
| | | <result column="payment_status" property="paymentStatus"/> |
| | | </resultMap> |
| | | |
| | | <!-- 通用查询结果列 --> |
| | |
| | | create_time, |
| | | update_by, |
| | | update_time, |
| | | id, order_id, payment_type, pay_amount, pay_order_no |
| | | id, order_id, payment_type, pay_amount, pay_order_no,payment_status |
| | | </sql> |
| | | |
| | | </mapper> |
New file |
| | |
| | | package com.xinquan.user.controller.client; |
| | | |
| | | |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | /** |
| | | * <p> |
| | | * 前端控制器 |
| | | * </p> |
| | | * |
| | | * @author mitao |
| | | * @since 2024-09-09 |
| | | */ |
| | | @RestController |
| | | @RequestMapping("/client/user/notice-record") |
| | | public class ClientNoticeRecordController { |
| | | |
| | | } |
| | | |
New file |
| | |
| | | package com.xinquan.user.controller.inner; |
| | | |
| | | |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | /** |
| | | * <p> |
| | | * 前端控制器 |
| | | * </p> |
| | | * |
| | | * @author mitao |
| | | * @since 2024-09-09 |
| | | */ |
| | | @RestController |
| | | @RequestMapping("/inner/user/notice-record") |
| | | public class InnerNoticeRecordController { |
| | | |
| | | } |
| | | |
New file |
| | |
| | | package com.xinquan.user.domain; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import com.xinquan.common.core.web.domain.BaseModel; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | /** |
| | | * <p> |
| | | * |
| | | * </p> |
| | | * |
| | | * @author mitao |
| | | * @since 2024-09-09 |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @TableName("t_notice_record") |
| | | @ApiModel(value = "NoticeRecord对象", description = "") |
| | | public class NoticeRecord extends BaseModel { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @ApiModelProperty(value = "id") |
| | | @TableId(value = "id", type = IdType.ASSIGN_ID) |
| | | private Long id; |
| | | |
| | | @ApiModelProperty(value = "APP用户id") |
| | | @TableField("app_user_id") |
| | | private Long appUserId; |
| | | |
| | | @ApiModelProperty(value = "冥想提问id 类型为回复通知时使用") |
| | | @TableField("meditation_question_id") |
| | | private Long meditationQuestionId; |
| | | |
| | | @ApiModelProperty(value = "查看状态 1:未读 2:已读 ") |
| | | @TableField("read_status") |
| | | private Integer readStatus; |
| | | |
| | | @ApiModelProperty(value = "通知类型 1=系统通知 2=回复通知") |
| | | @TableField("notice_type") |
| | | private Integer noticeType; |
| | | |
| | | @ApiModelProperty(value = "通知标题") |
| | | @TableField("title") |
| | | private String title; |
| | | |
| | | @ApiModelProperty(value = "通知内容") |
| | | @TableField("content") |
| | | private String content; |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.xinquan.user.mapper; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.xinquan.user.domain.NoticeRecord; |
| | | |
| | | /** |
| | | * <p> |
| | | * Mapper 接口 |
| | | * </p> |
| | | * |
| | | * @author mitao |
| | | * @since 2024-09-09 |
| | | */ |
| | | public interface NoticeRecordMapper extends BaseMapper<NoticeRecord> { |
| | | |
| | | } |
New file |
| | |
| | | package com.xinquan.user.service; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.xinquan.user.domain.NoticeRecord; |
| | | |
| | | /** |
| | | * <p> |
| | | * 服务类 |
| | | * </p> |
| | | * |
| | | * @author mitao |
| | | * @since 2024-09-09 |
| | | */ |
| | | public interface NoticeRecordService extends IService<NoticeRecord> { |
| | | |
| | | } |
New file |
| | |
| | | package com.xinquan.user.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.xinquan.user.domain.NoticeRecord; |
| | | import com.xinquan.user.mapper.NoticeRecordMapper; |
| | | import com.xinquan.user.service.NoticeRecordService; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | /** |
| | | * <p> |
| | | * 服务实现类 |
| | | * </p> |
| | | * |
| | | * @author mitao |
| | | * @since 2024-09-09 |
| | | */ |
| | | @Service |
| | | public class NoticeRecordServiceImpl extends |
| | | ServiceImpl<NoticeRecordMapper, NoticeRecord> implements NoticeRecordService { |
| | | |
| | | } |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| | | <mapper namespace="com.xinquan.user.mapper.NoticeRecordMapper"> |
| | | |
| | | <!-- 通用查询映射结果 --> |
| | | <resultMap id="BaseResultMap" type="com.xinquan.user.domain.NoticeRecord"> |
| | | <id column="id" property="id" /> |
| | | <result column="del_flag" property="delFlag" /> |
| | | <result column="create_by" property="createBy" /> |
| | | <result column="create_time" property="createTime" /> |
| | | <result column="update_by" property="updateBy" /> |
| | | <result column="update_time" property="updateTime" /> |
| | | <result column="app_user_id" property="appUserId" /> |
| | | <result column="meditation_question_id" property="meditationQuestionId" /> |
| | | <result column="read_status" property="readStatus" /> |
| | | <result column="notice_type" property="noticeType" /> |
| | | <result column="title" property="title" /> |
| | | <result column="content" property="content" /> |
| | | </resultMap> |
| | | |
| | | <!-- 通用查询结果列 --> |
| | | <sql id="Base_Column_List"> |
| | | del_flag, |
| | | create_by, |
| | | create_time, |
| | | update_by, |
| | | update_time, |
| | | id, app_user_id, meditation_question_id, read_status, notice_type, title, content |
| | | </sql> |
| | | |
| | | </mapper> |
New file |
| | |
| | | # replace default config |
| | | |
| | | # multipass: true |
| | | # full: true |
| | | |
| | | plugins: |
| | | |
| | | # - name |
| | | # |
| | | # or: |
| | | # - name: false |
| | | # - name: true |
| | | # |
| | | # or: |
| | | # - name: |
| | | # param1: 1 |
| | | # param2: 2 |
| | | |
| | | - removeAttrs: |
| | | attrs: |
| | | - 'fill' |
| | | - 'fill-rule' |
New file |
| | |
| | | # Tomcat |
| | | server: |
| | | port: 9100 |
| | | |
| | | # Spring |
| | | spring: |
| | | application: |
| | | # 应用名称 |
| | | name: xinquan-monitor |
| | | profiles: |
| | | # 环境配置 |
| | | active: dev |
| | | cloud: |
| | | nacos: |
| | | discovery: |
| | | # 服务注册地址 |
| | | server-addr: 127.0.0.1:8848 |
| | | config: |
| | | # 配置中心地址 |
| | | server-addr: 127.0.0.1:8848 |
| | | # 配置文件格式 |
| | | file-extension: yml |
| | | # 共享配置 |
| | | shared-configs: |
| | | - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} |