Ver código fonte

广告投放小程序

chenbiao 3 anos atrás
pai
commit
abf48b346d
59 arquivos alterados com 2371 adições e 2 exclusões
  1. 110 0
      netflix-common/src/main/java/com/cyksj/common/util/SpringCtxUtils.java
  2. 11 0
      netflix-dao/src/main/java/com/cyksj/mapper/advertisement/AdvertisementOrderDonMapper.java
  3. 16 0
      netflix-dao/src/main/java/com/cyksj/mapper/advertisement/AdvertisementOrderPostMapper.java
  4. 11 0
      netflix-dao/src/main/java/com/cyksj/mapper/advertisement/AdvertisementPopularizeMapper.java
  5. 11 0
      netflix-dao/src/main/java/com/cyksj/mapper/advertisement/AdvertisementProjectMapper.java
  6. 11 0
      netflix-dao/src/main/java/com/cyksj/mapper/advertisement/AdvertisementUserMapper.java
  7. 12 0
      netflix-dao/src/main/java/com/cyksj/mapper/advertisement/tencent/TenCentActionSetMapper.java
  8. 12 0
      netflix-dao/src/main/java/com/cyksj/mapper/advertisement/tencent/TenCentUserAccessTokenMapper.java
  9. 12 0
      netflix-dao/src/main/java/com/cyksj/mapper/advertisement/tencent/TenCentUserMapper.java
  10. 60 0
      netflix-dao/src/main/java/com/cyksj/model/dto/MiniProgramSession.java
  11. 100 0
      netflix-dao/src/main/java/com/cyksj/model/entity/AdvertisementOrderDon.java
  12. 128 0
      netflix-dao/src/main/java/com/cyksj/model/entity/AdvertisementOrderPost.java
  13. 45 0
      netflix-dao/src/main/java/com/cyksj/model/entity/AdvertisementPopularize.java
  14. 48 0
      netflix-dao/src/main/java/com/cyksj/model/entity/AdvertisementProject.java
  15. 44 0
      netflix-dao/src/main/java/com/cyksj/model/entity/AdvertisementUser.java
  16. 34 0
      netflix-dao/src/main/java/com/cyksj/model/entity/TencentActionSet.java
  17. 74 0
      netflix-dao/src/main/java/com/cyksj/model/entity/TencentUser.java
  18. 31 0
      netflix-dao/src/main/java/com/cyksj/model/entity/TencentUserAccessToken.java
  19. 40 0
      netflix-dao/src/main/java/com/cyksj/model/request/MiniProgramLoginPost.java
  20. 34 0
      netflix-dao/src/main/java/com/cyksj/model/request/WeChatPayRequest.java
  21. 26 0
      netflix-dao/src/main/java/com/cyksj/model/views/AdvertisementPopularizeView.java
  22. 42 0
      netflix-dao/src/main/java/com/cyksj/model/views/AdvertisementTencentView.java
  23. 30 0
      netflix-dao/src/main/java/com/cyksj/model/views/PaySuccessViews.java
  24. 23 0
      netflix-service/src/main/java/com/cyksj/service/advertisement/AdvertisementOrderDonService.java
  25. 11 0
      netflix-service/src/main/java/com/cyksj/service/advertisement/AdvertisementOrderPostService.java
  26. 11 0
      netflix-service/src/main/java/com/cyksj/service/advertisement/AdvertisementPopularizeService.java
  27. 11 0
      netflix-service/src/main/java/com/cyksj/service/advertisement/AdvertisementProjectService.java
  28. 15 0
      netflix-service/src/main/java/com/cyksj/service/advertisement/AdvertisementUserService.java
  29. 202 0
      netflix-service/src/main/java/com/cyksj/service/advertisement/impl/AdvertisementOrderDonServiceImpl.java
  30. 63 0
      netflix-service/src/main/java/com/cyksj/service/advertisement/impl/AdvertisementOrderPostServiceImpl.java
  31. 15 0
      netflix-service/src/main/java/com/cyksj/service/advertisement/impl/AdvertisementPopularizeServiceImpl.java
  32. 16 0
      netflix-service/src/main/java/com/cyksj/service/advertisement/impl/AdvertisementProjectServiceImpl.java
  33. 75 0
      netflix-service/src/main/java/com/cyksj/service/advertisement/impl/AdvertisementUserServiceImpl.java
  34. 21 0
      netflix-service/src/main/java/com/cyksj/service/advertisement/postdata/AbstractPostDataService.java
  35. 43 0
      netflix-service/src/main/java/com/cyksj/service/advertisement/postdata/PostDataFactory.java
  36. 215 0
      netflix-service/src/main/java/com/cyksj/service/advertisement/postdata/impl/WeChatPostDataService.java
  37. 14 0
      netflix-service/src/main/java/com/cyksj/service/advertisement/tencent/TenCentActionSetService.java
  38. 12 0
      netflix-service/src/main/java/com/cyksj/service/advertisement/tencent/TenCentUserAccessTokenService.java
  39. 12 0
      netflix-service/src/main/java/com/cyksj/service/advertisement/tencent/TenCentUserService.java
  40. 20 0
      netflix-service/src/main/java/com/cyksj/service/advertisement/tencent/impl/TenCentActionSetServiceImpl.java
  41. 17 0
      netflix-service/src/main/java/com/cyksj/service/advertisement/tencent/impl/TenCentUserAccessTokenServiceImpl.java
  42. 17 0
      netflix-service/src/main/java/com/cyksj/service/advertisement/tencent/impl/TenCentUserServiceImpl.java
  43. 95 0
      netflix-service/src/main/java/com/cyksj/service/wechat/MiniProgramOperator.java
  44. 29 0
      netflix-service/src/main/java/com/cyksj/service/wechat/MiniProgramOps.java
  45. 2 0
      netflix-service/src/main/java/com/cyksj/service/wechat/WeChatService.java
  46. 3 0
      netflix-service/src/main/java/com/cyksj/service/wechat/WxMpAccountOps.java
  47. 8 0
      netflix-service/src/main/java/com/cyksj/service/wechat/impl/WeChatServiceImpl.java
  48. 37 0
      netflix-service/src/main/java/com/cyksj/service/wechat/impl/WxMpAccountOpsService.java
  49. 101 0
      netflix-web/src/main/java/com/cyksj/web/controller/advertisement/AdvertisementOrderDonController.java
  50. 49 0
      netflix-web/src/main/java/com/cyksj/web/controller/advertisement/AdvertisementPopularizeController.java
  51. 66 0
      netflix-web/src/main/java/com/cyksj/web/controller/advertisement/AdvertisementUserController.java
  52. 39 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/advertisement/CmsAdvertisementOrderDonController.java
  53. 86 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/advertisement/CmsAdvertisementPopularizeController.java
  54. 61 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/advertisement/CmsAdvertisementProjectController.java
  55. 38 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/advertisement/CmsAdvertisementUserController.java
  56. 1 1
      netflix-web/src/main/java/com/cyksj/web/controller/payment/OrderController.java
  57. 1 1
      netflix-web/src/main/java/com/cyksj/web/controller/register/RegisterController.java
  58. 0 0
      netflix-web/src/main/resources/application-dev.yml
  59. 0 0
      netflix-web/src/main/resources/application-prd.yml

+ 110 - 0
netflix-common/src/main/java/com/cyksj/common/util/SpringCtxUtils.java

@@ -0,0 +1,110 @@
+package com.cyksj.common.util;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+/**
+ * @ClassName SpringCtxUtils
+ * @Author chan
+ * @Date 2020-04-27 16:19
+ * @Description
+ */
+@Component
+public final class SpringCtxUtils implements ApplicationContextAware {
+
+    private static ApplicationContext context;
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+        SpringCtxUtils.context = applicationContext;
+    }
+
+    public static ApplicationContext getContext() {
+        return context;
+    }
+
+    /**
+     * 获取对象
+     *
+     * @param beanIdOrName bean name
+     * @return Object 一个以所给名字注册的bean的实例
+     * @throws BeansException 异常
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T getBean(String beanIdOrName) throws BeansException {
+        return StringUtils.isEmpty(beanIdOrName) ? null : (T) context.getBean(beanIdOrName);
+    }
+
+    /**
+     * 获取类型为requiredType的对象
+     *
+     * @param clazz {@link Class}
+     * @return T
+     * @throws BeansException 异常
+     */
+    public static <T> T getBean(Class<T> clazz) throws BeansException {
+        return clazz == null ? null : (T) context.getBean(clazz);
+    }
+
+    /**
+     * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
+     *
+     * @param name bean name
+     * @return boolean
+     */
+    public static boolean containsBean(String name) {
+        return context.containsBean(name);
+    }
+
+    /**
+     * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
+     *
+     * @param name bean name
+     * @return boolean
+     * @throws NoSuchBeanDefinitionException 异常
+     */
+    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
+        return context.isSingleton(name);
+    }
+
+    /**
+     * @param name bean name
+     * @return Class 注册对象的类型
+     * @throws NoSuchBeanDefinitionException 异常
+     */
+    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
+        return context.getType(name);
+    }
+
+    /**
+     * 如果给定的bean名字在bean定义中有别名,则返回这些别名
+     *
+     * @param name bean name
+     * @return String array
+     * @throws NoSuchBeanDefinitionException 异常
+     */
+    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
+        return context.getAliases(name);
+    }
+
+    /**
+     * <pre>
+     *     静默获取bean,无视异常
+     * </pre>
+     *
+     * @param clazz
+     * @param <T>
+     * @return
+     */
+    public static <T> T getBeanQuietly(Class<T> clazz) {
+        try {
+            return clazz == null ? null : (T) context.getBean(clazz);
+        } catch (Exception e) {
+            return null;
+        }
+    }
+}

+ 11 - 0
netflix-dao/src/main/java/com/cyksj/mapper/advertisement/AdvertisementOrderDonMapper.java

@@ -0,0 +1,11 @@
+package com.cyksj.mapper.advertisement;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.AdvertisementOrderDon;
+
+/**
+ * @author chan
+ * @date 2023/5/16 11:03 AM
+ */
+public interface AdvertisementOrderDonMapper extends BaseMapper<AdvertisementOrderDon> {
+}

+ 16 - 0
netflix-dao/src/main/java/com/cyksj/mapper/advertisement/AdvertisementOrderPostMapper.java

