ソースを参照

spotify多个车队升级个人

zoujiajian 1 年間 前
コミット
faff106603
37 ファイル変更1065 行追加20 行削除
  1. 10 0
      netflix-common/src/main/java/com/cyksj/common/constant/Constant.java
  2. 3 0
      netflix-dao/src/main/java/com/cyksj/mapper/GroupsRelationMapper.java
  3. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/SpotifyUserSelfServiceRecordMapper.java
  4. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/SpotifyUserUpgradeOrderMapper.java
  5. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/SpotifyUserUpgradeSubmitRecordMapper.java
  6. 38 0
      netflix-dao/src/main/java/com/cyksj/model/dto/SpotifyOrderInfoDto.java
  7. 16 0
      netflix-dao/src/main/java/com/cyksj/model/entity/SpotifyUserSelfServiceRecord.java
  8. 81 0
      netflix-dao/src/main/java/com/cyksj/model/entity/SpotifyUserUpgradeOrder.java
  9. 40 0
      netflix-dao/src/main/java/com/cyksj/model/entity/SpotifyUserUpgradeSubmitRecord.java
  10. 7 1
      netflix-dao/src/main/java/com/cyksj/model/entity/ZfbShopOrderDayLimit.java
  11. 3 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/CorpWxOrderDonView.java
  12. 26 0
      netflix-dao/src/main/java/com/cyksj/model/request/SpotifyUpgradeInfoReq.java
  13. 18 0
      netflix-dao/src/main/java/com/cyksj/model/request/SpotifyUpgradeOrderReq.java
  14. 5 1
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonSkuFrontView.java
  15. 1 2
      netflix-dao/src/main/java/com/cyksj/model/views/RenewalView.java
  16. 48 0
      netflix-dao/src/main/java/com/cyksj/model/views/SpotifyUserUpgradeOrderView.java
  17. 54 0
      netflix-dao/src/main/java/com/cyksj/model/views/SpotifyUserUpgradeSubmitRecordView.java
  18. 3 0
      netflix-dao/src/main/java/com/cyksj/model/views/UserTicketView.java
  19. 6 3
      netflix-dao/src/main/java/com/cyksj/model/views/YHLXUserDetailView.java
  20. 18 0
      netflix-dao/src/main/resources/mapper/GroupRelationMapper.xml
  21. 2 0
      netflix-service/src/main/java/com/cyksj/config/zfb/BaseZfbConfig.java
  22. 2 0
      netflix-service/src/main/java/com/cyksj/service/corp/CorpUserService.java
  23. 28 0
      netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpUserServiceImpl.java
  24. 4 0
      netflix-service/src/main/java/com/cyksj/service/order/OrderDonService.java
  25. 2 0
      netflix-service/src/main/java/com/cyksj/service/order/OrderRefundService.java
  26. 45 0
      netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java
  27. 46 0
      netflix-service/src/main/java/com/cyksj/service/order/impl/OrderRefundServiceImpl.java
  28. 2 0
      netflix-service/src/main/java/com/cyksj/service/pay/AliPayCommonService.java
  29. 35 0
      netflix-service/src/main/java/com/cyksj/service/pay/impl/AliPayCommonServiceImpl.java
  30. 1 1
      netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationFrontServiceImpl.java
  31. 17 0
      netflix-service/src/main/java/com/cyksj/service/spotify/SpotifyUserUpgradeOrderService.java
  32. 143 0
      netflix-service/src/main/java/com/cyksj/service/spotify/impl/SpotifyUserUpgradeOrderServiceImpl.java
  33. 3 10
      netflix-web/src/main/java/com/cyksj/web/controller/group/GroupRelationController.java
  34. 9 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/WxCorpController.java
  35. 1 2
      netflix-web/src/main/java/com/cyksj/web/controller/manage/shop/ShopConfigController.java
  36. 98 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/spotify/SpotifyUpgradeController.java
  37. 211 0
      netflix-web/src/main/java/com/cyksj/web/controller/spotify/SpotifyController.java

+ 10 - 0
netflix-common/src/main/java/com/cyksj/common/constant/Constant.java

@@ -460,4 +460,14 @@ public interface Constant {
 	 * GPT PLUS
 	 */
 	Long GPT_PLUS_GID = 18L;
+
+	/**
+	 * spotify升级 配置key
+	 */
+	String SPOTIFY_UPGRADE_PRICE_KEY = "spotify_upgrade_price_key";
+
+	/**
+	 * 声破天平台id
+	 */
+	Long SPOTIFY_GOODS_ID = 4l;
 }

+ 3 - 0
netflix-dao/src/main/java/com/cyksj/mapper/GroupsRelationMapper.java

@@ -10,6 +10,7 @@ import com.cyksj.model.manage.views.GroupsRelationView;
 import com.cyksj.model.views.GroupsRelationUserView;
 import com.cyksj.model.views.RenewalView;
 import com.cyksj.model.views.UserRecommendGoodsFrontView;
+import com.cyksj.model.views.UserTicketView;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Update;
 
@@ -80,4 +81,6 @@ public interface GroupsRelationMapper extends BaseMapper<GroupsRelation> {
 	List<GroupsRelation> selectExtraRelation(@Param("userId") Long userId, @Param("skuId") Long skuId, @Param("relationId") Long relationId);
 
 	void incrExpiryTime(@Param("relationId") Long relationId, @Param("userId") Long userId);
+
+	List<UserTicketView> selectUserTickets(@Param("userIds") List<Long> userIds, @Param("goodsId") Long goodsId, @Param("skuId") Long skuId);
 }

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/SpotifyUserSelfServiceRecordMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.SpotifyUserSelfServiceRecord;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: SpotifyUserSelfServiceRecordMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/12/3 12:07
+ */
+public interface SpotifyUserSelfServiceRecordMapper extends BaseMapper<SpotifyUserSelfServiceRecord> {
+}

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/SpotifyUserUpgradeOrderMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.SpotifyUserUpgradeOrder;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: SpotifyUserUpgradeOrderMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/12/3 15:42
+ */
+public interface SpotifyUserUpgradeOrderMapper extends BaseMapper<SpotifyUserUpgradeOrder> {
+}

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/SpotifyUserUpgradeSubmitRecordMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.SpotifyUserUpgradeSubmitRecord;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: SpotifyUserUpgradeSubmitRecordMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/12/3 16:43
+ */
+public interface SpotifyUserUpgradeSubmitRecordMapper extends BaseMapper<SpotifyUserUpgradeSubmitRecord> {
+}

+ 38 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/SpotifyOrderInfoDto.java

@@ -0,0 +1,38 @@
+package com.cyksj.model.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: SpotifyOrderInfoDto
+ * 创建者: JavaZou
+ * 创建时间:2024/12/4 17:19
+ */
+@Getter
+@Setter
+public class SpotifyOrderInfoDto {
+	private Long relationId;
+
+	private String status;
+
+	private String account;
+
+	private String password;
+
+	private String email;
+
+	@Getter
+	public enum Status{
+		noPayment("未支付"),
+		notSubmitted("未提交"),
+		waiting("待处理"),
+		fail("失败"),
+		success("成功");
+		String msg;
+
+		Status(String msg) {
+			this.msg = msg;
+		}
+	}
+}

+ 16 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/SpotifyUserSelfServiceRecord.java