@@ -0,0 +1,16 @@
+package com.cyksj.mapper.advertisement;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.AdvertisementOrderPost;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Update;
+
+/**
+ * @author chan
+ * @date 2023/5/16 11:04 AM
+ */
+public interface AdvertisementOrderPostMapper extends BaseMapper<AdvertisementOrderPost> {
+
+    @Update("update advertisement_order_post o set o.status = 1  where o.order_id = #{orderId}")
+    void updateStatus(@Param("orderId") Long orderId);
+}

+ 11 - 0
netflix-dao/src/main/java/com/cyksj/mapper/advertisement/AdvertisementPopularizeMapper.java

@@ -0,0 +1,11 @@
+package com.cyksj.mapper.advertisement;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.AdvertisementPopularize;
+
+/**
+ * @author chan
+ * @date 2023/5/16 11:04 AM
+ */
+public interface AdvertisementPopularizeMapper extends BaseMapper<AdvertisementPopularize> {
+}

+ 11 - 0
netflix-dao/src/main/java/com/cyksj/mapper/advertisement/AdvertisementProjectMapper.java

@@ -0,0 +1,11 @@
+package com.cyksj.mapper.advertisement;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.AdvertisementProject;
+
+/**
+ * @author chan
+ * @date 2023/5/16 11:04 AM
+ */
+public interface AdvertisementProjectMapper extends BaseMapper<AdvertisementProject> {
+}

+ 11 - 0
netflix-dao/src/main/java/com/cyksj/mapper/advertisement/AdvertisementUserMapper.java

@@ -0,0 +1,11 @@
+package com.cyksj.mapper.advertisement;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.AdvertisementUser;
+
+/**
+ * @author chan
+ * @date 2023/5/16 11:04 AM
+ */
+public interface AdvertisementUserMapper extends BaseMapper<AdvertisementUser> {
+}

+ 12 - 0
netflix-dao/src/main/java/com/cyksj/mapper/advertisement/tencent/TenCentActionSetMapper.java

@@ -0,0 +1,12 @@
+package com.cyksj.mapper.advertisement.tencent;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.TencentActionSet;
+
+/**
+ * @author chan
+ * @className TenCentActionSetMapper
+ * @date 2020/12/16 6:53 下午
+ */
+public interface TenCentActionSetMapper extends BaseMapper<TencentActionSet> {
+}

+ 12 - 0
netflix-dao/src/main/java/com/cyksj/mapper/advertisement/tencent/TenCentUserAccessTokenMapper.java

@@ -0,0 +1,12 @@
+package com.cyksj.mapper.advertisement.tencent;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.TencentUserAccessToken;
+
+/**
+ * @author chan
+ * @className TenCentUserAccessTokenMapper
+ * @date 2020/12/16 5:03 下午
+ */
+public interface TenCentUserAccessTokenMapper extends BaseMapper<TencentUserAccessToken> {
+}

+ 12 - 0
netflix-dao/src/main/java/com/cyksj/mapper/advertisement/tencent/TenCentUserMapper.java

@@ -0,0 +1,12 @@
+package com.cyksj.mapper.advertisement.tencent;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.TencentUser;
+
+/**
+ * @author chan
+ * @className TenCentUserMapper
+ * @date 2020/12/16 5:03 下午
+ */
+public interface TenCentUserMapper extends BaseMapper<TencentUser> {
+}

+ 60 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/MiniProgramSession.java

@@ -0,0 +1,60 @@
+package com.cyksj.model.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author valor.
+ * @date 2019/12/3 20:36
+ */
+@Getter
+@Setter
+public class MiniProgramSession {
+
+    /**
+     * 用户唯一标识
+     */
+    private String openid;
+
+    /**
+     * 会话密钥
+     */
+    @JsonProperty("session_key")
+    private String sessionKey;
+
+    /**
+     * 用户在开放平台的唯一标识符
+     */
+    private String unionid;
+
+    /**
+     * 错误码
+     */
+    private Integer errcode;
+
+    /**
+     * 错误信息
+     */
+    private String errmsg;
+
+    /**
+     * baidu
+     * 错误码
+     */
+    private Integer errno;
+
+    /**
+     * baidu
+     * 错误描述
+     */
+    private String error;
+
+    /**
+     * baidu
+     * 错误描述信息
+     */
+    @JsonProperty("error_description")
+    private String errorDescription;
+
+}

+ 100 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/AdvertisementOrderDon.java

@@ -0,0 +1,100 @@
+package com.cyksj.model.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 
+ * @TableName advertisement_order_don
+ */
+@TableName(value ="advertisement_order_don")
+@Data
+@Accessors(chain = true)
+public class AdvertisementOrderDon extends BaseEntity implements Serializable {
+    /**
+     * 
+     */
+    private Long popularizeId;
+
+    /**
+     * 
+     */
+    private Long userId;
+
+    /**
+     * 
+     */
+    private String openId;
+
+    /**
+     * 订单号
+     */
+    private String orderNo;
+
+    /**
+     * 支付订单id
+     */
+    private String transactionId;
+
+    /**
+     * 
+     */
+    private BigDecimal money;
+
+    /**
+     * 来源
+     */
+    private Source source;
+
+    /**
+     * 
+     */
+    private Status status;
+
+    private Date payTime;
+
+
+    public enum Status {
+        /**
+         * 订单状态
+         */
+        noPayment("待付款"),
+        hasPayment("已付款");
+
+        private String desc;
+
+        Status(String desc) {
+            this.desc = desc;
+        }
+
+        public String getDesc() {
+            return desc;
+        }
+    }
+
+    public enum Source{
+
+        WeChat("微信"),
+        H5("h5"),
+        ALI_PAY("支付宝"),
+        Mini_Program("小程序"),
+        unknown("unknown");
+
+        private String desc;
+
+        Source(String desc){
+            this.desc = desc;
+        }
+
+    }
+
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+}

+ 128 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/AdvertisementOrderPost.java

@@ -0,0 +1,128 @@
+package com.cyksj.model.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.Getter;
+import lombok.experimental.Accessors;
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.stream.Stream;
+
+/**
+ * 
+ * @TableName advertisement_order_post
+ */
+@TableName(value ="advertisement_order_post")
+@Data
+@Accessors(chain = true)
+public class AdvertisementOrderPost extends BaseEntity implements Serializable {
+
+    /**
+     * 
+     */
+    private Long orderId;
+
+    /**
+     * 回传参数
+     */
+    private String callback;
+
+    /**
+     * 状态 true 已回传 false 未回传
+     */
+    private Boolean status;
+
+    /**
+     * Ks 快手 Dy抖音
+     */
+    private Type type;
+
+    /**
+     * 回传类型
+     */
+    private String evenType;
+
+
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 回传渠道类型
+     */
+    @Getter
+    public enum Type {
+
+        /**
+         * 抖音
+         */
+        DY("抖音回传", "Dy", "2"),
+
+        /**
+         * 微信
+         */
+        WeChat("微信回传", "WeChat", "COMPLETE_ORDER"),
+
+        /**
+         * adq
+         */
+        adq("腾讯回传", "adq", "COMPLETE_ORDER"),
+
+        ;
+
+        /**
+         * 描述
+         */
+        private String desc;
+
+        /**
+         * 回传类型
+         */
+        private String type;
+
+        /**
+         * 类型 表单提交
+         */
+        private String evenType;
+
+
+        Type(String desc, String type, String evenType) {
+            this.desc = desc;
+            this.type = type;
+            this.evenType = evenType;
+        }
+
+        /**
+         * 根据type 获取
+         *
+         * @param type
+         * @return
+         */
+        @SuppressWarnings("rawtypes")
+        public static Type getByType(String type) {
+            return Stream.of(Type.values())
+                    .filter((enums) -> enums.getType().equals(type)).findFirst().get();
+
+        }
+
+        /**
+         * 根据type
+         *
+         * @param type
+         * @return
+         */
+        @SuppressWarnings("rawtypes")
+        public static Boolean verify(String type) {
+            if (StringUtils.isBlank(type)) {
+                return Boolean.FALSE;
+            }
+            return Stream.of(Type.values())
+                    .anyMatch((enums) -> enums.getType().equals(type));
+        }
+
+
+    }
+}

+ 45 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/AdvertisementPopularize.java

@@ -0,0 +1,45 @@
+package com.cyksj.model.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 
+ * @TableName advertisement_popularize
+ */
+@TableName(value ="advertisement_popularize")
+@Data
+public class AdvertisementPopularize extends BaseEntity implements Serializable {
+    /**
+     * 项目id
+     */
+    private Long projectId;
+
+    /**
+     * url
+     */
+    private String url;
+
+    /**
+     * 推广渠道名称
+     */
+    private String popularizeName;
+
+    /**
+     * 是否删除
+     */
+    private Boolean isDel;
+
+    /**
+     * adp专属行为数据源id
+     */
+    private Long dataId;
+
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+}

+ 48 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/AdvertisementProject.java

@@ -0,0 +1,48 @@
+package com.cyksj.model.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 
+ * @TableName advertisement_project
+ */
+@TableName(value ="advertisement_project")
+@Data
+public class AdvertisementProject extends BaseEntity implements Serializable {
+
+    /**
+     * 
+     */
+    private String name;
+
+    /**
+     * 
+     */
+    private String img;
+
+    /**
+     * 成功页图片
+     */
+    private String successImg;
+
+    /**
+     * 金额
+     */
+    private BigDecimal money;
+
+    /**
+     * 
+     */
+    private String detail;
+
+
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+}

+ 44 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/AdvertisementUser.java

@@ -0,0 +1,44 @@
+package com.cyksj.model.entity;
+
+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 lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 
+ * @TableName advertisement_user
+ */
+@TableName(value ="advertisement_user")
+@Data
+@Accessors(chain = true)
+public class AdvertisementUser extends BaseEntity implements Serializable {
+
+    /**
+     * 推广id
+     */
+    private Long popularizeId;
+
+    /**
+     * 手机号;手机号
+     */
+    private String phone;
+
+    /**
+     * openId
+     */
+    private String openId;
+
+    /**
+     * 开放平台唯一id;开放平台唯一id
+     */
+    private String unionid;
+
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+}

+ 34 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/TencentActionSet.java

@@ -0,0 +1,34 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+
+/**
+ * @author chan
+ * @className TencentActionSet
+ * @description 数据源记录
+ * @date 2020/12/16 6:52 下午
+ */
+@Getter
+@Setter
+public class TencentActionSet extends BaseEntity implements Serializable {
+
+    /**
+     * 腾讯账号id
+     */
+    private Long userId;
+
+    private String name;
+
+    private Integer userActionSetId;
+
+    /**
+     * 推广账号类型
+     */
+    private String type;
+
+    private String status;
+
+}

+ 74 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/TencentUser.java

@@ -0,0 +1,74 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+
+/**
+ * @author chan
+ * @className TencentUser
+ * @description 腾讯广告用户
+ * @date 2020/12/16 4:28 下午
+ */
+@Getter
+@Setter
+public class TencentUser extends BaseEntity implements Serializable {
+
+    private Integer clientId;
+    /**
+     * 授权的推广帐号对应的 QQ 号
+     */
+    private Integer accountUin;
+
+    /**
+     * 授权的推广帐号 id,大部分接口均需同步该字段,请妥善保存
+     */
+    private Integer accountId;
+
+    /**
+     * 权限列表,若为空,则表示拥有所属应用的所有权限
+     */
+    private String scopeList;
+
+    /**
+     * 授权的推广帐号对应的微信帐号 id
+     */
+    private String wechatAccountId;
+
+    /**
+     * 授权账号身份类型,授权账号类型广告主,代理商,T1 账户,商务管家账户,[枚举详情]
+     */
+    private AccountRoleType accountRoleType;
+
+    /**
+     * 账号类型,[枚举详情]
+     */
+    private String accountType;
+
+    /**
+     * 角色
+     */
+    private String roleType;
+
+
+    /**
+     * 授权账号身份类型
+     */
+    enum AccountRoleType{
+
+        ACCOUNT_ROLE_TYPE_ADVERTISER("广告主"),
+        ACCOUNT_ROLE_TYPE_AGENCY("代理商"),
+        ACCOUNT_ROLE_TYPE_T1("T1 账户"),
+        ACCOUNT_ROLE_TYPE_BUSINESS_MANAGER("商务管家账户");
+        /**
+         * 描述
+         */
+        private String desc;
+
+        AccountRoleType(String desc){
+            this.desc = desc;
+        }
+    }
+
+}

+ 31 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/TencentUserAccessToken.java

@@ -0,0 +1,31 @@
+package com.cyksj.model.entity;
+
+import lombok.*;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @author chan
+ * @className TencentUserAccessToken
+ * @description 用户token
+ * @date 2020/12/16 4:43 下午
+ */
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class TencentUserAccessToken extends BaseEntity implements Serializable {
+
+    private Long tencentUserId;
+
+    private String accessToken;
+
+    private Date expiresIn;
+
+    private String refreshToken;
+
+    private Date refreshTokenExpiresIn;
+
+}

+ 40 - 0
netflix-dao/src/main/java/com/cyksj/model/request/MiniProgramLoginPost.java

@@ -0,0 +1,40 @@
+package com.cyksj.model.request;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.experimental.Accessors;
+
+/**
+ * @author chan
+ * @className MiniProgramLoginPost
+ * @description 小程序授权登录
+ * @date 2020/8/5 4:29 下午
+ */
+@Getter
+@Setter
+@ToString
+@Accessors(chain = true)
+public class MiniProgramLoginPost {
+
+    /**
+     * 登录凭证
+     */
+    private String code;
+
+    /**
+     * 密文
+     */
+    private String data;
+
+    /**
+     * 填充向量
+     */
+    private String iv;
+
+    /**
+     * appId
+     */
+    private String appId;
+
+}

+ 34 - 0
netflix-dao/src/main/java/com/cyksj/model/request/WeChatPayRequest.java

@@ -0,0 +1,34 @@
+package com.cyksj.model.request;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.DecimalMin;
+import javax.validation.constraints.NotNull;
+import java.math.BigDecimal;
+
+/**
+ * @author chan
+ * @className FoundationOrder
+ * @description 微信支付入参
+ * @date 2020/9/3 4:23 下午
+ */
+@Getter
+@Setter
+public class WeChatPayRequest {
+
+    @NotNull(message = "缺少必填参数")
+    private Long popularizeId;
+
+    @NotNull(message = "请输入金额")
+    @DecimalMin(value = "1",message = "请输入金额")
+    private BigDecimal donMoney;
+
+    private String appId;
+
+
+    private String callback;
+
+    private String callbackType;
+
+}

+ 26 - 0
netflix-dao/src/main/java/com/cyksj/model/views/AdvertisementPopularizeView.java

@@ -0,0 +1,26 @@
+package com.cyksj.model.views;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * @author chan
+ * @date 2023/5/16 2:52 PM
+ */
+@Data
+public class AdvertisementPopularizeView {
+
+    private Long id;
+
+    private BigDecimal money;
+
+    private String img;
+
+    private String successImg;
+
+    private String detail;
+
+    private String name;
+
+}

+ 42 - 0
netflix-dao/src/main/java/com/cyksj/model/views/AdvertisementTencentView.java

@@ -0,0 +1,42 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @ClassName advertiserTencentVo
+ * @Description 腾讯广告账号
+ * @Author Huang yuanzhi
+ * @Date 2022/8/5 13:41
+ * @Version 1.0.0
+ **/
+@Data
+@SearchBean( tables = " tencent_user tu left join tencent_action_set tas on tu.id = tas.user_id")
+public class AdvertisementTencentView {
+
+    @DbField("tu.id")
+    private Long id;
+
+    /**
+     * 推广账号id
+     */
+    @DbField("tu.account_id")
+    private Long accountId;
+
+    @DbField("tas.name")
+    private String name;
+
+    @DbField("tas.user_action_set_id")
+    private Long userActionSetId;
+
+    @DbField("tas.status")
+    private String status;
+
+    @DbField("tu.created_time")
+    private Date createdTime;
+
+    private static final long serialVersionUID = 1L;
+}

+ 30 - 0
netflix-dao/src/main/java/com/cyksj/model/views/PaySuccessViews.java

@@ -0,0 +1,30 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.AdvertisementOrderDon;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * @author chan
+ * @date 2022/1/7 下午12:17
+ */
+@Getter
+@Setter
+public class PaySuccessViews implements Serializable {
+
+    private Boolean isPay;
+
+    private String transactionId;
+
+    private BigDecimal money;
+
+    private Date payTime;
+
+    private AdvertisementOrderDon.Source source;
+
+
+}

+ 23 - 0
netflix-service/src/main/java/com/cyksj/service/advertisement/AdvertisementOrderDonService.java

@@ -0,0 +1,23 @@
+package com.cyksj.service.advertisement;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.dto.H5JsPayParams;
+import com.cyksj.model.entity.AdvertisementOrderDon;
+import com.cyksj.model.entity.AdvertisementUser;
+import com.cyksj.model.views.PaySuccessViews;
+
+import java.math.BigDecimal;
+import java.util.Map;
+
+/**
+ * @author chan
+ * @date 2023/5/16 11:07 AM
+ */
+public interface AdvertisementOrderDonService extends IService<AdvertisementOrderDon> {
+    H5JsPayParams minipay(Long popularizeId, BigDecimal money, String appId, AdvertisementUser user, String callback, String callbackType) throws Exception;
+
+    void prepayNotify(Map<String, String> map) throws Exception;
+
+    PaySuccessViews isPay(Long orderId);
+
+}

+ 11 - 0
netflix-service/src/main/java/com/cyksj/service/advertisement/AdvertisementOrderPostService.java

@@ -0,0 +1,11 @@
+package com.cyksj.service.advertisement;
+
+/**
+ * @author chan
+ * @date 2023/5/16 11:05 AM
+ */
+public interface AdvertisementOrderPostService {
+    void postData(Long orderId) throws Exception;
+
+    void savePostData(Long orderId, String callback, String callbackType);
+}

+ 11 - 0
netflix-service/src/main/java/com/cyksj/service/advertisement/AdvertisementPopularizeService.java

@@ -0,0 +1,11 @@
+package com.cyksj.service.advertisement;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.entity.AdvertisementPopularize;
+
+/**
+ * @author chan
+ * @date 2023/5/16 11:06 AM
+ */
+public interface AdvertisementPopularizeService extends IService<AdvertisementPopularize> {
+}

+ 11 - 0
netflix-service/src/main/java/com/cyksj/service/advertisement/AdvertisementProjectService.java

@@ -0,0 +1,11 @@
+package com.cyksj.service.advertisement;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.entity.AdvertisementProject;
+
+/**
+ * @author chan
+ * @date 2023/5/16 11:06 AM
+ */
+public interface AdvertisementProjectService extends IService<AdvertisementProject> {
+}

+ 15 - 0
netflix-service/src/main/java/com/cyksj/service/advertisement/AdvertisementUserService.java

@@ -0,0 +1,15 @@
+package com.cyksj.service.advertisement;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.dto.UserWhoami;
+import com.cyksj.model.entity.AdvertisementUser;
+
+/**
+ * @author chan
+ * @date 2023/5/16 11:05 AM
+ */
+public interface AdvertisementUserService extends IService<AdvertisementUser> {
+    AdvertisementUser wxlogin(String code, String appId) throws Exception;
+
+    UserWhoami whoami(Long userId);
+}

+ 202 - 0
netflix-service/src/main/java/com/cyksj/service/advertisement/impl/AdvertisementOrderDonServiceImpl.java