@@ -0,0 +1,16 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: SpotifyUserSelfServiceRecord
+ * 创建者: JavaZou
+ * 创建时间:2024/12/3 12:06
+ */
+@Getter
+@Setter
+public class SpotifyUserSelfServiceRecord extends BaseEntity{
+	private Long userId;
+}

+ 81 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/SpotifyUserUpgradeOrder.java

@@ -0,0 +1,81 @@
+package com.cyksj.model.entity;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: SpotifyUserUpgradeOrder
+ * 创建者: JavaZou
+ * 创建时间:2024/12/3 13:41
+ */
+@Getter
+@Setter
+public class SpotifyUserUpgradeOrder extends BaseEntity{
+	private Long userId;
+
+	private Long goodsId;
+
+	private Long skuId;
+
+	private Long relationId;
+
+	private String orderNo;
+
+	/**
+	 * 关联订单号
+	 */
+	private String relateOrderNo;
+
+	private String transactionId;
+
+	private String shopId;
+
+	private BigDecimal money;
+
+	private Status status;
+
+	private Date payTime;
+
+	private Type type;
+
+	public enum Status {
+		/**
+		 * 订单状态
+		 */
+		close("已关闭"),
+		noPayment("待付款"),
+		hasPayment("已付款"),
+		refund("已退款"),
+		;
+
+		private String desc;
+
+		Status(String desc) {
+			this.desc = desc;
+		}
+
+		public String getDesc() {
+			return desc;
+		}
+	}
+
+	@Getter
+	@AllArgsConstructor
+	public enum Type{
+		WeChat("wechat","微信"),
+		ALI_PAY("zfb","支付宝"),
+		;
+		String type;
+		String desc;
+
+		public static Type getType(String type) {
+			return Arrays.stream(SpotifyUserUpgradeOrder.Type.values()).filter(tp -> tp.getType().equals(type)).findFirst().orElse(ALI_PAY);
+		}
+	}
+}

+ 40 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/SpotifyUserUpgradeSubmitRecord.java

@@ -0,0 +1,40 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: SpotifyUserUpgradeSubmitRecord
+ * 创建者: JavaZou
+ * 创建时间:2024/12/3 16:41
+ */
+@Getter
+@Setter
+public class SpotifyUserUpgradeSubmitRecord extends BaseEntity{
+	private Long userId;
+
+	private Long orderId;
+
+	private Long relationId;
+
+	private String account;
+
+	private String password;
+
+	private String email;
+
+	private Status status;
+
+	@Getter
+	public enum Status{
+		waiting("待处理"),
+		fail("失败"),
+		success("成功");
+		String msg;
+
+		Status(String msg) {
+			this.msg = msg;
+		}
+	}
+}

+ 7 - 1
netflix-dao/src/main/java/com/cyksj/model/entity/ZfbShopOrderDayLimit.java

@@ -1,5 +1,6 @@
 package com.cyksj.model.entity;
 