@@ -0,0 +1,202 @@
+package com.cyksj.service.advertisement.impl;
+
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.http.HttpUtil;
+import cn.hutool.json.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
+import com.cyksj.common.util.Codec;
+import com.cyksj.common.util.Jsons;
+import com.cyksj.common.util.StringUtil;
+import com.cyksj.config.BaseWeChatConfig;
+import com.cyksj.config.WeChatFactory;
+import com.cyksj.mapper.advertisement.AdvertisementOrderDonMapper;
+import com.cyksj.mapper.advertisement.AdvertisementPopularizeMapper;
+import com.cyksj.mapper.advertisement.AdvertisementProjectMapper;
+import com.cyksj.model.dto.H5JsPayParams;
+import com.cyksj.model.entity.*;
+import com.cyksj.model.request.OrderAttach;
+import com.cyksj.model.views.PaySuccessViews;
+import com.cyksj.service.advertisement.AdvertisementOrderDonService;
+import com.cyksj.service.advertisement.AdvertisementOrderPostService;
+import com.cyksj.service.advertisement.AdvertisementPopularizeService;
+import com.cyksj.service.advertisement.AdvertisementProjectService;
+import com.cyksj.service.wechat.WeChatService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.Assert;
+
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author chan
+ * @date 2023/5/16 11:07 AM
+ */
+@Service
+@RequiredArgsConstructor
+@Slf4j
+public class AdvertisementOrderDonServiceImpl extends ServiceImpl<AdvertisementOrderDonMapper, AdvertisementOrderDon> implements AdvertisementOrderDonService {
+    
+    @Value("${advertisement.shopKey}")
+    private String shopKey;
+
+    @Value("${advertisement.appId}")
+    private String appId;
+
+    @Value("${advertisement.shopId}")
+    private String shopId;
+
+    @Value("${advertisement.notify}")
+    private String notify;
+    
+    private final static GlobalThreadPoolTaskExecutor THREAD_POOL_TASK_EXECUTOR = GlobalThreadPoolTaskExecutor.getInstance();
+
+    private final AdvertisementPopularizeMapper popularizeMapper;
+
+    private final WeChatService weChatService;
+    
+    private final AdvertisementOrderPostService orderPostService;
+
+    private final AdvertisementProjectMapper projectMapper;
+
+    @Override
+    public H5JsPayParams minipay(Long popularizeId, BigDecimal money, String appId, AdvertisementUser user, String callback, String callbackType) throws Exception {
+        if(!this.appId.equals(appId)){
+            throw BusinessRuntimeException.getInstance("appId非法.");
+        }
+        AdvertisementPopularize popularize = popularizeMapper.selectById(popularizeId);
+        if (popularize == null) {
+            log.error("链接不存在:{}", popularizeId);
+            throw BusinessRuntimeException.getInstance("链接不存在");
+        }
+        AdvertisementProject project = projectMapper.selectById(popularize.getProjectId());
+
+        /* 生成订单 */
+        String payOpenId = user.getOpenId();
+
+        String donNo = Codec.DoDigest.custom()
+                .setAlgorithm(Codec.DoDigest.Algorithm.MD5)
+                .setStringData(System.currentTimeMillis() + payOpenId)
+                .toHexString();
+
+        AdvertisementOrderDon orderDon = new AdvertisementOrderDon().setPopularizeId(popularizeId).setMoney(money).setOrderNo(donNo).setUserId(user.getId())
+                .setOpenId(payOpenId).setSource(AdvertisementOrderDon.Source.Mini_Program);
+
+        this.saveOrUpdate(orderDon);
+
+        //数据回传
+        if (StringUtils.isNotBlank(callback)) {
+            orderPostService.savePostData(orderDon.getId(), callback, callbackType);
+        }
+
+
+        OrderAttach attach = new OrderAttach();
+
+        attach.setO(orderDon.getId());
+
+        String toWechatAttach = Codec.DoBase64.custom()
+                .setData(Jsons.toJson(attach)).encodeAsText();
+
+        H5JsPayParams params = weChatService.getJsPayParams(
+                appId,
+                shopId,
+                orderDon.getOpenId(),
+                orderDon.getMoney().intValue(),
+                orderDon.getOrderNo(),
+                notify + "applets/order/prepay/notify",
+                toWechatAttach,
+                project.getName(),
+                "JSAPI",
+                orderDon.getCreatedTime()
+        );
+        params.setOrderNo(orderDon.getOrderNo());
+        log.info("微信支付成功[end]");
+        return params;
+    }
+
+    @Override
+    public PaySuccessViews isPay(Long orderId) {
+        
+        AdvertisementOrderDon orderDon = getById(orderId);
+
+        Assert.notNull(orderDon, "订单不存在!");
+
+        AdvertisementPopularize popularize = popularizeMapper.selectById(orderDon.getPopularizeId());
+        Assert.notNull(popularize, "推广链接不存在");
+
+        AdvertisementProject project = projectMapper.selectById(popularize.getProjectId());
+        Assert.notNull(project, "推广项目不存在");
+        
+        PaySuccessViews paySuccessViews = new PaySuccessViews();
+        paySuccessViews.setTransactionId(orderDon.getTransactionId());
+        paySuccessViews.setIsPay(AdvertisementOrderDon.Status.hasPayment.equals(orderDon.getStatus()));
+        paySuccessViews.setMoney(orderDon.getMoney());
+        paySuccessViews.setPayTime(orderDon.getPayTime());
+        paySuccessViews.setSource(orderDon.getSource());
+
+        return paySuccessViews;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Throwable.class)
+    public void prepayNotify(Map<String, String> map) throws Exception {
+        /* 此处处理订单等业务逻辑 */
+        // 获取订单 和 微信订单号 和 支付的金额
+
+        String attach = Codec.DoBase64.custom().setData(map.get("attach")).decodeAsText();
+
+        OrderAttach orderV2Attach = Jsons.parseObject(attach, OrderAttach.class);
+
+        final Long oid = orderV2Attach.getO();
+        AdvertisementOrderDon order = this.getById(oid);
+
+        if (null == order) {
+            throw BusinessRuntimeException.getInstance("订单不存在.");
+        }
+        
+        // 校验签名
+        boolean f = weChatService.checkSignWithMd5(map, shopKey);
+        if (!f) {
+            log.error("回调数据:{}", map);
+            throw BusinessRuntimeException.getInstance("支付成功回调, 校验签名失败.");
+        }
+
+        String transactionId = map.get("transaction_id");
+
+        if (order.getStatus().equals(AdvertisementOrderDon.Status.hasPayment)) {
+            log.info("已回调,重复修改状态 id:{}", order.getId());
+            return;
+        }
+
+        // 更改订单状态
+        order.setTransactionId(transactionId);
+        order.setStatus(AdvertisementOrderDon.Status.hasPayment);
+        order.setPayTime(DateUtil.parse(map.get("time_end"), "yyyyMMddHHmmss"));
+        if (StringUtils.isBlank(order.getOpenId())) {
+            order.setOpenId(map.get("openid"));
+        }
+
+        this.updateById(order);
+        
+        THREAD_POOL_TASK_EXECUTOR.execute(()->{
+            try {
+                orderPostService.postData((order.getId()));
+            } catch (Exception e) {
+                log.error("回传错误 {}",StringUtil.getErrorText(e));
+            }
+        });
+    }
+}

+ 63 - 0
netflix-service/src/main/java/com/cyksj/service/advertisement/impl/AdvertisementOrderPostServiceImpl.java

@@ -0,0 +1,63 @@
+package com.cyksj.service.advertisement.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.common.util.Jsons;
+import com.cyksj.common.util.StringUtil;
+import com.cyksj.mapper.advertisement.AdvertisementOrderPostMapper;
+import com.cyksj.model.entity.AdvertisementOrderPost;
+import com.cyksj.service.advertisement.AdvertisementOrderPostService;
+import com.cyksj.service.advertisement.postdata.AbstractPostDataService;
+import com.cyksj.service.advertisement.postdata.PostDataFactory;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.util.Assert;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author chan
+ * @date 2023/5/16 11:05 AM
+ */
+@Service
+@Slf4j
+public class AdvertisementOrderPostServiceImpl  extends ServiceImpl<AdvertisementOrderPostMapper, AdvertisementOrderPost> implements AdvertisementOrderPostService {
+
+    @Override
+    public void postData(Long orderId) throws Exception {
+        AdvertisementOrderPost orderPost = this.getOne(Wrappers.lambdaQuery(AdvertisementOrderPost.class).eq(AdvertisementOrderPost::getOrderId, orderId).eq(AdvertisementOrderPost::getStatus, Boolean.FALSE));
+        if (orderPost == null) {
+            log.info("post 数据 不了存在 id:{}", orderId);
+            return;
+        }
+        post(orderId, orderPost);
+    }
+
+    @Override
+    public void savePostData(Long orderId, String callback, String callbackType) {
+        if (AdvertisementOrderPost.Type.verify(callbackType) && StringUtils.isNotBlank(callback)) {
+            log.info("订单数据回传添加记录:{},type:{},orderType:{}", orderId, callbackType);
+            AdvertisementOrderPost.Type byType = AdvertisementOrderPost.Type.getByType(callbackType);
+
+            this.save(new AdvertisementOrderPost().setCallback(callback).setEvenType(byType.getEvenType()).setOrderId(orderId).setType(byType));
+        }
+
+    }
+
+
+    /**
+     * 数据回传
+     */
+    private void post(Long orderId, AdvertisementOrderPost orderPost) throws Exception {
+        AbstractPostDataService postStrategy = PostDataFactory.getPostStrategy(orderPost.getType().getType());
+
+        Assert.notNull(postStrategy, "回传渠道类型不存在。");
+
+        postStrategy.postData(orderId, orderPost.getCallback(), orderPost.getEvenType());
+    }
+
+}

+ 15 - 0
netflix-service/src/main/java/com/cyksj/service/advertisement/impl/AdvertisementPopularizeServiceImpl.java

@@ -0,0 +1,15 @@
+package com.cyksj.service.advertisement.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.mapper.advertisement.AdvertisementPopularizeMapper;
+import com.cyksj.model.entity.AdvertisementPopularize;
+import com.cyksj.service.advertisement.AdvertisementPopularizeService;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author chan
+ * @date 2023/5/16 11:06 AM
+ */
+@Service
+public class AdvertisementPopularizeServiceImpl extends ServiceImpl<AdvertisementPopularizeMapper, AdvertisementPopularize> implements AdvertisementPopularizeService {
+}

+ 16 - 0
netflix-service/src/main/java/com/cyksj/service/advertisement/impl/AdvertisementProjectServiceImpl.java

@@ -0,0 +1,16 @@
+package com.cyksj.service.advertisement.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.mapper.advertisement.AdvertisementProjectMapper;
+import com.cyksj.model.entity.AdvertisementProject;
+import com.cyksj.service.advertisement.AdvertisementProjectService;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author chan
+ * @date 2023/5/16 11:06 AM
+ */
+@Service
+public class AdvertisementProjectServiceImpl extends ServiceImpl<AdvertisementProjectMapper, AdvertisementProject> implements AdvertisementProjectService {
+
+}

+ 75 - 0
netflix-service/src/main/java/com/cyksj/service/advertisement/impl/AdvertisementUserServiceImpl.java