+import com.cyksj.model.BaseEntity;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -30,7 +31,12 @@ public class ZfbShopOrderDayLimit extends BaseEntity {
 	/**
 	 * 每小时随机单数 (小时重置)
 	 */
-	private Integer hourRandOrders;
+	private Integer hourRandOrdersSt;
+
+	/**
+	 * 每小时随机单数 (小时重置)
+	 */
+	private Integer hourRandOrdersEnd;
 
 	/**
 	 * 每小时限制单数

+ 3 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/views/CorpWxOrderDonView.java

@@ -93,4 +93,7 @@ public class CorpWxOrderDonView {
 
 	@DbField("u.nickname")
 	private String nickname;
+
+	@DbField("sku.num")
+	private Integer skuNum;
 }

+ 26 - 0
netflix-dao/src/main/java/com/cyksj/model/request/SpotifyUpgradeInfoReq.java

@@ -0,0 +1,26 @@
+package com.cyksj.model.request;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: SpotifyUpgradeInfoReq
+ * 创建者: JavaZou
+ * 创建时间:2024/12/3 16:35
+ */
+@Getter
+@Setter
+public class SpotifyUpgradeInfoReq {
+	private Long orderId;
+
+	private Long relationId;
+
+	private Long userId;
+
+	private String account;
+
+	private String password;
+
+	private String email;
+}

+ 18 - 0
netflix-dao/src/main/java/com/cyksj/model/request/SpotifyUpgradeOrderReq.java

@@ -0,0 +1,18 @@
+package com.cyksj.model.request;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: SpotifyUpgradeOrderReq
+ * 创建者: JavaZou
+ * 创建时间:2024/12/3 15:34
+ */
+@Getter
+@Setter
+public class SpotifyUpgradeOrderReq {
+	private Long relationId;
+
+	private Long userId;
+}

+ 5 - 1
netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonSkuFrontView.java

@@ -1,5 +1,6 @@
 package com.cyksj.model.views;
 
+import com.ejlchina.searcher.bean.DbField;
 import com.ejlchina.searcher.bean.DbIgnore;
 import com.ejlchina.searcher.bean.SearchBean;
 import com.fasterxml.jackson.annotation.JsonInclude;
@@ -17,7 +18,7 @@ import java.util.List;
  */
 @Getter
 @Setter
-@SearchBean(tables = "goods_don_sku")
+@SearchBean(tables = "goods_don_sku sku")
 @JsonInclude(JsonInclude.Include.NON_NULL)
 public class GoodsDonSkuFrontView {
 
@@ -130,6 +131,9 @@ public class GoodsDonSkuFrontView {
 	 */
 	private Integer sorted;
 
+	@DbField("sku.num")
+	private Integer skuNum;
+
 	/**
 	 * 限制次数
 	 */

+ 1 - 2
netflix-dao/src/main/java/com/cyksj/model/views/RenewalView.java

@@ -44,9 +44,8 @@ public class RenewalView {
     @DbField("sku.days")
     private Integer days;
 
-    @JsonIgnore
     @DbField("sku.num")
-    private Long skuNum;
+    private Integer skuNum;
 
     /**
      * 是否是多人规格

+ 48 - 0
netflix-dao/src/main/java/com/cyksj/model/views/SpotifyUserUpgradeOrderView.java

@@ -0,0 +1,48 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.SpotifyUserUpgradeOrder;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: SpotifyUserUpgradeOrderView
+ * 创建者: JavaZou
+ * 创建时间:2024/12/3 17:12
+ */
+@Getter
+@Setter
+@SearchBean(tables = "spotify_user_upgrade_order so left join user u on u.id = so.user_id")
+public class SpotifyUserUpgradeOrderView {
+	@DbField("so.id")
+	private Long id;
+
+	@DbField("so.user_id")
+	private Long userId;
+
+	@DbField("u.nickname")
+	private String nickname;
+
+	@DbField("so.order_no")
+	private String orderNo;
+
+	@DbField("so.relate_order_no")
+	private String relateOrderNo;
+
+	@DbField("so.money")
+	private BigDecimal money;
+
+	@DbField("so.type")
+	private SpotifyUserUpgradeOrder.Type type;
+
+	@DbField("so.status")
+	private SpotifyUserUpgradeOrder.Status status;
+
+	@DbField("so.created_time")
+	private Date createdTime;
+}

+ 54 - 0
netflix-dao/src/main/java/com/cyksj/model/views/SpotifyUserUpgradeSubmitRecordView.java

@@ -0,0 +1,54 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.SpotifyUserUpgradeSubmitRecord;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: SpotifyUserUpgradeSubmitRecordView
+ * 创建者: JavaZou
+ * 创建时间:2024/12/3 17:04
+ */
+@Getter
+@Setter
+@SearchBean(tables = "spotify_user_upgrade_submit_record sr inner join spotify_user_upgrade_order so on so.id = sr.order_id")
+public class SpotifyUserUpgradeSubmitRecordView {
+
+	@DbField("sr.id")
+	private Long id;
+
+	@DbField("sr.user_id")
+	private Long userId;
+
+	@DbField("sr.order_id")
+	private Long orderId;
+
+	@DbField("so.order_no")
+	private String orderNo;
+
+	@DbField("sr.relation_id")
+	private Long relationId;
+
+	@DbField("sr.account")
+	private String account;
+
+	@DbField("sr.password")
+	private String password;
+
+	@DbField("sr.email")
+	private String email;
+
+	@DbField("sr.status")
+	private SpotifyUserUpgradeSubmitRecord.Status status;
+
+	@DbField("sr.created_time")
+	private Date createdTime;
+
+	@DbField("sr.update_time")
+	private Date updateTime;
+}

+ 3 - 0
netflix-dao/src/main/java/com/cyksj/model/views/UserTicketView.java

@@ -37,6 +37,9 @@ public class UserTicketView {
 	@DbField("gdk.spec_val")
 	private String specVal;
 
+	@DbField("gdk.num")
+	private Integer skuNum;
+
 	@DbField("gr.expiry_time")
 	private Date expiryTime;
 

+ 6 - 3
netflix-dao/src/main/java/com/cyksj/model/views/YHLXUserDetailView.java

@@ -1,6 +1,5 @@
 package com.cyksj.model.views;
 
-import com.baomidou.mybatisplus.annotation.TableField;
 import com.cyksj.model.entity.Address;
 import com.cyksj.model.entity.User;
 import com.ejlchina.searcher.bean.DbField;
@@ -52,10 +51,14 @@ public class YHLXUserDetailView {
 	private Boolean isBind = false;
 
 	@DbIgnore
-	@TableField(exist = false)
 	private Address address;
 
 	@DbIgnore
-	@TableField(exist = false)
 	private List<User> userBindInfos;
+
+	/**
+	 * 是否开启spotify自动服务
+	 */
+	@DbIgnore
+	private Boolean isSpotifySelfService;
 }

+ 18 - 0
netflix-dao/src/main/resources/mapper/GroupRelationMapper.xml

@@ -393,4 +393,22 @@
             and gt.sku_id = #{skuId}
             and not exists (select 1 from order_don o where o.user_id = gr.user_id and o.relation_id = gr.id and o.status not in ('close','noPayment','refund'))
     </select>
+
+    <select id="selectUserTickets" resultType="com.cyksj.model.views.UserTicketView">
+        select gr.id as relation_id,gr.user_id,g.id as goods_id,gt.sku_id,g.title,gdk.spec_val,gr.expiry_time,gdk.is_mirror,gdk.gpt_limit_num as gptUserLimitNum,gdk.gpt_limit_time as gptUserLimitTime from groups_relation gr left join groups_trips gt on gt.id = gr.groups_id
+        left join goods_don_sku gdk on gdk.id = gt.sku_id left join goods_don g on g.id = gdk.goods_id
+        where gr.user_id in
+        <foreach collection="userIds" item="item" open="(" separator="," close=")">
+            #{item}
+        </foreach>
+        and gr.status in ('validity','outside')
+        and gr.cmt != 2
+        and (gr.expiry_time is null or gr.expiry_time > now() or (gdk.is_mirror and gr.expiry_time > DATE_ADD(now(),interval -7 day)))
+        <if test="goodsId != null">
+            and g.id = #{goodsId}
+        </if>
+        <if test="skuId != null">
+            and gt.sku_id = #{skuId}
+        </if>
+    </select>
 </mapper>

+ 2 - 0
netflix-service/src/main/java/com/cyksj/config/zfb/BaseZfbConfig.java

@@ -54,6 +54,8 @@ public class BaseZfbConfig {
 
 	public static String userMirrorOpenShopNotifyUrl = "applets/mirror/shop/prepay/zfb/notify";
 
+	public static String spotifyUpgradeNotifyUrl = "applets/spotify/prepay/zfb/upgrade/notify";
+
 	/**
 	 * qr_pay_mode PC扫码支付的方式。 跳转模式
 	 */

+ 2 - 0
netflix-service/src/main/java/com/cyksj/service/corp/CorpUserService.java

@@ -21,4 +21,6 @@ public interface CorpUserService {
 	void bindOtherUsersByOrderNo(CorpCommonReq corpCommonReq) throws Exception;
 
 	void markCorpUser(CorpCommonReq corpCommonReq) throws Exception;
+
+	void spotifySelfService(Long orderId);
 }

+ 28 - 0
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpUserServiceImpl.java

@@ -7,6 +7,7 @@ import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.config.corp.WeChatCorpFactory;
 import com.cyksj.mapper.AddressMapper;
 import com.cyksj.mapper.OrderDonMapper;
+import com.cyksj.mapper.SpotifyUserSelfServiceRecordMapper;
 import com.cyksj.mapper.UserMapper;
 import com.cyksj.mapper.corp.CorpUserAuthMapper;
 import com.cyksj.mapper.corp.CorpUserMapper;
@@ -23,6 +24,7 @@ import com.ejlchina.searcher.param.Operator;
 import com.ejlchina.searcher.util.MapUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.dao.DuplicateKeyException;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -58,6 +60,8 @@ public class CorpUserServiceImpl implements CorpUserService {
 
 	private final UserBindDetailMapper userBindDetailMapper;
 
+	private final SpotifyUserSelfServiceRecordMapper spotifyUserSelfServiceRecordMapper;
+
 	@Override
 	public YHLXUserDetailView getUserDetailView(String externalUserid, String corpId) throws Exception {
 		CorpUser corpUser = getExternalUserId(corpId, externalUserid);
@@ -108,6 +112,9 @@ public class CorpUserServiceImpl implements CorpUserService {
 		if (userIdList.size() == 3) {
 			view.setIsBind(true);
 		}
+		Integer count = spotifyUserSelfServiceRecordMapper.selectCount(Wrappers.lambdaQuery(SpotifyUserSelfServiceRecord.class)
+				.in(SpotifyUserSelfServiceRecord::getUserId, userIdList));
+		view.setIsSpotifySelfService(count > 0);
 		return view;
 	}
 
@@ -220,6 +227,27 @@ public class CorpUserServiceImpl implements CorpUserService {
 		corpUserMapper.updateById(corpUser);
 	}
 
+	@Override
+	public void spotifySelfService(Long orderId) {
+		OrderDon orderDon = orderDonMapper.selectById(orderId);
+		if (orderDon == null) {
+			return;
+		}
+		Long userId = orderDon.getUserId();
+		Integer selectCount = spotifyUserSelfServiceRecordMapper.selectCount(Wrappers.lambdaQuery(SpotifyUserSelfServiceRecord.class)
+				.eq(SpotifyUserSelfServiceRecord::getUserId, userId));
+		if (selectCount > 0) {
+			return;
+		}
+		try {
+			SpotifyUserSelfServiceRecord spotifyUserSelfServiceRecord = new SpotifyUserSelfServiceRecord();
+			spotifyUserSelfServiceRecord.setUserId(userId);
+			spotifyUserSelfServiceRecordMapper.insert(spotifyUserSelfServiceRecord);
+		} catch (DuplicateKeyException e) {
+
+		}
+	}
+
 	public CorpUser getExternalUserId(String corpId, String externalUserid) throws Exception {
 		WxCorpApp wxCorpApp = WeChatCorpFactory.getCorpConfigStrategy(corpId);
 

+ 4 - 0
netflix-service/src/main/java/com/cyksj/service/order/OrderDonService.java

@@ -107,4 +107,8 @@ public interface OrderDonService extends IService<OrderDon> {
 	OrderDon userBenefitsSubmit(OrderPayRequest orderPayRequest) throws Exception;
 
     UserPayEquipmentAvailableBenefits getComboOptionalTicketRecord(long userId, Long orderId);
+
+    AliPayParams aliPaySpotifyUpgrade(AlipayOrderDonReq alipayOrderDonReq, String productCode, String qrPayMode) throws Exception;
+
+    void aliPaySpotifyUpgradeNotify(Map<String, String> params) throws Exception;
 }

+ 2 - 0
netflix-service/src/main/java/com/cyksj/service/order/OrderRefundService.java

@@ -30,4 +30,6 @@ public interface OrderRefundService {
 	String refundWholesaleOrder(GoodsWholesaleOrderDon orderDon) throws Exception;
 
 	String refundUserMirrorShopFee(UserMirrorShopFeeOrderDon orderDon) throws Exception;
+
+	void refundSpotifyUpgrade(Long orderId) throws Exception;
 }

+ 45 - 0
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java

@@ -360,6 +360,8 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 
 	private final ClaudeUserMapper claudeUserMapper;
 
+	private final SpotifyUserUpgradeOrderMapper spotifyUserUpgradeOrderMapper;
+
 	private final List<String> noChekGoodsTemp = List.of("Apple One", "Youtube", "Spotify");
 
 	@Transactional(rollbackFor = Throwable.class)
@@ -4289,6 +4291,49 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		return userPayEquipmentAvailableBenefits;
 	}
 
+	@Override
+	public AliPayParams aliPaySpotifyUpgrade(AlipayOrderDonReq re, String productCode, String qrPayMode) throws Exception {
+		return aliPayCommonService.aliPaySpotifyUpgrade(re, productCode, qrPayMode);
+	}
+
+	@Override
+	public void aliPaySpotifyUpgradeNotify(Map<String, String> params) throws Exception {
+		//调用SDK验证签名
+		String body = Codec.DoBase64.custom().setData(params.get("body")).decodeAsText();
+		OrderAttach orderAttach = Jsons.parseObject(body, OrderAttach.class);
+		Long oderId = orderAttach.getO();
+		SpotifyUserUpgradeOrder orderDon = spotifyUserUpgradeOrderMapper.selectById(oderId);
+		if (null == orderDon) {
+			throw BusinessRuntimeException.getInstance("订单不存在.");
+		}
+		String appId = params.get("app_id");
+		boolean signVerified = AlipaySignature.rsaCheckV1(params, shopConfigMapper.getByAppId(appId).getPublicKey(), BaseZfbConfig.charset, BaseZfbConfig.signType);
+		if (!signVerified) {
+			log.error("支付宝回调校验签名错误,自定义入参:{}", params.get("body"));
+			throw BusinessRuntimeException.getInstance("支付宝回调校验签名错误");
+		}
+		String transactionId = params.get("trade_no");
+		String payTimeStr = params.get("gmt_payment");
+		//买家支付宝账号
+		String buyerId = Optional.ofNullable(params.get("buyer_id")).orElse(params.get("buyer_open_id"));
+		log.info("支付宝回调信息:{}", Jsons.toJson(params));
+		if (!orderDon.getStatus().equals(SpotifyUserUpgradeOrder.Status.noPayment) && !orderDon.getStatus().equals(SpotifyUserUpgradeOrder.Status.close)) {
+			log.info("支付宝已回调,重复修改状态 id:{}", orderDon.getId());
+			return;
+		}
+		Date payTime = DateTime.now();
+		if (StringUtils.isNotBlank(payTimeStr)) {
+			payTime = DateUtil.parse(payTimeStr, "yyyy-MM-dd HH:mm:ss");
+		}
+		// 更改订单状态
+		orderDon.setTransactionId(transactionId);
+		orderDon.setPayTime(payTime);
+		orderDon.setShopId(appId);
+		orderDon.setStatus(SpotifyUserUpgradeOrder.Status.hasPayment);
+		orderDon.setType(SpotifyUserUpgradeOrder.Type.ALI_PAY);
+		spotifyUserUpgradeOrderMapper.updateById(orderDon);
+	}
+
 	private void checkUserBenefitsStatus(UserBenefits userBenefits, List<Long> userIdList) {
 		UserBenefits.Type type = userBenefits.getType();
 		int fhCount = 0;

+ 46 - 0
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderRefundServiceImpl.java

@@ -63,6 +63,8 @@ public class OrderRefundServiceImpl implements OrderRefundService {
 
 	private final RefundUpgradeOrderDonMapper refundUpgradeOrderDonMapper;
 
+	private final SpotifyUserUpgradeOrderMapper spotifyUserUpgradeOrderMapper;
+
 	@Override
 	public String centerRefund(OrderRefundReq refundReq, OrderDon orderDon) throws Exception {
 		OrderDon.Type type = orderDon.getType();
@@ -432,6 +434,50 @@ public class OrderRefundServiceImpl implements OrderRefundService {
 		return outRefundNo;
 	}
 
+	@Override
+	public void refundSpotifyUpgrade(Long orderId) throws Exception {
+		SpotifyUserUpgradeOrder order = spotifyUserUpgradeOrderMapper.selectById(orderId);
+		if (order == null) {
+			throw BusinessRuntimeException.getInstance("订单不存在");
+		}
+		if (order.getStatus() != SpotifyUserUpgradeOrder.Status.hasPayment) {
+			throw BusinessRuntimeException.getInstance("订单状态异常");
+		}
+		BigDecimal money = order.getMoney();
+		if (money.compareTo(BigDecimal.ZERO) <=0){
+			return;
+		}
+		AlipayTradeRefundResponse response;
+		//支付宝退款
+		AlipayClient alipayClient = AliPayClientFactory.getAlipayClient(Optional.ofNullable(order.getShopId()).orElse(ShopConfig.ZFB_DEFAULT_APP_ID));
+		AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
+		AlipayTradeRefundModel model = new AlipayTradeRefundModel();
+		//支付宝交易号
+		model.setTradeNo(order.getTransactionId());
+		model.setRefundAmount(money.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_EVEN).toString());
+		model.setQueryOptions(List.of("gmt_refund_pay"));
+		long time = System.currentTimeMillis();
+		//退款订单号
+		String outRefundNo = Codec.DoDigest.custom()
+				.setAlgorithm(Codec.DoDigest.Algorithm.MD5)
+				.setStringData(time + String.valueOf(order.getId()))
+				.toHexString();
+		log.info("spotify升级订单oid:{}退款订单号:{}", orderId, outRefundNo);
+		//退款请求号
+		model.setOutRequestNo(outRefundNo);
+		request.setBizModel(model);
+		String shopId = order.getShopId();
+		ShopConfig shopConfig = shopConfigMapper.selectOne(Wrappers.lambdaQuery(ShopConfig.class).eq(ShopConfig::getAppId, order.getShopId()));
+		if (shopId != null && shopConfig != null && shopConfig.getIsCert()) {
+			response = alipayClient.certificateExecute(request);
+		} else {
+			response = alipayClient.execute(request);
+		}
+		if (!response.isSuccess()) throw BusinessRuntimeException.getInstance("退款失败,e:{0}", response.getSubMsg());
+		order.setStatus(SpotifyUserUpgradeOrder.Status.refund);
+		spotifyUserUpgradeOrderMapper.updateById(order);
+	}
+
 	private String zfbRefundWholesaleOrder(GoodsWholesaleOrderDon orderDon) throws Exception {
 		BigDecimal money = orderDon.getRefundMoney();
 		if (money.compareTo(BigDecimal.ZERO) <=0){

+ 2 - 0
netflix-service/src/main/java/com/cyksj/service/pay/AliPayCommonService.java

@@ -28,4 +28,6 @@ public interface AliPayCommonService {
 	AliPayParams aliPayUnifiedWholesaleDeposit(AlipayOrderDonReq re, String productCode, String qrPayMode) throws Exception;
 
 	AliPayParams openShopAliPay(AlipayOrderDonReq re, String productCode, String qrPayMode) throws Exception;
+
+	AliPayParams aliPaySpotifyUpgrade(AlipayOrderDonReq re, String productCode, String qrPayMode) throws Exception;
 }

+ 35 - 0
netflix-service/src/main/java/com/cyksj/service/pay/impl/AliPayCommonServiceImpl.java

@@ -80,6 +80,8 @@ public class AliPayCommonServiceImpl implements AliPayCommonService {
 
 	private final ZfbShopOrderDayLimitMapper zfbShopOrderDayLimitMapper;
 
+	private final SpotifyUserUpgradeOrderMapper spotifyUserUpgradeOrderMapper;
+
 	private static final Sequence SEQUENCE = new Sequence(0);
 
 	@Override
@@ -471,4 +473,37 @@ public class AliPayCommonServiceImpl implements AliPayCommonService {
 				notifyUrl,
 				returnUrl);
 	}
+
+	@Override
+	public AliPayParams aliPaySpotifyUpgrade(AlipayOrderDonReq re, String productCode, String payMode) throws Exception {
+		Long orderId = re.getOrderId();
+		String returnUrl = re.getReturnUrl();
+		SpotifyUserUpgradeOrder orderDon = spotifyUserUpgradeOrderMapper.selectById(orderId);
+		//获取支付宝默认商户
+		String appId = sysConfigService.getDefaultShopConfigByType("zfb");
+		if (SpotifyUserUpgradeOrder.Type.ALI_PAY != orderDon.getType()) {
+			orderDon.setType(SpotifyUserUpgradeOrder.Type.ALI_PAY);
+		}
+		orderDon.setShopId(appId);
+		spotifyUserUpgradeOrderMapper.updateById(orderDon);
+		String subject = "Spotify家庭组升级";
+		//回调地址
+		String host = envCommonService.getNotifyHost();
+		String notifyUrl = String.format("%s%s", host, BaseZfbConfig.spotifyUpgradeNotifyUrl);
+		//是否在微信内支付 微信内支付宝支付后 支付宝回调页面不跳转
+		if (StrUtil.isEmpty(returnUrl)) {
+			//默认跳转页
+			returnUrl = String.format("%s%s", envCommonService.getDomain(), BaseZfbConfig.DEFAULT_URL);
+		}
+		return builderPayParams(orderDon.getId(),
+				orderDon.getOrderNo(),
+				orderDon.getShopId(),
+				orderDon.getMoney(),
+				orderDon.getUpdateTime(),
+				subject,
+				productCode,
+				payMode,
+				notifyUrl,
+				returnUrl);
+	}
 }

+ 1 - 1
netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationFrontServiceImpl.java

@@ -256,7 +256,7 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 			if (ticket.getMonths() != null && ticket.getMonths() >= 300) {
 				ticket.setExpiryTime(null);
 			}
-			if (ticket.getExpiryTime() != null && ticket.getGoodsType() == 1 && ticket.getSecondType() == 2) {
+			if (ticket.getExpiryTime() != null && ticket.getGoodsType() == 1) {
 				String remainDays = DateUtil.formatBetween(now, ticket.getExpiryTime(), BetweenFormater.Level.DAY);
 				if ("0天".equals(remainDays)) {
 					remainDays = "小于1天";

+ 17 - 0
netflix-service/src/main/java/com/cyksj/service/spotify/SpotifyUserUpgradeOrderService.java

@@ -0,0 +1,17 @@
+package com.cyksj.service.spotify;
+
+import com.cyksj.model.entity.SpotifyUserUpgradeOrder;
+import com.cyksj.model.request.SpotifyUpgradeInfoReq;
+import com.cyksj.model.request.SpotifyUpgradeOrderReq;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: SpotifyUserUpgradeOrderService
+ * 创建者: JavaZou
+ * 创建时间:2024/12/3 15:40
+ */
+public interface SpotifyUserUpgradeOrderService {
+	SpotifyUserUpgradeOrder upgradeSubmit(SpotifyUpgradeOrderReq spotifyUpgradeOrderReq);
+
+	void submitUpgradeInfo(SpotifyUpgradeInfoReq spotifyUpgradeInfoReq);
+}

+ 143 - 0
netflix-service/src/main/java/com/cyksj/service/spotify/impl/SpotifyUserUpgradeOrderServiceImpl.java

@@ -0,0 +1,143 @@
+package com.cyksj.service.spotify.impl;
+
+import cn.hutool.core.lang.Validator;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.Assert;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.constant.Constant;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.snowflake.Sequence;
+import com.cyksj.mapper.*;
+import com.cyksj.mapper.sys.SysConfigMapper;
+import com.cyksj.model.entity.*;
+import com.cyksj.model.request.SpotifyUpgradeInfoReq;
+import com.cyksj.model.request.SpotifyUpgradeOrderReq;
+import com.cyksj.service.spotify.SpotifyUserUpgradeOrderService;
+import com.cyksj.service.user.UserBindRelationService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.dao.DuplicateKeyException;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: SpotifyUserUpgradeOrderServiceImpl
+ * 创建者: JavaZou
+ * 创建时间:2024/12/3 15:40
+ */
+@Service
+@RequiredArgsConstructor
+@Slf4j
+public class SpotifyUserUpgradeOrderServiceImpl implements SpotifyUserUpgradeOrderService {
+	private final SpotifyUserUpgradeOrderMapper spotifyUserUpgradeOrderMapper;
+
+	private final GroupsRelationMapper relationMapper;
+
+	private final UserBindRelationService userBindRelationService;
+
+	private final GroupsMapper groupsMapper;
+
+	private final GoodsDonSkuMapper skuMapper;
+
+	private final static Sequence SEQUENCE = new Sequence(0);
+
+	private final SysConfigMapper sysConfigMapper;
+
+	private final SpotifyUserUpgradeSubmitRecordMapper spotifyUserUpgradeSubmitRecordMapper;
+
+	private final OrderDonMapper orderDonMapper;
+
+	@Override
+	public SpotifyUserUpgradeOrder upgradeSubmit(SpotifyUpgradeOrderReq spotifyUpgradeOrderReq) {
+		Long userId = spotifyUpgradeOrderReq.getUserId();
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		Long relationId = spotifyUpgradeOrderReq.getRelationId();
+
+		GroupsRelation relation = relationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class).eq(GroupsRelation::getId, relationId).in(GroupsRelation::getUserId, userIdList).eq(GroupsRelation::getStatus, GroupsRelation.Status.validity));
+		if (relation == null) {
+			throw BusinessRuntimeException.getInstance("车票已过期");
+		}
+		GroupsTrips groupsTrips = groupsMapper.selectById(relation.getGroupsId());
+		GoodsDonSku sku = skuMapper.selectById(groupsTrips.getSkuId());
+		if (sku.getGoodsId() != Constant.SPOTIFY_GOODS_ID) {
+			throw BusinessRuntimeException.getInstance("暂只支持spotify车票");
+		}
+		SpotifyUserUpgradeOrder order = spotifyUserUpgradeOrderMapper.selectOne(Wrappers.lambdaQuery(SpotifyUserUpgradeOrder.class).eq(SpotifyUserUpgradeOrder::getRelationId, relationId).in(SpotifyUserUpgradeOrder::getUserId, userIdList).eq(SpotifyUserUpgradeOrder::getStatus, SpotifyUserUpgradeOrder.Status.noPayment).last("limit 1"));
+		if (order == null) {
+			order = new SpotifyUserUpgradeOrder();
+		}
+		order.setUserId(userId);
+		order.setGoodsId(sku.getGoodsId());
+		order.setSkuId(sku.getId());
+		order.setOrderNo(SEQUENCE.nextId().toString());
+		order.setStatus(SpotifyUserUpgradeOrder.Status.noPayment);
+		order.setRelationId(relationId);
+
+		OrderDon relateOrder = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class)
+				.in(OrderDon::getUserId, userIdList)
+				.eq(OrderDon::getRelationId, relationId)
+				.notIn(OrderDon::getStatus, Constant.noOrderAllStatus)
+				.orderByDesc(OrderDon::getId)
+				.last("limit 1"));
+		if (relateOrder != null) {
+			order.setRelateOrderNo(relateOrder.getOrderNo());
+		}
+		SysConfig sysConfig = sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, Constant.SPOTIFY_UPGRADE_PRICE_KEY).last("limit 1"));
+		order.setMoney(BigDecimal.valueOf(Long.parseLong(sysConfig.getSysValue())));
+		if (order.getId() == null) spotifyUserUpgradeOrderMapper.insert(order);
+		else spotifyUserUpgradeOrderMapper.updateById(order);
+		return order;
+	}
+
+	@Override
+	public void submitUpgradeInfo(SpotifyUpgradeInfoReq spotifyUpgradeInfoReq) {
+		Long relationId = spotifyUpgradeInfoReq.getRelationId();
+		Assert.notNull(relationId, "参数错误");
+		String account = spotifyUpgradeInfoReq.getAccount();
+		if (StrUtil.isEmpty(account) || account.length() > 64) {
+			throw BusinessRuntimeException.getInstance("请输入正确的账号信息");
+		}
+		String password = spotifyUpgradeInfoReq.getPassword();
+		if (StrUtil.isEmpty(password) || password.length() > 64) {
+			throw BusinessRuntimeException.getInstance("请输入正确的账号信息");
+		}
+		String email = spotifyUpgradeInfoReq.getEmail();
+		if (!Validator.isEmail(email)) {
+			throw BusinessRuntimeException.getInstance("请输入正确的邮箱");
+		}
+		Long userId = spotifyUpgradeInfoReq.getUserId();
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		SpotifyUserUpgradeOrder order = spotifyUserUpgradeOrderMapper.selectOne(Wrappers.lambdaQuery(SpotifyUserUpgradeOrder.class)
+				.eq(SpotifyUserUpgradeOrder::getRelationId, relationId)
+				.in(SpotifyUserUpgradeOrder::getUserId, userIdList)
+				.eq(SpotifyUserUpgradeOrder::getStatus, SpotifyUserUpgradeOrder.Status.hasPayment));
+		if (order == null) {
+			throw BusinessRuntimeException.getInstance("订单不存在");
+		}
+		Long orderId = order.getId();
+		SpotifyUserUpgradeSubmitRecord upgradeSubmitRecord = Optional.ofNullable(spotifyUserUpgradeSubmitRecordMapper.selectOne(Wrappers.lambdaQuery(SpotifyUserUpgradeSubmitRecord.class)
+				.eq(SpotifyUserUpgradeSubmitRecord::getOrderId, orderId)
+				.last("limit 1"))).orElse(new SpotifyUserUpgradeSubmitRecord());
+		if (upgradeSubmitRecord.getStatus() != null && upgradeSubmitRecord.getStatus() != SpotifyUserUpgradeSubmitRecord.Status.fail) {
+			throw BusinessRuntimeException.getInstance("您已提交记录");
+		}
+		try {
+			upgradeSubmitRecord.setUserId(order.getUserId());
+			upgradeSubmitRecord.setAccount(account);
+			upgradeSubmitRecord.setPassword(password);
+			upgradeSubmitRecord.setEmail(email);
+			upgradeSubmitRecord.setStatus(SpotifyUserUpgradeSubmitRecord.Status.waiting);
+			upgradeSubmitRecord.setOrderId(orderId);
+			upgradeSubmitRecord.setRelationId(order.getRelationId());
+			if (upgradeSubmitRecord.getId() == null) {
+				spotifyUserUpgradeSubmitRecordMapper.insert(upgradeSubmitRecord);
+			} else spotifyUserUpgradeSubmitRecordMapper.updateById(upgradeSubmitRecord);
+		} catch (DuplicateKeyException e) {
+
+		}
+	}
+}

+ 3 - 10
netflix-web/src/main/java/com/cyksj/web/controller/group/GroupRelationController.java

@@ -211,18 +211,11 @@ public class GroupRelationController {
      * 获取全部车票
      */
     @GetMapping("/get")
-    public Result<List<UserTicketView>> getUserTicketView() {
+    public Result<List<UserTicketView>> getUserTicketView(Long goodsId, Long skuId) {
         long userId = StpUserUtil.getLoginIdAsLong();
         List<Long> userIds = userBindRelationService.getRelationUserIdList(userId, null);
-        List<UserTicketView> ticketViews = beanSearcher.searchAll(UserTicketView.class, MapUtils.flatBuilder(request.getParameterMap())
-                .field(UserTicketView::getUserId, userIds).op(Operator.InList)
-                .field(UserTicketView::getStatus, List.of("validity", "outside")).op(Operator.InList)
-                .field(UserTicketView::getExpiryTime, DateTime.now()).op(Operator.GreaterThan)
-                //过滤镜像店铺车票
-                .field(UserTicketView::getCmt, 2).op(Operator.NotEqual)
-                .orderBy(UserTicketView::getRelationId).asc()
-                .build());
-        return GatewayResponse.SUCCESS.newBuilder().toResult(ticketViews);
+        List<UserTicketView> tickets = relationMapper.selectUserTickets(userIds, goodsId, skuId);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(tickets);
     }
 
     /**

+ 9 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/WxCorpController.java

@@ -510,4 +510,13 @@ public class WxCorpController {
 		cmsOrderDonService.unifiedRefund(refundReq);
 		return GatewayResponse.SUCCESS.newBuilder().toResult("退款成功");
 	}
+
+	/**
+	 * 开启spotify用户自助
+	 */
+	@PostMapping("/spotify/self/service/{orderId}")
+	public Result<String> spotifySelfService(@PathVariable Long orderId) {
+		corpUserService.spotifySelfService(orderId);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
 }

+ 1 - 2
netflix-web/src/main/java/com/cyksj/web/controller/manage/shop/ShopConfigController.java

@@ -111,8 +111,7 @@ public class ShopConfigController {
      */
     @PostMapping("/save/zfb/limit")
     public Result<String> saveZfbShopOrderDayLimit(@RequestBody ZfbShopOrderDayLimit zfbShopOrderDayLimit) {
-        Integer hourRandHourOrders = zfbShopOrderDayLimit.getHourRandOrders();
-        zfbShopOrderDayLimit.setHourLimitOrders(RandomUtil.randomInt(hourRandHourOrders) + 1);
+        zfbShopOrderDayLimit.setHourLimitOrders(RandomUtil.randomInt(zfbShopOrderDayLimit.getHourRandOrdersSt(), zfbShopOrderDayLimit.getHourRandOrdersEnd()));
         zfbShopOrderDayLimit.setHourRemainOrders(zfbShopOrderDayLimit.getHourLimitOrders());
         zfbShopOrderDayLimit.setDayRemainOrders(zfbShopOrderDayLimit.getDayLimitOrders());
         zfbShopOrderDayLimitMapper.insert(zfbShopOrderDayLimit);

+ 98 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/spotify/SpotifyUpgradeController.java

@@ -0,0 +1,98 @@
+package com.cyksj.web.controller.manage.spotify;
+
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.GroupsRelationMapper;
+import com.cyksj.mapper.SpotifyUserUpgradeSubmitRecordMapper;
+import com.cyksj.model.entity.SpotifyUserUpgradeSubmitRecord;
+import com.cyksj.model.views.SpotifyUserUpgradeOrderView;
+import com.cyksj.model.views.SpotifyUserUpgradeSubmitRecordView;
+import com.cyksj.service.order.OrderRefundService;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Optional;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: SpotifyUpgradeController
+ * 创建者: JavaZou
+ * 创建时间:2024/12/3 17:01
+ */
+@RestController
+@RequestMapping("/manage/spotify/upgrade")
+@RequiredArgsConstructor
+public class SpotifyUpgradeController {
+
+	private final BeanSearcher beanSearcher;
+
+	private final HttpServletRequest request;
+
+	private final SpotifyUserUpgradeSubmitRecordMapper spotifyUserUpgradeSubmitRecordMapper;
+
+	private final OrderRefundService orderRefundService;
+
+	private final GroupsRelationMapper relationMapper;
+
+	/**
+	 * 提交账号列表
+	 */
+	@GetMapping("/get/account/submit")
+	public Result<SearchResult<SpotifyUserUpgradeSubmitRecordView>> getSubmitAccount() {
+		SearchResult<SpotifyUserUpgradeSubmitRecordView> search = beanSearcher.search(SpotifyUserUpgradeSubmitRecordView.class, MapUtils.flatBuilder(request.getParameterMap()).orderBy(SpotifyUserUpgradeSubmitRecordView::getUpdateTime).desc().build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 设置提交状态
+	 */
+	@PutMapping("/set/account/submit/status")
+	public Result<String> setAccountSubmitStatus(@RequestBody SpotifyUserUpgradeSubmitRecord submitRecord) {
+		Long id = submitRecord.getId();
+		SpotifyUserUpgradeSubmitRecord.Status status = submitRecord.getStatus();
+		SpotifyUserUpgradeSubmitRecord upgradeSubmitRecord = spotifyUserUpgradeSubmitRecordMapper.selectById(id);
+		if (upgradeSubmitRecord.getStatus() != SpotifyUserUpgradeSubmitRecord.Status.waiting) {
+			throw BusinessRuntimeException.getInstance("状态已修改");
+		}
+		upgradeSubmitRecord.setStatus(status);
+		spotifyUserUpgradeSubmitRecordMapper.updateById(upgradeSubmitRecord);
+		//成功后 修改车票时间
+		if (status == SpotifyUserUpgradeSubmitRecord.Status.success) {
+			Optional.ofNullable(relationMapper.selectById(upgradeSubmitRecord.getRelationId())).ifPresent(relation -> {
+				if (relation.getStartTime() == null) {
+					relation.setStartTime(DateTime.now());
+					relation.setExpiryTime(DateUtil.offsetMonth(relation.getStartTime(), 12));
+				} else {
+					relation.setExpiryTime(DateUtil.offsetMonth(DateTime.now(), 12));
+				}
+				relationMapper.updateById(relation);
+			});
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 订单列表
+	 */
+	@GetMapping("/get/orders")
+	public Result<SearchResult<SpotifyUserUpgradeOrderView>> getOrders() {
+		SearchResult<SpotifyUserUpgradeOrderView> search = beanSearcher.search(SpotifyUserUpgradeOrderView.class, MapUtils.flatBuilder(request.getParameterMap()).orderBy(SpotifyUserUpgradeOrderView::getId).desc().build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 订单退款
+	 */
+	@PostMapping("/refund/{orderId}")
+	public Result<String> refund(@PathVariable Long orderId) throws Exception {
+		orderRefundService.refundSpotifyUpgrade(orderId);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+}

+ 211 - 0
netflix-web/src/main/java/com/cyksj/web/controller/spotify/SpotifyController.java

@@ -0,0 +1,211 @@
+package com.cyksj.web.controller.spotify;
+
+import com.cyksj.config.zfb.BaseZfbConfig;
+import com.cyksj.config.zfb.ZfbProductCode;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.model.dto.AliPayParams;
+import com.cyksj.model.dto.SpotifyOrderInfoDto;
+import com.cyksj.model.entity.SpotifyUserSelfServiceRecord;
+import com.cyksj.model.entity.SpotifyUserUpgradeOrder;
+import com.cyksj.model.entity.SpotifyUserUpgradeSubmitRecord;
+import com.cyksj.model.request.AlipayOrderDonReq;
+import com.cyksj.model.request.SpotifyUpgradeInfoReq;
+import com.cyksj.model.request.SpotifyUpgradeOrderReq;
+import com.cyksj.model.response.AliPayTradeStatus;
+import com.cyksj.service.order.OrderDonService;
+import com.cyksj.service.spotify.SpotifyUserUpgradeOrderService;
+import com.cyksj.service.user.UserBindRelationService;
+import com.cyksj.web.util.StpUserUtil;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.param.Operator;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: SpotifyController
+ * 创建者: JavaZou
+ * 创建时间:2024/12/3 12:11
+ */
+@RestController
+@RequestMapping("/applets/spotify")
+@RequiredArgsConstructor
+@Slf4j
+public class SpotifyController {
+	private final SpotifyUserUpgradeOrderService spotifyUserUpgradeOrderService;
+
+	private final OrderDonService orderDonService;
+
+	private final UserBindRelationService userBindRelationService;
+
+	private final BeanSearcher beanSearcher;
+
+	private final HttpServletRequest request;
+
+	/**
+	 * 提交升级订单
+	 */
+	@PostMapping("/upgrade/submit")
+	public Result<SpotifyUserUpgradeOrder> upgradeSubmit(@RequestBody SpotifyUpgradeOrderReq spotifyUpgradeOrderReq) {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		spotifyUpgradeOrderReq.setUserId(userId);
+		SpotifyUserUpgradeOrder order = spotifyUserUpgradeOrderService.upgradeSubmit(spotifyUpgradeOrderReq);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(order);
+	}
+
+	/**
+	 * 支付宝表单支付
+	 * 支付宝调起支付宝表单
+	 * 手机支付
+	 */
+	@PostMapping("/post/pay/zfb")
+	public Result<String> aliPaySpotifyUpgrade(@RequestBody @Validated AlipayOrderDonReq re) throws Exception {
+		AliPayParams aliPayParams = orderDonService.aliPaySpotifyUpgrade(re, ZfbProductCode.MOBILE_WEB.getProductCode(), null);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(aliPayParams.getBody());
+	}
+
+	/**
+	 * 支付宝web支付
+	 */
+	@PostMapping("/get/zfb/orderQrCode")
+	public Result<String> zfbWebQrCode(@RequestBody @Validated AlipayOrderDonReq re) throws Exception {
+		AliPayParams aliPayParams = orderDonService.aliPaySpotifyUpgrade(re, ZfbProductCode.PC_WEB.getProductCode(), BaseZfbConfig.qrPayMode_orderCode);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(aliPayParams.getBody());
+	}
+
+	/**
+	 * 支付宝回调
+	 */
+	@PostMapping("/prepay/zfb/upgrade/notify")
+	public String aliPaySpotifyUpgradeNotify(HttpServletRequest request) throws Exception {
+		////将异步通知中收到的所有参数都存放到map中
+		Map<String, String> params = convertRequestParamsToMap(request);
+		String tradeStatus = params.get("trade_status");
+		String orderNo = params.get("out_trade_no");
+		if (AliPayTradeStatus.TRADE_SUCCESS.getStatus().equals(tradeStatus) || AliPayTradeStatus.TRADE_FINISHED.getStatus().equals(tradeStatus)) {
+			log.info("支付宝商家订单号orderNo:{},status:{}开始回调", orderNo, tradeStatus);
+			orderDonService.aliPaySpotifyUpgradeNotify(params);
+		} else {
+			log.error("支付宝回调 error 状态不符合 成功或完成 status:{} ,orderNo:{}", tradeStatus, orderNo);
+			return "fail";
+		}
+		return "success";
+	}
+
+	/**
+	 * 查询订单状态
+	 */
+	@GetMapping("/get/order/status/{orderId}")
+	public Result<SpotifyUserUpgradeOrder> getOrderStatus(@PathVariable Long orderId) {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		SpotifyUserUpgradeOrder order = beanSearcher.searchFirst(SpotifyUserUpgradeOrder.class, MapUtils.builder()
+				.field(SpotifyUserUpgradeOrder::getId, orderId)
+				.field(SpotifyUserUpgradeOrder::getUserId, userIdList).op(Operator.InList)
+				.build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(order);
+	}
+
+	/**
+	 * 订单列表
+	 */
+	@GetMapping("/get/order")
+	public Result<SearchResult<SpotifyUserUpgradeOrder>> getOrders() {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		SearchResult<SpotifyUserUpgradeOrder> search = beanSearcher.search(SpotifyUserUpgradeOrder.class, MapUtils.flatBuilder(request.getParameterMap())
+				.field(SpotifyUserUpgradeOrder::getUserId, userIdList).op(Operator.InList)
+				.build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 是否开启升级spotify权限
+	 */
+	@GetMapping("/get/upgrade/permit")
+	public Result<Boolean> getUpgradePermit() {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		Number number = beanSearcher.searchCount(SpotifyUserSelfServiceRecord.class, MapUtils.builder().field(SpotifyUserSelfServiceRecord::getUserId, userIdList).op(Operator.InList).build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(number.intValue() > 0);
+	}
+
+	/**
+	 * 提交账号信息
+	 */
+	@PostMapping("/upgrade/submit/info")
+	public Result<String> submitUpgradeInfo(@RequestBody SpotifyUpgradeInfoReq spotifyUpgradeInfoReq) {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		spotifyUpgradeInfoReq.setUserId(userId);
+		spotifyUserUpgradeOrderService.submitUpgradeInfo(spotifyUpgradeInfoReq);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 查看提交账号信息
+	 */
+	@GetMapping("/upgrade/submit/account")
+	public Result<SpotifyOrderInfoDto> getUpgradeSubmitAccount() {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		SpotifyOrderInfoDto spotifyOrderInfoDto = new SpotifyOrderInfoDto();
+		SpotifyUserUpgradeOrder order = beanSearcher.searchFirst(SpotifyUserUpgradeOrder.class, MapUtils.builder()
+				.field(SpotifyUserUpgradeOrder::getUserId, userIdList).op(Operator.InList)
+				.field(SpotifyUserUpgradeOrder::getStatus, SpotifyUserUpgradeOrder.Status.hasPayment.name())
+				.build());
+		if (order == null) {
+			spotifyOrderInfoDto.setStatus(SpotifyOrderInfoDto.Status.noPayment.name());
+		} else {
+			spotifyOrderInfoDto.setRelationId(order.getRelationId());
+			SpotifyUserUpgradeSubmitRecord upgradeSubmitRecord = beanSearcher.searchFirst(SpotifyUserUpgradeSubmitRecord.class, MapUtils.builder()
+					.field(SpotifyUserUpgradeSubmitRecord::getUserId, userIdList).op(Operator.InList)
+					.field(SpotifyUserUpgradeSubmitRecord::getRelationId, order.getRelationId())
+					.orderBy(SpotifyUserUpgradeSubmitRecord::getId).desc().build());
+			if (upgradeSubmitRecord == null) {
+				spotifyOrderInfoDto.setStatus(SpotifyOrderInfoDto.Status.notSubmitted.name());
+			} else {
+				spotifyOrderInfoDto.setAccount(upgradeSubmitRecord.getAccount());
+				spotifyOrderInfoDto.setPassword(upgradeSubmitRecord.getPassword());
+				spotifyOrderInfoDto.setEmail(upgradeSubmitRecord.getEmail());
+				spotifyOrderInfoDto.setStatus(upgradeSubmitRecord.getStatus().name());
+			}
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult(spotifyOrderInfoDto);
+	}
+
+	/**
+	 * 获取支付宝回调参数
+	 */
+	private static Map<String, String> convertRequestParamsToMap(HttpServletRequest request) {
+		Map<String, String> retMap = new HashMap<>();
+		Set<Map.Entry<String, String[]>> entrySet = request.getParameterMap().entrySet();
+		for (Map.Entry<String, String[]> entry : entrySet) {
+			String name = entry.getKey();
+			String[] values = entry.getValue();
+			int valLen = values.length;
+			if (valLen == 1) {
+				retMap.put(name, values[0]);
+			} else if (valLen > 1) {
+				StringBuilder sb = new StringBuilder();
+				for (String val : values) {
+					sb.append(",").append(val);
+				}
+				retMap.put(name, sb.substring(1));
+			} else {
+				retMap.put(name, "");
+			}
+		}
+		return retMap;
+	}
+}