@@ -0,0 +1,75 @@
+package com.cyksj.service.advertisement.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.util.StreamUtil;
+import com.cyksj.mapper.advertisement.AdvertisementProjectMapper;
+import com.cyksj.mapper.advertisement.AdvertisementUserMapper;
+import com.cyksj.model.dto.MiniProgramSession;
+import com.cyksj.model.dto.UserWhoami;
+import com.cyksj.model.entity.AdvertisementProject;
+import com.cyksj.model.entity.AdvertisementUser;
+import com.cyksj.model.entity.WxApp;
+import com.cyksj.service.advertisement.AdvertisementProjectService;
+import com.cyksj.service.advertisement.AdvertisementUserService;
+import com.cyksj.service.wechat.WeChatService;
+import lombok.RequiredArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+import org.checkerframework.checker.units.qual.A;
+import org.springframework.stereotype.Service;
+import org.springframework.util.Assert;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * @author chan
+ * @date 2023/5/16 11:05 AM
+ */
+@RequiredArgsConstructor
+@Service
+public class AdvertisementUserServiceImpl extends ServiceImpl<AdvertisementUserMapper, AdvertisementUser> implements AdvertisementUserService {
+
+    private final WeChatService weChatService;
+
+    @Override
+    public AdvertisementUser wxlogin(String code, String appId) throws Exception{
+        MiniProgramSession session = weChatService.code2Session(appId,code);
+        if(StringUtils.isBlank(session.getOpenid())){
+            throw BusinessRuntimeException.getInstance("获取用户信息异常.");
+        }
+        // 根据unionId 判断用户是否存在
+        String openid = session.getOpenid();
+
+        // 查询用户是否存在
+        LambdaQueryWrapper<AdvertisementUser> userLambdaQueryWrapper = new QueryWrapper<AdvertisementUser>().lambda();
+        userLambdaQueryWrapper.eq(AdvertisementUser::getOpenId, openid);
+
+        AdvertisementUser user = Optional.ofNullable(
+                        getOne(userLambdaQueryWrapper))
+                .orElseGet(() -> new AdvertisementUser()
+                        .setOpenId(openid));
+
+        this.saveOrUpdate(user);
+        user = getById(user.getId());
+
+        return user;
+    }
+
+    @Override
+    public UserWhoami whoami(Long userId) {
+        AdvertisementUser user = this.getById(userId);
+        Assert.notNull(user,"业务处理失败,请联系客服");
+        UserWhoami userWhoami = new UserWhoami();
+
+        BeanUtil.copyProperties(user, userWhoami);
+
+        return userWhoami;
+    }
+}

+ 21 - 0
netflix-service/src/main/java/com/cyksj/service/advertisement/postdata/AbstractPostDataService.java

@@ -0,0 +1,21 @@
+package com.cyksj.service.advertisement.postdata;
+
+/**
+ * @author chan
+ * @className AbstractPostDataService
+ * @description 数据回传抽象类
+ * @date 2020/11/23 3:33 下午
+ */
+public abstract class AbstractPostDataService {
+
+    /**
+     * @description  回传数据方法
+     * @author chan
+     * @date 2020-11-23 3:56 下午
+     * @param
+     * @return
+     */
+    public abstract void postData(Long orderId, String callBack, String evenType) throws Exception;
+
+
+}

+ 43 - 0
netflix-service/src/main/java/com/cyksj/service/advertisement/postdata/PostDataFactory.java

@@ -0,0 +1,43 @@
+package com.cyksj.service.advertisement.postdata;
+
+import com.cyksj.common.util.SpringCtxUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author chan
+ * @className PostDataFactory
+ * @description 数据回传工厂类
+ * @date 2020/11/23 3:46 下午
+ */
+public class PostDataFactory {
+
+    private static Map<String, AbstractPostDataService> strategyBean = new ConcurrentHashMap<>();
+
+    // 初始化
+    public static AbstractPostDataService getPostStrategy(String key) {
+        try {
+            if (StringUtils.isNotBlank(key)) {
+                return null;
+            }else {
+                key += "PostDataService";
+            }
+            AbstractPostDataService mapInPayNotify = strategyBean.get(key);
+            if (mapInPayNotify != null) {
+                return mapInPayNotify;
+            }
+            AbstractPostDataService newInPayNotify = SpringCtxUtils.getBean(key);
+            strategyBean.put(key, newInPayNotify);
+            return newInPayNotify;
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+    public static void add(AbstractPostDataService postDataService,String key) {
+        strategyBean.put(key,postDataService);
+    }
+
+}

+ 215 - 0
netflix-service/src/main/java/com/cyksj/service/advertisement/postdata/impl/WeChatPostDataService.java

@@ -0,0 +1,215 @@
+package com.cyksj.service.advertisement.postdata.impl;
+
+import cn.hutool.http.HttpUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.util.*;
+import com.cyksj.mapper.advertisement.AdvertisementOrderDonMapper;
+import com.cyksj.mapper.advertisement.AdvertisementOrderPostMapper;
+import com.cyksj.mapper.advertisement.AdvertisementPopularizeMapper;
+import com.cyksj.model.entity.*;
+import com.cyksj.service.advertisement.postdata.AbstractPostDataService;
+import com.cyksj.service.advertisement.postdata.PostDataFactory;
+import com.cyksj.service.advertisement.tencent.TenCentActionSetService;
+import com.cyksj.service.advertisement.tencent.TenCentUserAccessTokenService;
+import com.cyksj.service.advertisement.tencent.TenCentUserService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import java.net.URLDecoder;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+
+/**
+ * @author chan
+ * @className DyPostDataService
+ * @description 微信回传
+ * @date 2020/12/15 1:35 下午
+ */
+
+@Slf4j
+@Service("WeChatPostDataService")
+@RequiredArgsConstructor
+public class WeChatPostDataService extends AbstractPostDataService {
+
+
+    private final AdvertisementOrderPostMapper orderPostMapper;
+
+    private final AdvertisementPopularizeMapper popularizeMapper;
+
+    private final AdvertisementOrderDonMapper orderDonMapper;
+
+    private final TenCentActionSetService tenCentActionSetService;
+
+    private final TenCentUserAccessTokenService tenCentUserAccessTokenService;
+
+    private final TenCentUserService tenCentUserService;
+
+
+    @Override
+    public void postData(Long orderId, String callback, String evenType) throws Exception {
+
+        callback = callback.replaceAll("#", "");
+        log.info("腾讯广告回传入参id:{}", orderId);
+
+        callback = URLDecoder.decode(callback, IoKit.Charsets.UTF_8.getCharset());
+
+        Map<String, String> paramMap = HttpUtil.decodeParamMap(callback, StandardCharsets.UTF_8);
+        AdvertisementOrderDon orderDon = orderDonMapper.selectById(orderId);
+        AdvertisementPopularize popularize = popularizeMapper.selectById(orderDon.getPopularizeId());
+
+        String dataId = popularize.getDataId() != null ? StringUtil.getString(popularize.getDataId()) : paramMap.get("dataId");
+        //adq
+        if (dataId != null) {
+            String clickId = Optional.ofNullable(paramMap.get("click_id")).orElse(Optional.ofNullable(paramMap.get("qz_gdt")).orElse(Optional.ofNullable(paramMap.get("gdt_vid")).orElse("")));
+
+            TencentActionSet actionSet = tenCentActionSetService.getOne(Wrappers.lambdaQuery(TencentActionSet.class).eq(TencentActionSet::getUserActionSetId, dataId));
+            AdvertisementOrderPost orderPost = orderPostMapper.selectOne(Wrappers.lambdaQuery(AdvertisementOrderPost.class).eq(AdvertisementOrderPost::getOrderId, orderId));
+            orderPost.setType(AdvertisementOrderPost.Type.adq);
+            orderPostMapper.updateById(orderPost);
+            if (actionSet != null) {
+
+                TencentUser tencentUser = tenCentUserService.getById(actionSet.getUserId());
+                TencentUserAccessToken accessToken = tenCentUserAccessTokenService.getOne(new QueryWrapper<TencentUserAccessToken>().lambda().eq(TencentUserAccessToken::getTencentUserId, tencentUser.getId()));
+
+                String url = "https://api.e.qq.com/v1.3/user_actions/add?access_token=" + accessToken.getAccessToken() +
+                        "&timestamp=" + System.currentTimeMillis() / 1000 +
+                        "&nonce=" + Codec.DoDigest.custom().setAlgorithm(Codec.DoDigest.Algorithm.MD5).setStringData("toufang123" + System.currentTimeMillis()).toHexString();
+
+
+                List<Map<String, Object>> actions = new ArrayList<>();
+                Map<String, Object> action = new HashMap<>(8);
+                action.put("url", callback);
+                action.put("action_time", System.currentTimeMillis() / 1000);
+                action.put("action_type", evenType);
+                Map<Object, Object> trace = new HashMap<>(2);
+                trace.put("click_id", clickId);
+                action.put("trace", trace);
+                actions.add(action);
+
+                Map<String, Object> params = new HashMap<>(2);
+                params.put("user_action_set_id", actionSet.getUserActionSetId());
+                params.put("account_id", tencentUser.getAccountId());
+                params.put("actions", actions);
+
+                log.info("腾讯广告api回传 参数params:{}", Jsons.toJson(params));
+                HttpResponse<byte[]> res =
+                        J11HttpC.custom()
+                                .ofPost()
+                                .url(url)
+                                .headers(J11HttpC.ReqType.raw_json)
+                                .body(HttpRequest.BodyPublishers.ofString(Jsons.toJson(params), IoKit.Charsets.UTF_8.getCharset()))
+                                .send(HttpResponse.BodyHandlers.ofByteArray());
+
+
+                Map<String, Object> resMap = Jsons.parseObject(res.body(), Map.class);
+                log.info("腾讯广告api回传:{}", resMap);
+
+                String result = StringUtil.getString(resMap.get("code"));
+                if ("0".equals(result)) {
+                    //修改记录状态
+                    orderPostMapper.updateStatus(orderId);
+                    log.info("回传记录修改状态");
+
+                    // 判断回传状态
+                    if ("未接入".equals(actionSet.getStatus())) {
+                        actionSet.setStatus("已接入");
+                        tenCentActionSetService.updateById(actionSet);
+                    }
+                } else {
+                    //错误
+                    log.error("腾讯广告回传错误 msg:{}, orderId:{}", StringUtil.getString(resMap.get("message")), orderId);
+                }
+            }
+        }
+
+    }
+
+
+    //public void postWeChat(Long orderId, String callback, String evenType) throws Exception {
+    //
+    //    log.info("微信回传入参id:{}", orderId);
+    //    long time = System.currentTimeMillis();
+    //
+    //    AdvertisementOrderPost orderPost = orderPostMapper.getByOrderId(orderId);
+    //
+    //    AdvertisementOrderDon orderDon = orderDonMapper.selectById(orderId);
+    //    Long   popularizeId = orderDon.getPopularizeId();
+    //    String   openId = orderDon.getOpenId();
+    //
+    //    AdvertisementPopularize popularize = popularizeMapper.selectById(popularizeId);
+    //    String appId;
+    //    String dataId;
+    //
+    //    String accessToken = weChatService.getAccessToken(appId);
+    //    String url = "https://api.weixin.qq.com/marketing/user_actions/add?version=v1.0&access_token=" + accessToken;
+    //
+    //    callback = URLDecoder.decode(callback, IoKit.Charsets.UTF_8.getCharset());
+    //// 兼容性代码
+    //    Map<String, String> paramMap = HttpUtil.decodeParamMap(callback, StandardCharsets.UTF_8);
+    //
+    //    String clickId = paramMap.get("click_id") != null ? paramMap.get("click_id") : paramMap.get("gdt_vid");
+    //
+    //    List<Map<String,Object>> actions = new ArrayList<>();
+    //    Map<String,Object> action = new HashMap<>(8);
+    //    action.put("url",callback);
+    //    action.put("action_time", time /1000);
+    //    action.put("action_type",evenType);
+    //
+    //    Map<Object, Object> trace = new HashMap<>(2);
+    //    trace.put("click_id", clickId);
+    //    action.put("trace", trace);
+    //
+    //    //测试roi
+    //    if(popularizeId == 416936782416842752L || popularizeId == 421650470746984448L || popularizeId == 436556082228236288L || popularizeId == 451050013800271872L || popularizeId == 454269741779914752L || popularizeId == 435050773403930624L){
+    //        BigDecimal money;
+    //        if(FoundationOrderPost.OrderType.time.getType().equals(orderPost.getOrderType())){
+    //            //次捐
+    //            money = orderDonMapper.selectById(orderId).getMoney();
+    //        }else {
+    //            money = monthlyDonationMapper.selectById(orderId).getMoney();
+    //        }
+    //        Map<Object, Object> actionParam = new HashMap<>(2);
+    //        actionParam.put("value",money);
+    //        action.put("action_param", actionParam);
+    //    }
+    //
+    //    actions.add(action);
+    //
+    //    //
+    //    Map<String, Object> params = new HashMap<>(2);
+    //    params.put("user_action_set_id",dataId);
+    //    params.put("actions",actions);
+    //
+    //    HttpResponse<byte[]> res =
+    //            J11HttpC.custom()
+    //                    .ofPost()
+    //                    .url(url)
+    //                    .headers(J11HttpC.ReqType.raw_json)
+    //                    .body(HttpRequest.BodyPublishers.ofString(Jsons.toJson(params), IoKit.Charsets.UTF_8.getCharset()))
+    //                    .send(HttpResponse.BodyHandlers.ofByteArray());
+    //
+    //    Map<String, Object> resMap = Jsons.parseObject(res.body(), Map.class);
+    //    log.info("微信api回传:{}", resMap);
+    //
+    //    String result = StringUtil.getString(resMap.get("errcode"));
+    //    if ("0".equals(result)) {
+    //        //修改记录状态
+    //        orderPostMapper.updateStatus(orderId);
+    //        log.info("回传记录修改状态");
+    //    }else {
+    //        //错误
+    //        log.error("微信回传错误 msg:{}, orderId:{}",StringUtil.getString(resMap.get("errmsg")),orderId);
+    //    }
+    //}
+
+    @PostConstruct
+    public void init() {
+        PostDataFactory.add(this, this.getClass().getSimpleName());
+    }
+
+}

+ 14 - 0
netflix-service/src/main/java/com/cyksj/service/advertisement/tencent/TenCentActionSetService.java

@@ -0,0 +1,14 @@
+package com.cyksj.service.advertisement.tencent;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.entity.TencentActionSet;
+
+/**
+ * @author chan
+ * @className TenCentActionSetService
+ * @description 腾讯广告数据源
+ * @date 2020/12/16 6:54 下午
+ */
+public interface TenCentActionSetService extends IService<TencentActionSet> {
+
+}

+ 12 - 0
netflix-service/src/main/java/com/cyksj/service/advertisement/tencent/TenCentUserAccessTokenService.java

@@ -0,0 +1,12 @@
+package com.cyksj.service.advertisement.tencent;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.entity.TencentUserAccessToken;
+
+/**
+ * @author chan
+ * @className TenCentUserService
+ * @date 2020/12/16 5:01 下午
+ */
+public interface TenCentUserAccessTokenService extends IService<TencentUserAccessToken>{
+}

+ 12 - 0
netflix-service/src/main/java/com/cyksj/service/advertisement/tencent/TenCentUserService.java

@@ -0,0 +1,12 @@
+package com.cyksj.service.advertisement.tencent;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.entity.TencentUser;
+
+/**
+ * @author chan
+ * @className TenCentUserService
+ * @date 2020/12/16 5:01 下午
+ */
+public interface TenCentUserService extends IService<TencentUser>{
+}

+ 20 - 0
netflix-service/src/main/java/com/cyksj/service/advertisement/tencent/impl/TenCentActionSetServiceImpl.java

@@ -0,0 +1,20 @@
+package com.cyksj.service.advertisement.tencent.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.mapper.advertisement.tencent.TenCentActionSetMapper;
+import com.cyksj.model.entity.TencentActionSet;
+import com.cyksj.service.advertisement.tencent.TenCentActionSetService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author chan
+ * @className TenCentActionSetServiceImpl
+ * @description 数据源记录服务
+ * @date 2020/12/16 6:55 下午
+ */
+@Service
+@Slf4j
+public class TenCentActionSetServiceImpl extends ServiceImpl<TenCentActionSetMapper, TencentActionSet> implements TenCentActionSetService {
+
+}

+ 17 - 0
netflix-service/src/main/java/com/cyksj/service/advertisement/tencent/impl/TenCentUserAccessTokenServiceImpl.java

@@ -0,0 +1,17 @@
+package com.cyksj.service.advertisement.tencent.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.mapper.advertisement.tencent.TenCentUserAccessTokenMapper;
+import com.cyksj.model.entity.TencentUserAccessToken;
+import com.cyksj.service.advertisement.tencent.TenCentUserAccessTokenService;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author chan
+ * @className TenCentUserAccessTokenServiceImpl
+ * @date 2020/12/16 5:02 下午
+ */
+@Service
+public class TenCentUserAccessTokenServiceImpl extends ServiceImpl<TenCentUserAccessTokenMapper, TencentUserAccessToken> implements TenCentUserAccessTokenService {
+
+}

+ 17 - 0
netflix-service/src/main/java/com/cyksj/service/advertisement/tencent/impl/TenCentUserServiceImpl.java

@@ -0,0 +1,17 @@
+package com.cyksj.service.advertisement.tencent.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.mapper.advertisement.tencent.TenCentUserMapper;
+import com.cyksj.model.entity.TencentUser;
+import com.cyksj.service.advertisement.tencent.TenCentUserService;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author chan
+ * @className TenCentUserServiceImpl
+ * @date 2020/12/16 5:02 下午
+ */
+@Service
+public class TenCentUserServiceImpl extends ServiceImpl<TenCentUserMapper, TencentUser> implements TenCentUserService {
+
+}

+ 95 - 0
netflix-service/src/main/java/com/cyksj/service/wechat/MiniProgramOperator.java

@@ -0,0 +1,95 @@
+package com.cyksj.service.wechat;
+
+
+
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.util.IoKit;
+import com.cyksj.common.util.J11HttpC;
+import com.cyksj.common.util.Jsons;
+import com.cyksj.model.dto.MiniProgramSession;
+import com.cyksj.model.dto.WeChatAccessToken;
+
+import java.net.http.HttpResponse;
+
+/**
+ * @author valor.
+ * @date 2019/12/3 20:44
+ */
+public class MiniProgramOperator implements MiniProgramOps {
+
+//    private static final Logger log = LoggerFactory.getLogger(MiniProgramOperator.class);
+
+    private MiniProgramOperator() { }
+
+    private static volatile MiniProgramOperator instance;
+
+    public static MiniProgramOperator getInstance() {
+        if (null == instance) {
+            synchronized (MiniProgramOperator.class) {
+                if (null == instance) {
+                    instance = new MiniProgramOperator();
+                }
+            }
+        }
+        return instance;
+    }
+
+    @Override
+    public MiniProgramSession code2session(String appid, String secret, String code) throws Exception {
+        // GET https://api.weixin.qq.com/sns/jscode2session?appid={APPID}&secret={SECRET}&js_code={JSCODE}&grant_type=authorization_code
+        String url = "https://api.weixin.qq.com/sns/jscode2session" +
+                "?appid=" + appid +
+                "&secret=" + secret +
+                "&js_code=" + code +
+                "&grant_type=authorization_code";
+        HttpResponse<byte[]> res =
+                J11HttpC.custom()
+                        .ofGet()
+                        .url(url)
+                        .send(HttpResponse.BodyHandlers.ofByteArray());
+
+        if (200 != res.statusCode()) {
+            throw BusinessRuntimeException.getInstance("获取用户信息失败: " + IoKit.toString(res.body()));
+        }
+
+        MiniProgramSession session = Jsons.parseObject(res.body(), MiniProgramSession.class);
+        if (null == session) {
+            throw BusinessRuntimeException.getInstance("获取用户信息失败: " + IoKit.toString(res.body()));
+        }
+
+        final Integer errcode = session.getErrcode();
+        if (null != errcode && 0 != errcode) {
+            throw BusinessRuntimeException.getInstance("获取用户信息失败: " + session.getErrmsg() + "[" + errcode + "]");
+        }
+        return session;
+    }
+
+    @Override
+    public WeChatAccessToken access_token(String appid, String secret) throws Exception {
+        // GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={APPID}&secret={APPSECRET}
+        String url = "https://api.weixin.qq.com/cgi-bin/token" +
+                "?appid=" + appid +
+                "&secret=" + secret +
+                "&grant_type=client_credential";
+        HttpResponse<byte[]> res =
+                J11HttpC.custom()
+                        .ofGet()
+                        .url(url)
+                        .send(HttpResponse.BodyHandlers.ofByteArray());
+
+        if (200 != res.statusCode()) {
+            throw BusinessRuntimeException.getInstance("获取access_token失败: " + IoKit.toString(res.body()));
+        }
+
+        WeChatAccessToken token = Jsons.parseObject(res.body(), WeChatAccessToken.class);
+        if (null == token) {
+            throw BusinessRuntimeException.getInstance("获取access_token失败: " + IoKit.toString(res.body()));
+        }
+
+        final Integer errcode = token.getErrcode();
+        if (null != errcode && 0 != errcode) {
+            throw BusinessRuntimeException.getInstance("获取access_token失败: " + token.getErrmsg() + "[" + errcode + "]");
+        }
+        return token;
+    }
+}

+ 29 - 0
netflix-service/src/main/java/com/cyksj/service/wechat/MiniProgramOps.java

@@ -0,0 +1,29 @@
+package com.cyksj.service.wechat;
+
+
+import com.cyksj.model.dto.MiniProgramSession;
+import com.cyksj.model.dto.WeChatAccessToken;
+
+/**
+ * @author valor.
+ * @date 2019/12/3 18:33
+ */
+public interface MiniProgramOps {
+
+    public static MiniProgramOps create() {
+        return MiniProgramOperator.getInstance();
+    }
+
+    /**
+     * 根据code 换取session
+     * https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html
+     */
+    MiniProgramSession code2session(String appid, String secret, String code) throws Exception;
+
+    /**
+     * 获取access_token
+     * https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/access-token/auth.getAccessToken.html
+     */
+    WeChatAccessToken access_token(String appid, String secret) throws Exception;
+
+}

+ 2 - 0
netflix-service/src/main/java/com/cyksj/service/wechat/WeChatService.java

@@ -99,4 +99,6 @@ public interface WeChatService {
      * 获取跳转微信小程序链接
      */
     String getMiniURLLink(String accessToken, MiniURLLink miniURLLink) throws Exception;
+
+    MiniProgramSession code2Session(String appId, String code) throws Exception;
 }

+ 3 - 0
netflix-service/src/main/java/com/cyksj/service/wechat/WxMpAccountOps.java

@@ -1,6 +1,7 @@
 package com.cyksj.service.wechat;
 
 
+import com.cyksj.model.dto.MiniProgramSession;
 
 /**
  * @author valor.
@@ -17,4 +18,6 @@ public interface WxMpAccountOps {
       * 获取jsTicket
       */
      String jsTicket(String appId) throws Exception;
+
+    MiniProgramSession miniProgramCode2Session(String appId, String code) throws Exception;
 }

+ 8 - 0
netflix-service/src/main/java/com/cyksj/service/wechat/impl/WeChatServiceImpl.java

@@ -656,4 +656,12 @@ public class WeChatServiceImpl implements WeChatService {
                 .toUpperCase();
         return sign;
     }
+
+    @Override
+    public MiniProgramSession code2Session(String appId,String code) throws Exception {
+        appId = Optional.ofNullable(appId).orElse(weChatConfig.getAppid());
+
+        return wxMpAccountOps.miniProgramCode2Session(appId,code);
+    }
+
 }

+ 37 - 0
netflix-service/src/main/java/com/cyksj/service/wechat/impl/WxMpAccountOpsService.java

@@ -1,7 +1,14 @@
 package com.cyksj.service.wechat.impl;
 
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.util.SpringCtxUtils;
+import com.cyksj.mapper.WxAppMapper;
+import com.cyksj.model.dto.MiniProgramSession;
+import com.cyksj.model.entity.WxApp;
+import com.cyksj.service.wechat.MiniProgramOps;
 import com.cyksj.service.wechat.WxMpAccountOps;
 import com.cyksj.service.wechat.cach.AccountCache;
 import lombok.extern.slf4j.Slf4j;
@@ -20,6 +27,9 @@ public class WxMpAccountOpsService implements WxMpAccountOps {
     @Autowired
     private AccountCache ACCOUNT_CACHE;
 
+    private static final MiniProgramOps MINI_PROGRAM_OPS = MiniProgramOps.create();
+
+
     @Override
     public String accessToken(String appId) throws Exception {
         if (StringUtils.isBlank(appId)) {
@@ -44,5 +54,32 @@ public class WxMpAccountOpsService implements WxMpAccountOps {
 
         return ticket;
     }
+    
+    @Override
+    public MiniProgramSession miniProgramCode2Session(String appId, String code) throws Exception {
+
+        if (StringUtils.isBlank(appId)) {
+            throw BusinessRuntimeException.getInstance("Empty appId.");
+        }
+        if (StringUtils.isBlank(code)) {
+            throw BusinessRuntimeException.getInstance("Empty code.");
+        }
+
+        WxAppMapper wxAppMapper = SpringCtxUtils.getBean(WxAppMapper.class);
+        LambdaQueryWrapper<WxApp> wxAppLambdaQueryWrapper = new QueryWrapper<WxApp>().lambda();
+        wxAppLambdaQueryWrapper.eq(WxApp::getAppId,appId);
+        WxApp wxApp = wxAppMapper.selectOne(wxAppLambdaQueryWrapper);
+
+        if (null == wxApp) {
+            throw BusinessRuntimeException.getInstance("No appid configured.");
+        }
+        final String secret = wxApp.getAppSecret();
+
+        MiniProgramSession session = MINI_PROGRAM_OPS.code2session(appId, secret, code);
+        log.info("miniProgram[{}]: unionid[{}] / session_key[{}]", appId, session.getUnionid(), session.getSessionKey());
+
+        return session;
+
+    }
 
 }

+ 101 - 0
netflix-web/src/main/java/com/cyksj/web/controller/advertisement/AdvertisementOrderDonController.java

@@ -0,0 +1,101 @@
+package com.cyksj.web.controller.advertisement;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.util.IoKit;
+import com.cyksj.common.util.Xmls;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayApiCode;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.model.dto.H5JsPayParams;
+import com.cyksj.model.entity.AdvertisementUser;
+import com.cyksj.model.entity.WxApp;
+import com.cyksj.model.request.WeChatPayRequest;
+import com.cyksj.model.views.PaySuccessViews;
+import com.cyksj.redis.RedisService;
+import com.cyksj.service.advertisement.AdvertisementOrderDonService;
+import com.cyksj.service.advertisement.AdvertisementUserService;
+import com.cyksj.web.util.StpUserUtil;
+import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.OutputStream;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.Map;
+
+/**
+ * @author chan
+ * @date 2023/5/16 11:49 AM
+ */
+@Slf4j
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/applets/advertisement/order")
+public class AdvertisementOrderDonController {
+
+    private final AdvertisementUserService advertisementUserService;
+
+    private final AdvertisementOrderDonService advertisementOrderDonService;
+
+    @PostMapping("/post/pay")
+    public Result<H5JsPayParams> pay(@RequestBody @Validated WeChatPayRequest weChatPayRequest) throws Exception {
+        final String methodName = "广告投放微信支付";
+        BigDecimal donMoney = weChatPayRequest.getDonMoney();
+        log.info("{}[start] donMoney:{}", methodName, donMoney);
+
+        if (StringUtils.isBlank(weChatPayRequest.getAppId())) {
+            throw BusinessRuntimeException.getInstance("缺少必填参数appId");
+        }
+
+        //小程序支付
+        AdvertisementUser user = advertisementUserService.getById(StpUserUtil.getLoginIdAsLong());
+
+        H5JsPayParams payParams = advertisementOrderDonService.minipay(weChatPayRequest.getPopularizeId()
+                , donMoney.setScale(0, RoundingMode.DOWN), weChatPayRequest.getAppId(), user
+                , weChatPayRequest.getCallback(), weChatPayRequest.getCallbackType());
+
+
+        return GatewayResponse.SUCCESS.newBuilder().toResult(payParams);
+    }
+
+    @GetMapping("/isPay/{orderId}")
+    public Result<PaySuccessViews> isPay(@PathVariable @NonNull Long orderId) {
+        return GatewayResponse.SUCCESS.newBuilder().toResult(advertisementOrderDonService.isPay(orderId));
+    }
+
+    @PostMapping("/prepay/notify")
+    public void prepayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
+
+        String xml = IoKit.toString(request.getInputStream());
+        log.info("=== 微信支付的回调: \n {}", xml);
+
+        // 解析xml
+        Map<String, String> map = Xmls.toMap(xml);
+
+        // 支付失败
+        if (!StringUtils.equals("SUCCESS", map.get("return_code")) || !StringUtils.equals("SUCCESS", map.get("result_code"))) {
+            throw BusinessRuntimeException.getInstance("支付失败.");
+        }
+
+        advertisementOrderDonService.prepayNotify(map);
+        String toWeChatXmlResponse = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
+
+        OutputStream out = null;
+        try {
+            out = response.getOutputStream();
+            IoKit.write(toWeChatXmlResponse, out);
+        } catch (Throwable e) {
+            throw new BusinessRuntimeException(e,"微信支付回调错误.");
+        } finally {
+            IoKit.close(out);
+        }
+    }
+}

+ 49 - 0
netflix-web/src/main/java/com/cyksj/web/controller/advertisement/AdvertisementPopularizeController.java

@@ -0,0 +1,49 @@
+package com.cyksj.web.controller.advertisement;
+
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.model.entity.AdvertisementPopularize;
+import com.cyksj.model.entity.AdvertisementProject;
+import com.cyksj.model.views.AdvertisementPopularizeView;
+import com.cyksj.service.advertisement.AdvertisementPopularizeService;
+import com.cyksj.service.advertisement.AdvertisementProjectService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author chan
+ * @date 2023/5/16 11:49 AM
+ */
+@Slf4j
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/applets/advertisement/popularize")
+public class AdvertisementPopularizeController {
+
+    private final AdvertisementPopularizeService advertisementPopularizeService;
+
+    private final AdvertisementProjectService advertisementProjectService;
+
+    @GetMapping("/{id}")
+    public Result<AdvertisementPopularizeView> get(@PathVariable Long id){
+        AdvertisementPopularize popularize = advertisementPopularizeService.getById(id);
+        if (popularize == null) {
+            throw BusinessRuntimeException.getInstance("链接不存在.");
+        }
+        AdvertisementProject project = advertisementProjectService.getById(popularize.getProjectId());
+
+        AdvertisementPopularizeView view = new AdvertisementPopularizeView();
+        view.setId(popularize.getId());
+        view.setName(project.getName());
+        view.setDetail(project.getDetail());
+        view.setSuccessImg(project.getSuccessImg());
+        view.setMoney(project.getMoney());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(view);
+    }
+
+}

+ 66 - 0
netflix-web/src/main/java/com/cyksj/web/controller/advertisement/AdvertisementUserController.java

@@ -0,0 +1,66 @@
+package com.cyksj.web.controller.advertisement;
+
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.model.dto.UserWhoami;
+import com.cyksj.model.entity.AdvertisementUser;
+import com.cyksj.model.request.MiniProgramLoginPost;
+import com.cyksj.service.advertisement.AdvertisementUserService;
+import com.cyksj.web.util.StpUserUtil;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * @author chan
+ * @date 2023/5/16 11:49 AM
+ */
+@Slf4j
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/applets/advertisement/user")
+public class AdvertisementUserController {
+
+    private final AdvertisementUserService advertisementUserService;
+
+    /**
+     * 小程序静默授权
+     */
+    @PostMapping(value = "/login")
+    @Transactional(rollbackFor = Exception.class)
+    public Result<String> wxlogin(@RequestBody MiniProgramLoginPost miniDataParams) throws Exception{
+        String methodName = "小程序静默授权";
+        log.info("{}[start] params:{}",methodName,miniDataParams);
+
+        if (StringUtils.isBlank(miniDataParams.getCode())) {
+            throw BusinessRuntimeException.getInstance("需要登录凭证code.");
+        }
+
+        final String code = miniDataParams.getCode();
+
+        // 用户token
+        AdvertisementUser user = advertisementUserService.wxlogin(code,miniDataParams.getAppId());
+        StpUserUtil.login(user.getId());
+
+        log.info("{}[end] uuid:{}",methodName, user.getId());
+
+        return GatewayResponse.SUCCESS.newBuilder().toResult(StpUserUtil.getTokenValue());
+
+    }
+
+    @GetMapping(value = "/whoami")
+    public Result<UserWhoami> whoami(){
+        AdvertisementUser user = advertisementUserService.getById(StpUserUtil.getLoginIdAsLong());
+
+        UserWhoami userWhoami = advertisementUserService.whoami(user.getId());
+
+        return GatewayResponse.SUCCESS.newBuilder().toResult(userWhoami);
+    }
+
+
+
+
+}

+ 39 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/advertisement/CmsAdvertisementOrderDonController.java

@@ -0,0 +1,39 @@
+package com.cyksj.web.controller.manage.advertisement;
+
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.model.entity.AdvertisementOrderDon;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * @author chan
+ * @date 2023/5/16 11:07 AM
+ */
+@RestController
+@RequestMapping("manage/advertisement/order")
+@Slf4j
+@RequiredArgsConstructor
+public class CmsAdvertisementOrderDonController {
+
+    private final HttpServletRequest request;
+
+    private final BeanSearcher beanSearcher;
+
+    @GetMapping
+    public Result<SearchResult<AdvertisementOrderDon>> get() {
+        SearchResult<AdvertisementOrderDon> searchResult = beanSearcher.search(AdvertisementOrderDon.class,
+                MapUtils.flatBuilder(request.getParameterMap())
+                        .build());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(searchResult);
+    }
+
+}

+ 86 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/advertisement/CmsAdvertisementPopularizeController.java

@@ -0,0 +1,86 @@
+package com.cyksj.web.controller.manage.advertisement;
+
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.model.entity.AdvertisementPopularize;
+import com.cyksj.model.views.AdvertisementTencentView;
+import com.cyksj.service.advertisement.AdvertisementPopularizeService;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.param.Operator;
+import com.ejlchina.searcher.util.MapBuilder;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+
+/**
+ * @author chan
+ * @date 2023/5/16 11:06 AM
+ */
+@RestController
+@RequestMapping("manage/advertisement/popularize")
+@Slf4j
+@RequiredArgsConstructor
+public class CmsAdvertisementPopularizeController {
+
+    private final HttpServletRequest request;
+
+    private final BeanSearcher beanSearcher;
+
+    private final AdvertisementPopularizeService advertisementPopularizeService;
+
+    @GetMapping
+    public Result<SearchResult<AdvertisementPopularize>> get() {
+        SearchResult<AdvertisementPopularize> searchResult = beanSearcher.search(AdvertisementPopularize.class,
+                MapUtils.flatBuilder(request.getParameterMap())
+                        .build());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(searchResult);
+    }
+
+    @PostMapping
+    public Result<AdvertisementPopularize> post(@RequestBody AdvertisementPopularize popularize) {
+        advertisementPopularizeService.save(popularize);
+        popularize.setUrl(popularize.getUrl() + "?fid=" + popularize.getId());
+        advertisementPopularizeService.updateById(popularize);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(advertisementPopularizeService.getById(popularize.getId()));
+    }
+
+    @PutMapping
+    public Result<String> put(@RequestBody AdvertisementPopularize popularize) {
+        advertisementPopularizeService.updateById(popularize);
+        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    }
+
+    @DeleteMapping("/{id}")
+    public Result<String> del(@PathVariable Long id) {
+        advertisementPopularizeService.removeById(id);
+        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    }
+
+
+    @GetMapping("/getDataIdList")
+    public Result<SearchResult<AdvertisementTencentView>> get(@RequestParam(required = false) Long accountId,
+                                                              @RequestParam(required = false) Long userActionSetId) throws Exception {
+
+        MapBuilder params = MapUtils.builder()
+                .field(AdvertisementTencentView::getAccountId, accountId)
+                .field(AdvertisementTencentView::getUserActionSetId, userActionSetId)
+                .orderBy(AdvertisementTencentView::getId, "desc");
+        // 选择数据源查询数据
+
+        params.field(AdvertisementTencentView::getName)
+                .op(Operator.NotNull)
+                .onlySelect(AdvertisementTencentView::getUserActionSetId, AdvertisementTencentView::getName);
+        List<AdvertisementTencentView> list = beanSearcher.searchAll(AdvertisementTencentView.class, params.build());
+        list.stream().forEach(advertiserTencentVo -> advertiserTencentVo.setName(advertiserTencentVo.getName() + "-" + advertiserTencentVo.getUserActionSetId()));
+        return GatewayResponse.SUCCESS.newBuilder().toResult(new SearchResult<>(list));
+
+
+    }
+
+
+}

+ 61 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/advertisement/CmsAdvertisementProjectController.java

@@ -0,0 +1,61 @@
+package com.cyksj.web.controller.manage.advertisement;
+
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.model.entity.AdvertisementPopularize;
+import com.cyksj.model.entity.AdvertisementProject;
+import com.cyksj.service.advertisement.AdvertisementPopularizeService;
+import com.cyksj.service.advertisement.AdvertisementProjectService;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * @author chan
+ * @date 2023/5/16 11:06 AM
+ */
+@RestController
+@RequestMapping("manage/advertisement/project")
+@Slf4j
+@RequiredArgsConstructor
+public class CmsAdvertisementProjectController{
+
+
+    private final HttpServletRequest request;
+
+    private final BeanSearcher beanSearcher;
+
+    private final AdvertisementProjectService advertisementProjectService;
+
+    @GetMapping
+    public Result<SearchResult<AdvertisementProject>> get() {
+        SearchResult<AdvertisementProject> searchResult = beanSearcher.search(AdvertisementProject.class,
+                MapUtils.flatBuilder(request.getParameterMap())
+                        .build());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(searchResult);
+    }
+
+    @PostMapping
+    public Result<AdvertisementProject> post(@RequestBody AdvertisementProject project){
+        advertisementProjectService.save(project);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(advertisementProjectService.getById(project.getId()));
+    }
+
+    @PutMapping
+    public Result<String> put(@RequestBody AdvertisementProject project){
+        advertisementProjectService.updateById(project);
+        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    }
+
+    @DeleteMapping("/{id}")
+    public Result<String> del(@PathVariable Long id){
+        advertisementProjectService.removeById(id);
+        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    }
+
+}

+ 38 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/advertisement/CmsAdvertisementUserController.java

@@ -0,0 +1,38 @@
+package com.cyksj.web.controller.manage.advertisement;
+
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.model.entity.AdvertisementUser;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * @author chan
+ * @date 2023/5/16 11:05 AM
+ */
+@RestController
+@RequestMapping("manage/advertisement/user")
+@Slf4j
+@RequiredArgsConstructor
+public class CmsAdvertisementUserController {
+
+    private final HttpServletRequest request;
+
+    private final BeanSearcher beanSearcher;
+
+    @GetMapping
+    public Result<SearchResult<AdvertisementUser>> get() {
+        SearchResult<AdvertisementUser> searchResult = beanSearcher.search(AdvertisementUser.class,
+                MapUtils.flatBuilder(request.getParameterMap())
+                        .build());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(searchResult);
+    }
+}

+ 1 - 1
netflix-web/src/main/java/com/cyksj/web/controller/payment/OrderController.java

@@ -188,7 +188,7 @@ public class OrderController {
     public void prepayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
 
         String xml = IoKit.toString(request.getInputStream());
-        log.info("=== 基金会分发支付成功的回调: \n {}", xml);
+        log.info("=== 微信支付成功的回调: \n {}", xml);
 
         // 解析xml
         Map<String, String> map = Xmls.toMap(xml);

+ 1 - 1
netflix-web/src/main/java/com/cyksj/web/controller/register/RegisterController.java

@@ -98,7 +98,7 @@ public class RegisterController {
     public void prepayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
 
         String xml = IoKit.toString(request.getInputStream());
-        log.info("=== 基金会分发支付成功的回调: \n {}", xml);
+        log.info("=== 微信支付成功的回调: \n {}", xml);
 
         // 解析xml
         Map<String, String> map = Xmls.toMap(xml);

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
netflix-web/src/main/resources/application-dev.yml


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
netflix-web/src/main/resources/application-prd.yml


Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff