35 changed files with 3513 additions and 110 deletions
@ -0,0 +1,183 @@ |
|||
package com.ccsens.tall.bean.po; |
|||
|
|||
import java.io.Serializable; |
|||
import java.util.Date; |
|||
|
|||
public class SysWx implements Serializable { |
|||
private Long id; |
|||
|
|||
private Long userId; |
|||
|
|||
private String openId; |
|||
|
|||
private String unionId; |
|||
|
|||
private String nickname; |
|||
|
|||
private String headImgUrl; |
|||
|
|||
private Byte sex; |
|||
|
|||
private String province; |
|||
|
|||
private String city; |
|||
|
|||
private String country; |
|||
|
|||
private String language; |
|||
|
|||
private String privilege; |
|||
|
|||
private Date createdAt; |
|||
|
|||
private Date updatedAt; |
|||
|
|||
private Byte recStatus; |
|||
|
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
public Long getId() { |
|||
return id; |
|||
} |
|||
|
|||
public void setId(Long id) { |
|||
this.id = id; |
|||
} |
|||
|
|||
public Long getUserId() { |
|||
return userId; |
|||
} |
|||
|
|||
public void setUserId(Long userId) { |
|||
this.userId = userId; |
|||
} |
|||
|
|||
public String getOpenId() { |
|||
return openId; |
|||
} |
|||
|
|||
public void setOpenId(String openId) { |
|||
this.openId = openId == null ? null : openId.trim(); |
|||
} |
|||
|
|||
public String getUnionId() { |
|||
return unionId; |
|||
} |
|||
|
|||
public void setUnionId(String unionId) { |
|||
this.unionId = unionId == null ? null : unionId.trim(); |
|||
} |
|||
|
|||
public String getNickname() { |
|||
return nickname; |
|||
} |
|||
|
|||
public void setNickname(String nickname) { |
|||
this.nickname = nickname == null ? null : nickname.trim(); |
|||
} |
|||
|
|||
public String getHeadImgUrl() { |
|||
return headImgUrl; |
|||
} |
|||
|
|||
public void setHeadImgUrl(String headImgUrl) { |
|||
this.headImgUrl = headImgUrl == null ? null : headImgUrl.trim(); |
|||
} |
|||
|
|||
public Byte getSex() { |
|||
return sex; |
|||
} |
|||
|
|||
public void setSex(Byte sex) { |
|||
this.sex = sex; |
|||
} |
|||
|
|||
public String getProvince() { |
|||
return province; |
|||
} |
|||
|
|||
public void setProvince(String province) { |
|||
this.province = province == null ? null : province.trim(); |
|||
} |
|||
|
|||
public String getCity() { |
|||
return city; |
|||
} |
|||
|
|||
public void setCity(String city) { |
|||
this.city = city == null ? null : city.trim(); |
|||
} |
|||
|
|||
public String getCountry() { |
|||
return country; |
|||
} |
|||
|
|||
public void setCountry(String country) { |
|||
this.country = country == null ? null : country.trim(); |
|||
} |
|||
|
|||
public String getLanguage() { |
|||
return language; |
|||
} |
|||
|
|||
public void setLanguage(String language) { |
|||
this.language = language == null ? null : language.trim(); |
|||
} |
|||
|
|||
public String getPrivilege() { |
|||
return privilege; |
|||
} |
|||
|
|||
public void setPrivilege(String privilege) { |
|||
this.privilege = privilege == null ? null : privilege.trim(); |
|||
} |
|||
|
|||
public Date getCreatedAt() { |
|||
return createdAt; |
|||
} |
|||
|
|||
public void setCreatedAt(Date createdAt) { |
|||
this.createdAt = createdAt; |
|||
} |
|||
|
|||
public Date getUpdatedAt() { |
|||
return updatedAt; |
|||
} |
|||
|
|||
public void setUpdatedAt(Date updatedAt) { |
|||
this.updatedAt = updatedAt; |
|||
} |
|||
|
|||
public Byte getRecStatus() { |
|||
return recStatus; |
|||
} |
|||
|
|||
public void setRecStatus(Byte recStatus) { |
|||
this.recStatus = recStatus; |
|||
} |
|||
|
|||
@Override |
|||
public String toString() { |
|||
StringBuilder sb = new StringBuilder(); |
|||
sb.append(getClass().getSimpleName()); |
|||
sb.append(" ["); |
|||
sb.append("Hash = ").append(hashCode()); |
|||
sb.append(", id=").append(id); |
|||
sb.append(", userId=").append(userId); |
|||
sb.append(", openId=").append(openId); |
|||
sb.append(", unionId=").append(unionId); |
|||
sb.append(", nickname=").append(nickname); |
|||
sb.append(", headImgUrl=").append(headImgUrl); |
|||
sb.append(", sex=").append(sex); |
|||
sb.append(", province=").append(province); |
|||
sb.append(", city=").append(city); |
|||
sb.append(", country=").append(country); |
|||
sb.append(", language=").append(language); |
|||
sb.append(", privilege=").append(privilege); |
|||
sb.append(", createdAt=").append(createdAt); |
|||
sb.append(", updatedAt=").append(updatedAt); |
|||
sb.append(", recStatus=").append(recStatus); |
|||
sb.append("]"); |
|||
return sb.toString(); |
|||
} |
|||
} |
File diff suppressed because it is too large
@ -0,0 +1,9 @@ |
|||
package com.ccsens.tall.persist.dao; |
|||
|
|||
import com.ccsens.tall.persist.mapper.SysWxMapper; |
|||
import org.springframework.stereotype.Repository; |
|||
|
|||
@Repository |
|||
public interface SysWxDao extends SysWxMapper { |
|||
|
|||
} |
@ -0,0 +1,30 @@ |
|||
package com.ccsens.tall.persist.mapper; |
|||
|
|||
import com.ccsens.tall.bean.po.SysWx; |
|||
import com.ccsens.tall.bean.po.SysWxExample; |
|||
import java.util.List; |
|||
import org.apache.ibatis.annotations.Param; |
|||
|
|||
public interface SysWxMapper { |
|||
long countByExample(SysWxExample example); |
|||
|
|||
int deleteByExample(SysWxExample example); |
|||
|
|||
int deleteByPrimaryKey(Long id); |
|||
|
|||
int insert(SysWx record); |
|||
|
|||
int insertSelective(SysWx record); |
|||
|
|||
List<SysWx> selectByExample(SysWxExample example); |
|||
|
|||
SysWx selectByPrimaryKey(Long id); |
|||
|
|||
int updateByExampleSelective(@Param("record") SysWx record, @Param("example") SysWxExample example); |
|||
|
|||
int updateByExample(@Param("record") SysWx record, @Param("example") SysWxExample example); |
|||
|
|||
int updateByPrimaryKeySelective(SysWx record); |
|||
|
|||
int updateByPrimaryKey(SysWx record); |
|||
} |
@ -0,0 +1,370 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
|||
<mapper namespace="com.ccsens.tall.persist.mapper.SysWxMapper"> |
|||
<resultMap id="BaseResultMap" type="com.ccsens.tall.bean.po.SysWx"> |
|||
<id column="id" jdbcType="BIGINT" property="id" /> |
|||
<result column="user_id" jdbcType="BIGINT" property="userId" /> |
|||
<result column="open_id" jdbcType="VARCHAR" property="openId" /> |
|||
<result column="union_id" jdbcType="VARCHAR" property="unionId" /> |
|||
<result column="nickname" jdbcType="VARCHAR" property="nickname" /> |
|||
<result column="head_img_url" jdbcType="VARCHAR" property="headImgUrl" /> |
|||
<result column="sex" jdbcType="TINYINT" property="sex" /> |
|||
<result column="province" jdbcType="VARCHAR" property="province" /> |
|||
<result column="city" jdbcType="VARCHAR" property="city" /> |
|||
<result column="country" jdbcType="VARCHAR" property="country" /> |
|||
<result column="language" jdbcType="VARCHAR" property="language" /> |
|||
<result column="privilege" jdbcType="VARCHAR" property="privilege" /> |
|||
<result column="created_at" jdbcType="TIMESTAMP" property="createdAt" /> |
|||
<result column="updated_at" jdbcType="TIMESTAMP" property="updatedAt" /> |
|||
<result column="rec_status" jdbcType="TINYINT" property="recStatus" /> |
|||
</resultMap> |
|||
<sql id="Example_Where_Clause"> |
|||
<where> |
|||
<foreach collection="oredCriteria" item="criteria" separator="or"> |
|||
<if test="criteria.valid"> |
|||
<trim prefix="(" prefixOverrides="and" suffix=")"> |
|||
<foreach collection="criteria.criteria" item="criterion"> |
|||
<choose> |
|||
<when test="criterion.noValue"> |
|||
and ${criterion.condition} |
|||
</when> |
|||
<when test="criterion.singleValue"> |
|||
and ${criterion.condition} #{criterion.value} |
|||
</when> |
|||
<when test="criterion.betweenValue"> |
|||
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} |
|||
</when> |
|||
<when test="criterion.listValue"> |
|||
and ${criterion.condition} |
|||
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=","> |
|||
#{listItem} |
|||
</foreach> |
|||
</when> |
|||
</choose> |
|||
</foreach> |
|||
</trim> |
|||
</if> |
|||
</foreach> |
|||
</where> |
|||
</sql> |
|||
<sql id="Update_By_Example_Where_Clause"> |
|||
<where> |
|||
<foreach collection="example.oredCriteria" item="criteria" separator="or"> |
|||
<if test="criteria.valid"> |
|||
<trim prefix="(" prefixOverrides="and" suffix=")"> |
|||
<foreach collection="criteria.criteria" item="criterion"> |
|||
<choose> |
|||
<when test="criterion.noValue"> |
|||
and ${criterion.condition} |
|||
</when> |
|||
<when test="criterion.singleValue"> |
|||
and ${criterion.condition} #{criterion.value} |
|||
</when> |
|||
<when test="criterion.betweenValue"> |
|||
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} |
|||
</when> |
|||
<when test="criterion.listValue"> |
|||
and ${criterion.condition} |
|||
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=","> |
|||
#{listItem} |
|||
</foreach> |
|||
</when> |
|||
</choose> |
|||
</foreach> |
|||
</trim> |
|||
</if> |
|||
</foreach> |
|||
</where> |
|||
</sql> |
|||
<sql id="Base_Column_List"> |
|||
id, user_id, open_id, union_id, nickname, head_img_url, sex, province, city, country, |
|||
language, privilege, created_at, updated_at, rec_status |
|||
</sql> |
|||
<select id="selectByExample" parameterType="com.ccsens.tall.bean.po.SysWxExample" resultMap="BaseResultMap"> |
|||
select |
|||
<if test="distinct"> |
|||
distinct |
|||
</if> |
|||
<include refid="Base_Column_List" /> |
|||
from t_sys_wx |
|||
<if test="_parameter != null"> |
|||
<include refid="Example_Where_Clause" /> |
|||
</if> |
|||
<if test="orderByClause != null"> |
|||
order by ${orderByClause} |
|||
</if> |
|||
</select> |
|||
<select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap"> |
|||
select |
|||
<include refid="Base_Column_List" /> |
|||
from t_sys_wx |
|||
where id = #{id,jdbcType=BIGINT} |
|||
</select> |
|||
<delete id="deleteByPrimaryKey" parameterType="java.lang.Long"> |
|||
delete from t_sys_wx |
|||
where id = #{id,jdbcType=BIGINT} |
|||
</delete> |
|||
<delete id="deleteByExample" parameterType="com.ccsens.tall.bean.po.SysWxExample"> |
|||
delete from t_sys_wx |
|||
<if test="_parameter != null"> |
|||
<include refid="Example_Where_Clause" /> |
|||
</if> |
|||
</delete> |
|||
<insert id="insert" parameterType="com.ccsens.tall.bean.po.SysWx"> |
|||
insert into t_sys_wx (id, user_id, open_id, |
|||
union_id, nickname, head_img_url, |
|||
sex, province, city, |
|||
country, language, privilege, |
|||
created_at, updated_at, rec_status |
|||
) |
|||
values (#{id,jdbcType=BIGINT}, #{userId,jdbcType=BIGINT}, #{openId,jdbcType=VARCHAR}, |
|||
#{unionId,jdbcType=VARCHAR}, #{nickname,jdbcType=VARCHAR}, #{headImgUrl,jdbcType=VARCHAR}, |
|||
#{sex,jdbcType=TINYINT}, #{province,jdbcType=VARCHAR}, #{city,jdbcType=VARCHAR}, |
|||
#{country,jdbcType=VARCHAR}, #{language,jdbcType=VARCHAR}, #{privilege,jdbcType=VARCHAR}, |
|||
#{createdAt,jdbcType=TIMESTAMP}, #{updatedAt,jdbcType=TIMESTAMP}, #{recStatus,jdbcType=TINYINT} |
|||
) |
|||
</insert> |
|||
<insert id="insertSelective" parameterType="com.ccsens.tall.bean.po.SysWx"> |
|||
insert into t_sys_wx |
|||
<trim prefix="(" suffix=")" suffixOverrides=","> |
|||
<if test="id != null"> |
|||
id, |
|||
</if> |
|||
<if test="userId != null"> |
|||
user_id, |
|||
</if> |
|||
<if test="openId != null"> |
|||
open_id, |
|||
</if> |
|||
<if test="unionId != null"> |
|||
union_id, |
|||
</if> |
|||
<if test="nickname != null"> |
|||
nickname, |
|||
</if> |
|||
<if test="headImgUrl != null"> |
|||
head_img_url, |
|||
</if> |
|||
<if test="sex != null"> |
|||
sex, |
|||
</if> |
|||
<if test="province != null"> |
|||
province, |
|||
</if> |
|||
<if test="city != null"> |
|||
city, |
|||
</if> |
|||
<if test="country != null"> |
|||
country, |
|||
</if> |
|||
<if test="language != null"> |
|||
language, |
|||
</if> |
|||
<if test="privilege != null"> |
|||
privilege, |
|||
</if> |
|||
<if test="createdAt != null"> |
|||
created_at, |
|||
</if> |
|||
<if test="updatedAt != null"> |
|||
updated_at, |
|||
</if> |
|||
<if test="recStatus != null"> |
|||
rec_status, |
|||
</if> |
|||
</trim> |
|||
<trim prefix="values (" suffix=")" suffixOverrides=","> |
|||
<if test="id != null"> |
|||
#{id,jdbcType=BIGINT}, |
|||
</if> |
|||
<if test="userId != null"> |
|||
#{userId,jdbcType=BIGINT}, |
|||
</if> |
|||
<if test="openId != null"> |
|||
#{openId,jdbcType=VARCHAR}, |
|||
</if> |
|||
<if test="unionId != null"> |
|||
#{unionId,jdbcType=VARCHAR}, |
|||
</if> |
|||
<if test="nickname != null"> |
|||
#{nickname,jdbcType=VARCHAR}, |
|||
</if> |
|||
<if test="headImgUrl != null"> |
|||
#{headImgUrl,jdbcType=VARCHAR}, |
|||
</if> |
|||
<if test="sex != null"> |
|||
#{sex,jdbcType=TINYINT}, |
|||
</if> |
|||
<if test="province != null"> |
|||
#{province,jdbcType=VARCHAR}, |
|||
</if> |
|||
<if test="city != null"> |
|||
#{city,jdbcType=VARCHAR}, |
|||
</if> |
|||
<if test="country != null"> |
|||
#{country,jdbcType=VARCHAR}, |
|||
</if> |
|||
<if test="language != null"> |
|||
#{language,jdbcType=VARCHAR}, |
|||
</if> |
|||
<if test="privilege != null"> |
|||
#{privilege,jdbcType=VARCHAR}, |
|||
</if> |
|||
<if test="createdAt != null"> |
|||
#{createdAt,jdbcType=TIMESTAMP}, |
|||
</if> |
|||
<if test="updatedAt != null"> |
|||
#{updatedAt,jdbcType=TIMESTAMP}, |
|||
</if> |
|||
<if test="recStatus != null"> |
|||
#{recStatus,jdbcType=TINYINT}, |
|||
</if> |
|||
</trim> |
|||
</insert> |
|||
<select id="countByExample" parameterType="com.ccsens.tall.bean.po.SysWxExample" resultType="java.lang.Long"> |
|||
select count(*) from t_sys_wx |
|||
<if test="_parameter != null"> |
|||
<include refid="Example_Where_Clause" /> |
|||
</if> |
|||
</select> |
|||
<update id="updateByExampleSelective" parameterType="map"> |
|||
update t_sys_wx |
|||
<set> |
|||
<if test="record.id != null"> |
|||
id = #{record.id,jdbcType=BIGINT}, |
|||
</if> |
|||
<if test="record.userId != null"> |
|||
user_id = #{record.userId,jdbcType=BIGINT}, |
|||
</if> |
|||
<if test="record.openId != null"> |
|||
open_id = #{record.openId,jdbcType=VARCHAR}, |
|||
</if> |
|||
<if test="record.unionId != null"> |
|||
union_id = #{record.unionId,jdbcType=VARCHAR}, |
|||
</if> |
|||
<if test="record.nickname != null"> |
|||
nickname = #{record.nickname,jdbcType=VARCHAR}, |
|||
</if> |
|||
<if test="record.headImgUrl != null"> |
|||
head_img_url = #{record.headImgUrl,jdbcType=VARCHAR}, |
|||
</if> |
|||
<if test="record.sex != null"> |
|||
sex = #{record.sex,jdbcType=TINYINT}, |
|||
</if> |
|||
<if test="record.province != null"> |
|||
province = #{record.province,jdbcType=VARCHAR}, |
|||
</if> |
|||
<if test="record.city != null"> |
|||
city = #{record.city,jdbcType=VARCHAR}, |
|||
</if> |
|||
<if test="record.country != null"> |
|||
country = #{record.country,jdbcType=VARCHAR}, |
|||
</if> |
|||
<if test="record.language != null"> |
|||
language = #{record.language,jdbcType=VARCHAR}, |
|||
</if> |
|||
<if test="record.privilege != null"> |
|||
privilege = #{record.privilege,jdbcType=VARCHAR}, |
|||
</if> |
|||
<if test="record.createdAt != null"> |
|||
created_at = #{record.createdAt,jdbcType=TIMESTAMP}, |
|||
</if> |
|||
<if test="record.updatedAt != null"> |
|||
updated_at = #{record.updatedAt,jdbcType=TIMESTAMP}, |
|||
</if> |
|||
<if test="record.recStatus != null"> |
|||
rec_status = #{record.recStatus,jdbcType=TINYINT}, |
|||
</if> |
|||
</set> |
|||
<if test="_parameter != null"> |
|||
<include refid="Update_By_Example_Where_Clause" /> |
|||
</if> |
|||
</update> |
|||
<update id="updateByExample" parameterType="map"> |
|||
update t_sys_wx |
|||
set id = #{record.id,jdbcType=BIGINT}, |
|||
user_id = #{record.userId,jdbcType=BIGINT}, |
|||
open_id = #{record.openId,jdbcType=VARCHAR}, |
|||
union_id = #{record.unionId,jdbcType=VARCHAR}, |
|||
nickname = #{record.nickname,jdbcType=VARCHAR}, |
|||
head_img_url = #{record.headImgUrl,jdbcType=VARCHAR}, |
|||
sex = #{record.sex,jdbcType=TINYINT}, |
|||
province = #{record.province,jdbcType=VARCHAR}, |
|||
city = #{record.city,jdbcType=VARCHAR}, |
|||
country = #{record.country,jdbcType=VARCHAR}, |
|||
language = #{record.language,jdbcType=VARCHAR}, |
|||
privilege = #{record.privilege,jdbcType=VARCHAR}, |
|||
created_at = #{record.createdAt,jdbcType=TIMESTAMP}, |
|||
updated_at = #{record.updatedAt,jdbcType=TIMESTAMP}, |
|||
rec_status = #{record.recStatus,jdbcType=TINYINT} |
|||
<if test="_parameter != null"> |
|||
<include refid="Update_By_Example_Where_Clause" /> |
|||
</if> |
|||
</update> |
|||
<update id="updateByPrimaryKeySelective" parameterType="com.ccsens.tall.bean.po.SysWx"> |
|||
update t_sys_wx |
|||
<set> |
|||
<if test="userId != null"> |
|||
user_id = #{userId,jdbcType=BIGINT}, |
|||
</if> |
|||
<if test="openId != null"> |
|||
open_id = #{openId,jdbcType=VARCHAR}, |
|||
</if> |
|||
<if test="unionId != null"> |
|||
union_id = #{unionId,jdbcType=VARCHAR}, |
|||
</if> |
|||
<if test="nickname != null"> |
|||
nickname = #{nickname,jdbcType=VARCHAR}, |
|||
</if> |
|||
<if test="headImgUrl != null"> |
|||
head_img_url = #{headImgUrl,jdbcType=VARCHAR}, |
|||
</if> |
|||
<if test="sex != null"> |
|||
sex = #{sex,jdbcType=TINYINT}, |
|||
</if> |
|||
<if test="province != null"> |
|||
province = #{province,jdbcType=VARCHAR}, |
|||
</if> |
|||
<if test="city != null"> |
|||
city = #{city,jdbcType=VARCHAR}, |
|||
</if> |
|||
<if test="country != null"> |
|||
country = #{country,jdbcType=VARCHAR}, |
|||
</if> |
|||
<if test="language != null"> |
|||
language = #{language,jdbcType=VARCHAR}, |
|||
</if> |
|||
<if test="privilege != null"> |
|||
privilege = #{privilege,jdbcType=VARCHAR}, |
|||
</if> |
|||
<if test="createdAt != null"> |
|||
created_at = #{createdAt,jdbcType=TIMESTAMP}, |
|||
</if> |
|||
<if test="updatedAt != null"> |
|||
updated_at = #{updatedAt,jdbcType=TIMESTAMP}, |
|||
</if> |
|||
<if test="recStatus != null"> |
|||
rec_status = #{recStatus,jdbcType=TINYINT}, |
|||
</if> |
|||
</set> |
|||
where id = #{id,jdbcType=BIGINT} |
|||
</update> |
|||
<update id="updateByPrimaryKey" parameterType="com.ccsens.tall.bean.po.SysWx"> |
|||
update t_sys_wx |
|||
set user_id = #{userId,jdbcType=BIGINT}, |
|||
open_id = #{openId,jdbcType=VARCHAR}, |
|||
union_id = #{unionId,jdbcType=VARCHAR}, |
|||
nickname = #{nickname,jdbcType=VARCHAR}, |
|||
head_img_url = #{headImgUrl,jdbcType=VARCHAR}, |
|||
sex = #{sex,jdbcType=TINYINT}, |
|||
province = #{province,jdbcType=VARCHAR}, |
|||
city = #{city,jdbcType=VARCHAR}, |
|||
country = #{country,jdbcType=VARCHAR}, |
|||
language = #{language,jdbcType=VARCHAR}, |
|||
privilege = #{privilege,jdbcType=VARCHAR}, |
|||
created_at = #{createdAt,jdbcType=TIMESTAMP}, |
|||
updated_at = #{updatedAt,jdbcType=TIMESTAMP}, |
|||
rec_status = #{recStatus,jdbcType=TINYINT} |
|||
where id = #{id,jdbcType=BIGINT} |
|||
</update> |
|||
</mapper> |
@ -0,0 +1,151 @@ |
|||
package com.ccsens.util.bean.wx.dto; |
|||
|
|||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; |
|||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; |
|||
import lombok.Data; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* @author __zHangSan |
|||
*/ |
|||
@Data |
|||
@JacksonXmlRootElement(localName = "xml") |
|||
public class WxGzhAction { |
|||
@Data |
|||
private static class ScanCodeInfo{ |
|||
@JacksonXmlProperty(localName = "ScanType") |
|||
private String scanType; |
|||
@JacksonXmlProperty(localName = "ScanResult") |
|||
private String scanResult; |
|||
}; |
|||
|
|||
@Data |
|||
private static class SendPicsInfo{ |
|||
@Data |
|||
private static class Item{ |
|||
@JacksonXmlProperty(localName = "PicMd5Sum") |
|||
private String picMd5Sum; |
|||
} |
|||
@JacksonXmlProperty(localName = "Count") |
|||
private Integer count; |
|||
@JacksonXmlProperty(localName = "PicList") |
|||
private List<Item> picList; |
|||
} |
|||
|
|||
@Data |
|||
private static class SendLocationInfo{ |
|||
@JacksonXmlProperty(localName = "Location_X") |
|||
private String x; |
|||
@JacksonXmlProperty(localName = "Location_Y") |
|||
private String y; |
|||
@JacksonXmlProperty(localName = "Scale") |
|||
private String scale; |
|||
@JacksonXmlProperty(localName = "Label") |
|||
private String label; |
|||
@JacksonXmlProperty(localName = "Poiname") |
|||
private String poiname; |
|||
} |
|||
|
|||
@JacksonXmlProperty(localName = "FromUserName") |
|||
private String openId; |
|||
@JacksonXmlProperty(localName = "ToUserName") |
|||
private String gzhId; |
|||
@JacksonXmlProperty(localName = "CreateTime") |
|||
private Long createTime; |
|||
@JacksonXmlProperty(localName = "MsgType") |
|||
private String msgType; |
|||
|
|||
/** |
|||
* MsgType: Text (Content,MsgId) |
|||
*/ |
|||
@JacksonXmlProperty(localName = "Content") |
|||
private String content; |
|||
@JacksonXmlProperty(localName = "MsgId") |
|||
private String msgId; |
|||
/** |
|||
* MsgType: image (PicUrl,MediaId,MsgId) |
|||
*/ |
|||
@JacksonXmlProperty(localName = "PicUrl") |
|||
private String picUrl; |
|||
@JacksonXmlProperty(localName = "MediaId") |
|||
private String mediaId; |
|||
/** |
|||
* MsgType: voice (MediaId,Format,MsgId) |
|||
* Recognition: 开通语音识别后生效 |
|||
*/ |
|||
@JacksonXmlProperty(localName = "Format") |
|||
private String format; |
|||
@JacksonXmlProperty(localName = "Recognition") |
|||
private String recognition; |
|||
|
|||
/** |
|||
* MsgType: video/shortvideo(MediaId,ThumbMediaId,MsgId) |
|||
*/ |
|||
@JacksonXmlProperty(localName = "ThumbMediaId") |
|||
private String thumbMediaId; |
|||
/** |
|||
* MsgType: location(Location_x,Location_y,Scale,Label,MsgId) |
|||
*/ |
|||
@JacksonXmlProperty(localName = "Location_X") |
|||
private String x; |
|||
@JacksonXmlProperty(localName = "Location_Y") |
|||
private String y; |
|||
@JacksonXmlProperty(localName = "Scale") |
|||
private String scale; |
|||
@JacksonXmlProperty(localName = "Label") |
|||
private String label; |
|||
/** |
|||
* MsgType: link(Title,Description,Url,MsgId) |
|||
*/ |
|||
@JacksonXmlProperty(localName = "Title") |
|||
private String title; |
|||
@JacksonXmlProperty(localName = "Description") |
|||
private String description; |
|||
@JacksonXmlProperty(localName = "Url") |
|||
private String url; |
|||
|
|||
/** |
|||
* MsgType: event |
|||
*/ |
|||
@JacksonXmlProperty(localName = "Event") |
|||
private String event; |
|||
@JacksonXmlProperty(localName = "EventKey") |
|||
private String eventKey; |
|||
|
|||
/** |
|||
* Event: subscribe/SCAN |
|||
*/ |
|||
@JacksonXmlProperty(localName = "Ticket") |
|||
private String ticket; |
|||
/** |
|||
* Event: Location |
|||
*/ |
|||
@JacksonXmlProperty(localName = "Latitude") |
|||
private String latitude; |
|||
@JacksonXmlProperty(localName = "Longitude") |
|||
private String longitude; |
|||
@JacksonXmlProperty(localName = "Precision") |
|||
private String precision; |
|||
|
|||
/** |
|||
* Event: VIEW/view_miniprogram |
|||
*/ |
|||
@JacksonXmlProperty(localName = "MenuId") |
|||
private String menuId; |
|||
/** |
|||
* Event: scancode_push/scancode_waitmsg |
|||
*/ |
|||
@JacksonXmlProperty(localName = "ScanCodeInfo") |
|||
private ScanCodeInfo scanCodeInfo; |
|||
/** |
|||
* Event: pic_sysphoto/pic_photo_or_album/pic_weixin |
|||
*/ |
|||
@JacksonXmlProperty(localName = "SendPicsInfo") |
|||
private SendPicsInfo sendPicsInfo; |
|||
/** |
|||
* Event: location_select |
|||
*/ |
|||
@JacksonXmlProperty(localName = "SendLocationInfo") |
|||
private SendLocationInfo sendLocationInfo; |
|||
} |
@ -0,0 +1,18 @@ |
|||
package com.ccsens.util.bean.wx.po; |
|||
|
|||
import com.fasterxml.jackson.annotation.JsonIgnore; |
|||
import com.fasterxml.jackson.annotation.JsonProperty; |
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* @author __zHangSan |
|||
*/ |
|||
@Data |
|||
public class WxAccessToken extends WxBaseEntity{ |
|||
@JsonProperty("access_token") |
|||
private String accessToken; |
|||
@JsonProperty("expires_in") |
|||
private Long expiresIn; |
|||
@JsonIgnore |
|||
private Long createdAt; |
|||
} |
@ -0,0 +1,12 @@ |
|||
package com.ccsens.util.bean.wx.po; |
|||
|
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* @author __zHangSan |
|||
*/ |
|||
@Data |
|||
public class WxBaseEntity { |
|||
private Integer errcode; |
|||
private String errmsg; |
|||
} |
@ -0,0 +1,23 @@ |
|||
package com.ccsens.util.bean.wx.po; |
|||
|
|||
import lombok.Getter; |
|||
import lombok.Setter; |
|||
|
|||
/** |
|||
* @author __zHangSan |
|||
*/ |
|||
|
|||
public enum WxGzhAuthType { |
|||
//基本授权类型,静默,只能获取openId
|
|||
SNSAPI_BASE("snsapi_base"), |
|||
//信息授权类型,弹出提示框,可以获取openId,unionId,nickanme,city等用户信息
|
|||
SNSAPI_USERINFO("snsapi_userinfo"); |
|||
|
|||
@Getter |
|||
@Setter |
|||
private String text; |
|||
|
|||
private WxGzhAuthType(String text){ |
|||
this.text = text; |
|||
} |
|||
} |
@ -0,0 +1,97 @@ |
|||
package com.ccsens.util.bean.wx.po; |
|||
|
|||
import cn.hutool.core.collection.CollectionUtil; |
|||
import com.fasterxml.jackson.annotation.JsonProperty; |
|||
import com.fasterxml.jackson.annotation.JsonValue; |
|||
import lombok.Builder; |
|||
import lombok.Data; |
|||
import lombok.Getter; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* @author __zHangSan |
|||
*/ |
|||
@Data |
|||
public class WxGzhMenu { |
|||
public enum ButtonType{ |
|||
//点击推事件
|
|||
CLICK("click"), |
|||
//跳转URL
|
|||
VIEW("view"), |
|||
//小程序
|
|||
MINIPROGRAM("miniprogram"), |
|||
//扫码推事件
|
|||
SCANCODE_PUSH("scancode_push"), |
|||
//扫码推事件且弹出“消息接收中”提示框
|
|||
SCANCODE_WAITMSG("scancode_waitmsg"), |
|||
//弹出系统拍照发图
|
|||
PIC_SYSPHOTO("pic_sysphoto"), |
|||
//弹出拍照或者相册发图
|
|||
PIC_PHOTO_OR_ALBUM("pic_photo_or_album"), |
|||
//弹出微信相册发图器
|
|||
PIC_WEIXIN("pic_weixin"), |
|||
//弹出地理位置选择器
|
|||
LOCATION_SELECT("location_select"), |
|||
//下发消息(除文本消息)
|
|||
MEDIA_ID("media_id"), |
|||
//跳转图文消息URL
|
|||
VIEW_LIMITED("view_limited"); |
|||
|
|||
@JsonValue |
|||
private String text; |
|||
|
|||
ButtonType(String text){ |
|||
this.text = text; |
|||
} |
|||
} |
|||
@Builder(toBuilder = true) |
|||
@Getter |
|||
public static class Button{ |
|||
/** |
|||
* 必须 |
|||
*/ |
|||
private ButtonType type; |
|||
/** |
|||
* 必须 |
|||
*/ |
|||
private String name; |
|||
/** |
|||
* click等点击类型必须 |
|||
*/ |
|||
private String key; |
|||
/** |
|||
* view、miniprogram类型必须 |
|||
*/ |
|||
private String url; |
|||
/** |
|||
* media_id类型和view_limited类型必须 |
|||
*/ |
|||
@JsonProperty("media_id") |
|||
private String mediaId; |
|||
/** |
|||
* miniprogram类型必须 |
|||
*/ |
|||
private String appid; |
|||
private String pagepath; |
|||
/** |
|||
* optional |
|||
*/ |
|||
@JsonProperty("sub_button") |
|||
private List<Button> subButton; |
|||
} |
|||
@JsonProperty("button") |
|||
private List<Button> buttons; |
|||
|
|||
public static WxGzhMenu newInstance(){ |
|||
return new WxGzhMenu(); |
|||
} |
|||
|
|||
public WxGzhMenu add(Button button){ |
|||
if(buttons == null){ |
|||
buttons = CollectionUtil.newArrayList(); |
|||
} |
|||
buttons.add(button); |
|||
return this; |
|||
} |
|||
} |
@ -0,0 +1,53 @@ |
|||
package com.ccsens.util.bean.wx.po; |
|||
|
|||
import lombok.Getter; |
|||
import lombok.Setter; |
|||
|
|||
/** |
|||
* @author __zHangSan |
|||
*/ |
|||
public enum WxGzhMsgEvent { |
|||
/** |
|||
* 关注/取消关注事件 |
|||
*/ |
|||
SUBSCRIBE("subscribe"),UNSUBSCRIBE("unsubscribe"), |
|||
/** |
|||
* 扫描带参数(公众号)二维码事件 |
|||
* 未关注:产生Event: SUBSCRIBE EventKey: qrscene_xxx |
|||
* 已关注:产生Event: Scan EventKey: scene_value |
|||
*/ |
|||
SCAN("SCAN"), |
|||
/** |
|||
* 上报地理位置事件 |
|||
*/ |
|||
LOCATION("LOCATION"), |
|||
/** |
|||
* 自定义菜单事件 |
|||
*/ |
|||
//点击菜单拉取消息时的事件推送
|
|||
CLICK("CLICK"), |
|||
//点击菜单跳转链接时的事件推送
|
|||
VIEW("VIEW"), |
|||
//扫码推事件的事件推送
|
|||
SCANCODE_PUSH("scancode_push"), |
|||
//扫码推事件且弹出“消息接收中”提示框的事件推送
|
|||
SCANCODE_WAITMSG("scancode_waitmsg"), |
|||
//弹出系统拍照发图的事件推送
|
|||
PIC_SYSPHOTO("pic_sysphoto"), |
|||
//弹出拍照或者相册发图的事件推送
|
|||
PIC_PHOTO_OR_ALBUM("pic_photo_or_album"), |
|||
//弹出微信相册发图器的事件推送
|
|||
PIC_WEIXIN("pic_weixin"), |
|||
//弹出地理位置选择器的事件推送
|
|||
LOCATION_SELECT("location_select"), |
|||
//点击菜单跳转小程序的事件推送
|
|||
VIEW_MINIPROGRAM("view_miniprogram"); |
|||
|
|||
@Getter |
|||
@Setter |
|||
private String text; |
|||
|
|||
private WxGzhMsgEvent(String text){ |
|||
this.text = text; |
|||
} |
|||
} |
@ -0,0 +1,34 @@ |
|||
package com.ccsens.util.bean.wx.po; |
|||
|
|||
import lombok.Getter; |
|||
import lombok.Setter; |
|||
|
|||
/** |
|||
* @author __zHangSan |
|||
*/ |
|||
public enum WxGzhMsgType { |
|||
/** |
|||
* 1.普通消息 |
|||
*/ |
|||
//1.1 文本消息
|
|||
TEXT("text"), |
|||
IMAGE("image"), |
|||
VOICE("voice"), |
|||
VIDEO("video"), |
|||
SHORTVIDEO("shortvideo"), |
|||
LOCATION("location"), |
|||
LINK("link"), |
|||
|
|||
/** |
|||
* 2.事件推送 |
|||
*/ |
|||
EVENT("event"); |
|||
|
|||
@Getter |
|||
@Setter |
|||
private String text; |
|||
|
|||
private WxGzhMsgType(String text){ |
|||
this.text = text; |
|||
} |
|||
} |
@ -0,0 +1,26 @@ |
|||
package com.ccsens.util.bean.wx.po; |
|||
|
|||
import com.fasterxml.jackson.annotation.JsonIgnore; |
|||
import com.fasterxml.jackson.annotation.JsonProperty; |
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* @author __zHangSan |
|||
*/ |
|||
@Data |
|||
public class WxOauth2AccessToken extends WxBaseEntity{ |
|||
@JsonProperty("access_token") |
|||
private String accessToken; |
|||
@JsonProperty("expires_in") |
|||
private int expiresIn; |
|||
@JsonProperty("refresh_token") |
|||
private String refreshToken; |
|||
@JsonProperty("openid") |
|||
private String openId; |
|||
@JsonProperty("scope") |
|||
private String scope; |
|||
@JsonProperty("unionid") |
|||
private String unionId; |
|||
@JsonIgnore |
|||
private Long createdAt; |
|||
} |
@ -0,0 +1,42 @@ |
|||
package com.ccsens.util.bean.wx.po; |
|||
|
|||
import com.fasterxml.jackson.annotation.JsonProperty; |
|||
import lombok.Data; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* @author __zHangSan |
|||
*/ |
|||
@Data |
|||
public class WxOauth2UserInfo extends WxBaseEntity{ |
|||
@JsonProperty("openid") |
|||
private String openId; |
|||
|
|||
@JsonProperty("nickname") |
|||
private String nickname; |
|||
|
|||
@JsonProperty("sex") |
|||
private int sex; |
|||
|
|||
@JsonProperty("province") |
|||
private String province; |
|||
|
|||
@JsonProperty("city") |
|||
private String city; |
|||
|
|||
@JsonProperty("country") |
|||
private String country; |
|||
|
|||
@JsonProperty("headimgurl") |
|||
private String headImgUrl; |
|||
|
|||
@JsonProperty("privilege") |
|||
private List<String> privilegeList; |
|||
|
|||
@JsonProperty("unionid") |
|||
private String unionId; |
|||
|
|||
@JsonProperty("language") |
|||
private String language; |
|||
} |
@ -0,0 +1,21 @@ |
|||
package com.ccsens.util.bean.wx.po; |
|||
|
|||
import com.fasterxml.jackson.annotation.JsonValue; |
|||
|
|||
/** |
|||
* @author __zHangSan |
|||
*/ |
|||
|
|||
public enum WxOperation { |
|||
/** |
|||
* 创建公众号底部菜单 |
|||
*/ |
|||
CREATE_MENU("CreateMenu"); |
|||
|
|||
@JsonValue |
|||
private String text; |
|||
|
|||
WxOperation(String text){ |
|||
this.text = text; |
|||
} |
|||
} |
@ -0,0 +1,16 @@ |
|||
package com.ccsens.util.exception; |
|||
|
|||
/** |
|||
* @author __zHangSan |
|||
*/ |
|||
public class BusinessException extends BaseException { |
|||
private String type = "BusinessError"; |
|||
|
|||
public BusinessException(){ |
|||
|
|||
} |
|||
|
|||
public BusinessException(Integer errcode, String errmsg){ |
|||
super(errcode,errmsg); |
|||
} |
|||
} |
@ -0,0 +1,19 @@ |
|||
package com.ccsens.util.exception; |
|||
|
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* @author __zHangSan |
|||
*/ |
|||
@Data |
|||
public class WxException extends BaseException{ |
|||
private String type = "WxError"; |
|||
|
|||
public WxException(){ |
|||
|
|||
} |
|||
|
|||
public WxException(Integer errcode, String errmsg){ |
|||
super(errcode,errmsg); |
|||
} |
|||
} |
@ -0,0 +1,300 @@ |
|||
package com.ccsens.util.wx; |
|||
|
|||
import cn.hutool.core.lang.Console; |
|||
import cn.hutool.core.util.StrUtil; |
|||
import cn.hutool.core.util.URLUtil; |
|||
import cn.hutool.http.HttpRequest; |
|||
|
|||
import com.ccsens.util.DateUtil; |
|||
import com.ccsens.util.JacksonUtil; |
|||
import com.ccsens.util.WebConstant; |
|||
import com.ccsens.util.bean.wx.po.*; |
|||
import com.ccsens.util.exception.BaseException; |
|||
import com.ccsens.util.exception.BusinessException; |
|||
import com.ccsens.util.exception.WxException; |
|||
import com.fasterxml.jackson.core.JsonProcessingException; |
|||
import org.slf4j.Logger; |
|||
import org.slf4j.LoggerFactory; |
|||
|
|||
import java.io.IOException; |
|||
import java.security.MessageDigest; |
|||
import java.util.Arrays; |
|||
import java.util.Map; |
|||
|
|||
/** |
|||
* @author __zHangSan |
|||
*/ |
|||
public class WxGzhUtil { |
|||
private static final Logger logger = LoggerFactory.getLogger(WxGzhUtil.class); |
|||
/** |
|||
* 全局唯一accessToken |
|||
*/ |
|||
private static WxAccessToken globalWxAccessToken; |
|||
/** |
|||
* accessToken 过期提前10分钟刷新 |
|||
*/ |
|||
private static final Integer ACCESS_TOKEN_RESERVED_SECONDS = 10 * 60; |
|||
|
|||
private static final String URL_LOGIN |
|||
= "https://api.weixin.qq.com/sns/jscode2session?appid=%1$s&secret=%2$s&js_code=%3$s&grant_type=%4$s"; |
|||
private static final String URL_GET_ACCESS_TOKEN |
|||
= "https://api.weixin.qq.com/cgi-bin/token?grant_type=%1$s&appid=%2$s&secret=%3$s"; |
|||
private static final String URL_GET_WX_CODE_A |
|||
= "https://api.weixin.qq.com/wxa/getwxacode?access_token=%1$s"; |
|||
private static final String URL_GET_WX_CODE_B |
|||
= "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=%1$s"; |
|||
private static final String URL_GET_WX_CODE_C |
|||
= "https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token=%1$s"; |
|||
private static final String URL_PREPARE_PAY |
|||
= "https://api.mch.weixin.qq.com/pay/unifiedorder"; |
|||
private static final String URL_PAY_TO_USR_WX |
|||
= "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers"; |
|||
private static final String URL_PAY_TO_USR_BANK |
|||
= "https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank"; |
|||
private static final String URL_CREATE_MENU |
|||
= " https://api.weixin.qq.com/cgi-bin/menu/create?access_token=%1$s"; |
|||
private static final String URL_QUERY_MENU |
|||
= "https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info?access_token=%1$s"; |
|||
private static final String GZH_AUTH_URL |
|||
= "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%1$s&redirect_uri=%2$s&response_type=code&scope=%3$s&state=STATE#wechat_redirect"; |
|||
private static final String URL_GET_OAUTH2_ACCESS_TOKEN |
|||
= "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%1$s&secret=%2$s&code=%3$s&grant_type=authorization_code"; |
|||
private static final String URL_GET_OAUTH2_USERINFO |
|||
= "https://api.weixin.qq.com/sns/userinfo?access_token=%1$s&openid=%2$s"; |
|||
private static final String APPID = "wx7af1bf1e14facf82"; |
|||
private static final String SECRET = "a6613fae11b497639c0224b820aaf6d9"; |
|||
|
|||
private static final String APPID_H5 = "wxd1842e073e0e6d91"; |
|||
private static final String SECRET_H5 = "96d69b79039caf92a2abafa999880cad"; |
|||
|
|||
private static final String TOKEN = "nNzkL9KkZUOIS8uU"; |
|||
private static final String ENCODING_AES_KEY = "MQEXG7grhRNsARbUzem6OwnGr2ZW9o5jsauNqaQWOuu"; |
|||
private static final String MCHID = ""; |
|||
private static final String KEY = ""; |
|||
|
|||
private static String appId(WebConstant.IDENTIFY_TYPE identifyType){ |
|||
switch (identifyType){ |
|||
case Wx_H5: |
|||
return APPID_H5; |
|||
case OAUTH2_Wx: |
|||
|
|||
default: |
|||
return APPID; |
|||
} |
|||
} |
|||
|
|||
private static String secret(WebConstant.IDENTIFY_TYPE identifyType){ |
|||
switch (identifyType){ |
|||
case Wx_H5: |
|||
return SECRET_H5; |
|||
case OAUTH2_Wx: |
|||
|
|||
default: |
|||
return SECRET; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 数组转字符串 |
|||
*/ |
|||
private static String arrayToString(String[] arr) { |
|||
StringBuilder bf = new StringBuilder(); |
|||
for (String s : arr) { |
|||
bf.append(s); |
|||
} |
|||
return bf.toString(); |
|||
} |
|||
|
|||
/** |
|||
* sha1加密 |
|||
*/ |
|||
private static String sha1Encode(String sourceString) { |
|||
String resultString = null; |
|||
try { |
|||
MessageDigest md = MessageDigest.getInstance("SHA-1"); |
|||
resultString = byte2hexString(md.digest(sourceString.getBytes())); |
|||
} catch (Exception ex) { |
|||
ex.printStackTrace(); |
|||
} |
|||
return resultString; |
|||
} |
|||
|
|||
/** |
|||
* 字节数组转字符串 |
|||
*/ |
|||
private static String byte2hexString(byte[] bytes) { |
|||
StringBuilder buf = new StringBuilder(bytes.length * 2); |
|||
for (byte aByte : bytes) { |
|||
if (((int) aByte & 0xff) < 0x10) { |
|||
buf.append("0"); |
|||
} |
|||
buf.append(Long.toString((int) aByte & 0xff, 16)); |
|||
} |
|||
return buf.toString().toUpperCase(); |
|||
} |
|||
|
|||
/** |
|||
* 公众号接入验证 |
|||
* @param signature signature |
|||
* @param timestamp timestamp |
|||
* @param nonce nonce |
|||
* @param echostr echostr |
|||
* @return true or false |
|||
*/ |
|||
public static boolean checkSignature(String signature,String timestamp,String nonce,String echostr){ |
|||
if(StrUtil.isEmpty(signature) || StrUtil.isEmpty(timestamp) || StrUtil.isEmpty(nonce) || StrUtil.isEmpty(echostr)){ |
|||
return false; |
|||
} |
|||
String[] tmpArr = { TOKEN, timestamp, nonce }; |
|||
Arrays.sort(tmpArr); |
|||
String sign = sha1Encode( arrayToString(tmpArr)); |
|||
Console.log("sign:{} , signature: {}",sign,signature); |
|||
if (sign.equalsIgnoreCase(signature)) { |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
/** |
|||
* 获取Access_token |
|||
*/ |
|||
public static String getAccessToken() throws BaseException { |
|||
if(globalWxAccessToken == null || |
|||
globalWxAccessToken.getCreatedAt() + globalWxAccessToken.getExpiresIn() |
|||
>= DateUtil.currentSeconds() - ACCESS_TOKEN_RESERVED_SECONDS){ |
|||
WxAccessToken wxAccessToken = null; |
|||
String url = String.format(URL_GET_ACCESS_TOKEN,"client_credential",SECRET); |
|||
String response = HttpRequest.get(url).execute().body(); |
|||
Console.log("getAccessToken: {}",response); |
|||
try { |
|||
if(StrUtil.isEmpty(response) || null == (wxAccessToken = JacksonUtil.jsonToBean(response, WxAccessToken.class))) { |
|||
throw new BusinessException(-1,"the response of HttpRequest is empty."); |
|||
} |
|||
} catch (IOException e) { |
|||
throw new BusinessException(-1,e.getMessage()); |
|||
} |
|||
|
|||
if(null != wxAccessToken.getErrcode()){ |
|||
throw new WxException(wxAccessToken.getErrcode(),wxAccessToken.getErrmsg()); |
|||
} |
|||
if (StrUtil.isEmpty(wxAccessToken.getAccessToken())) { |
|||
throw new BusinessException(-1,"can't find the access_token attribute."); |
|||
} |
|||
globalWxAccessToken = wxAccessToken; |
|||
globalWxAccessToken.setCreatedAt(DateUtil.currentSeconds()); |
|||
} |
|||
return globalWxAccessToken.getAccessToken(); |
|||
} |
|||
|
|||
/** |
|||
* 查询微信公众号底部菜单 |
|||
*/ |
|||
public static String queryMenu() throws BaseException { |
|||
String url = String.format(URL_QUERY_MENU,getAccessToken()); |
|||
String menuString = HttpRequest.get(url).execute().body(); |
|||
Console.log("url:{}, menuString: {}",url,menuString); |
|||
return menuString; |
|||
} |
|||
|
|||
/** |
|||
* 创建微信公众号底部菜单 |
|||
*/ |
|||
public static void createMenu(WxGzhMenu gzhMenu) throws BaseException { |
|||
String url = String.format(URL_CREATE_MENU,getAccessToken()); |
|||
String menuString = null; |
|||
try { |
|||
menuString = JacksonUtil.beanToJson(gzhMenu); |
|||
Console.log(menuString); |
|||
} catch (JsonProcessingException e) { |
|||
e.printStackTrace(); |
|||
throw new BusinessException(-1,e.getMessage()); |
|||
} |
|||
String response = HttpRequest.post(url).body(menuString).execute().body(); |
|||
if(StrUtil.isEmpty(response)){ |
|||
throw new BusinessException(-1,"the response of HttpRequest is empty."); |
|||
} |
|||
Map<String,Object> map = null; |
|||
try { |
|||
map = JacksonUtil.jsonToMap(response); |
|||
} catch (IOException e) { |
|||
throw new BusinessException(-1,e.getMessage()); |
|||
} |
|||
|
|||
Object errcode = map.get("errcode"); |
|||
if(errcode == null || ((Integer)errcode) != 0) { |
|||
throw new WxException((Integer)errcode,(String)map.get("errmsg")); |
|||
} |
|||
} |
|||
|
|||
public static String getAuthedUrl(String url, WxGzhAuthType wxGzhAuthType){ |
|||
return String.format(GZH_AUTH_URL,APPID, URLUtil.encode(url),wxGzhAuthType.getText()); |
|||
} |
|||
|
|||
/** |
|||
* 获取网页授权凭证 |
|||
* @param code OAuth2授权码 |
|||
* @return WxOauth2AccessToken |
|||
*/ |
|||
public static WxOauth2AccessToken getOauth2AccessToken(WebConstant.IDENTIFY_TYPE identifyType,String code) throws BaseException { |
|||
WxOauth2AccessToken wxOauth2AccessToken = null; |
|||
String url = String.format(URL_GET_OAUTH2_ACCESS_TOKEN,appId(identifyType),secret(identifyType),code); |
|||
String response = HttpRequest.get(url).execute().body(); |
|||
Console.log("url: {}\nresponse: {}",url,response); |
|||
try { |
|||
if(StrUtil.isEmpty(response) || null == (wxOauth2AccessToken = JacksonUtil.jsonToBean(response,WxOauth2AccessToken.class))) { |
|||
throw new BusinessException(-1,"the response of HttpRequest is empty."); |
|||
} |
|||
} catch (IOException e) { |
|||
throw new BusinessException(-1,e.getMessage()); |
|||
} |
|||
|
|||
if(null != wxOauth2AccessToken.getErrcode()){ |
|||
throw new WxException(wxOauth2AccessToken.getErrcode(),wxOauth2AccessToken.getErrmsg()); |
|||
} |
|||
if (StrUtil.isEmpty(wxOauth2AccessToken.getAccessToken())) { |
|||
throw new BusinessException(-1,"can't find the access_token attribute."); |
|||
} |
|||
wxOauth2AccessToken.setCreatedAt(DateUtil.currentSeconds()); |
|||
return wxOauth2AccessToken; |
|||
} |
|||
|
|||
/** |
|||
* 通过网页授权获取用户信息 |
|||
* |
|||
* @param accessToken 网页授权接口调用凭证 |
|||
* @param openId 用户标识 |
|||
* @return SNSUserInfo |
|||
*/ |
|||
public static WxOauth2UserInfo getOauth2UserInfo(String accessToken, String openId) throws BaseException { |
|||
WxOauth2UserInfo wxOauth2UserInfo = null; |
|||
String url = String.format(URL_GET_OAUTH2_USERINFO,accessToken,openId); |
|||
String response = HttpRequest.get(url).execute().body(); |
|||
Console.log("url: {}\nresponse: {}",url,response); |
|||
try { |
|||
if(StrUtil.isEmpty(response) || null == (wxOauth2UserInfo = JacksonUtil.jsonToBean(response,WxOauth2UserInfo.class))) { |
|||
throw new BusinessException(-1,"the response of HttpRequest is empty."); |
|||
} |
|||
} catch (IOException e) { |
|||
throw new BusinessException(-1,e.getMessage()); |
|||
} |
|||
|
|||
if(null != wxOauth2UserInfo.getErrcode()){ |
|||
throw new WxException(wxOauth2UserInfo.getErrcode(),wxOauth2UserInfo.getErrmsg()); |
|||
} |
|||
if (StrUtil.isEmpty(wxOauth2UserInfo.getOpenId())) { |
|||
throw new BusinessException(-1,"can't find the openid attribute."); |
|||
} |
|||
return wxOauth2UserInfo; |
|||
} |
|||
|
|||
/** |
|||
* 通过网页授权code拉取用户信息,封装了getOauth2AccessToken和getOauth2UserInfo(accessToken,openId) |
|||
* @param code 网页授权码 |
|||
* @return WxOauth2UserInfo |
|||
* @throws BaseException 异常 |
|||
*/ |
|||
public static WxOauth2UserInfo getOauth2UserInfo(WebConstant.IDENTIFY_TYPE identifyType,String code) throws BaseException { |
|||
WxOauth2AccessToken wxOauth2AccessToken = getOauth2AccessToken(identifyType,code); |
|||
return getOauth2UserInfo(wxOauth2AccessToken.getAccessToken(),wxOauth2AccessToken.getOpenId()); |
|||
} |
|||
} |
@ -0,0 +1,406 @@ |
|||
package com.ccsens.util.wx; |
|||
|
|||
import cn.hutool.core.util.ObjectUtil; |
|||
import cn.hutool.core.util.StrUtil; |
|||
import cn.hutool.http.HttpRequest; |
|||
|
|||
import com.ccsens.util.HttpsUtil; |
|||
import com.ccsens.util.JacksonUtil; |
|||
import com.ccsens.util.WebConstant; |
|||
import com.ccsens.util.exception.BusinessException; |
|||
import com.ccsens.util.exception.WxException; |
|||
import lombok.Data; |
|||
import org.apache.commons.codec.digest.DigestUtils; |
|||
|
|||
import java.io.ByteArrayInputStream; |
|||
import java.io.IOException; |
|||
import java.io.UnsupportedEncodingException; |
|||
import java.net.ConnectException; |
|||
import java.util.*; |
|||
|
|||
@Data |
|||
class GetUserInfoException extends RuntimeException{ |
|||
private int code; |
|||
public GetUserInfoException(int code,String message){ |
|||
super(message); |
|||
this.code = code; |
|||
} |
|||
} |
|||
|
|||
@Data |
|||
class PayException extends RuntimeException{ |
|||
private int code; |
|||
public PayException(int code,String message){ |
|||
super(message); |
|||
this.code = code; |
|||
} |
|||
|
|||
public PayException(String message){ |
|||
super(message); |
|||
this.code = -1; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* @author __zHangSan |
|||
*/ |
|||
public class WxXcxUtil { |
|||
|
|||
/** |
|||
* 被Jasckson使用的内部类 必须是static的 |
|||
*/ |
|||
public static class WechatUser { |
|||
public String openid; |
|||
public String session_key; |
|||
public String unionid; |
|||
public Integer errcode; |
|||
public String errmsg; |
|||
} |
|||
|
|||
/** |
|||
* Get wx code |
|||
*/ |
|||
public static class WechatCode{ |
|||
public String scene; |
|||
public String page; |
|||
public Integer width; |
|||
public Boolean auto_color; |
|||
public Boolean line_color; |
|||
public Boolean is_hyaline; |
|||
} |
|||
|
|||
/** |
|||
* Prepare pay |
|||
*/ |
|||
public static class PreparePayBean{ |
|||
public String appid;//小程序ID
|
|||
public String mch_id;//商户号
|
|||
public String device_info;//设备号
|
|||
public String nonce_str;//随机字符串
|
|||
public String sign;//签名
|
|||
public String sign_type; //签名类型
|
|||
public String body;//商品描述
|
|||
public String detail;//商品详情
|
|||
public String attach;//附加数据
|
|||
public String out_trade_no;//商户订单号
|
|||
public String fee_type;//货币类型
|
|||
public Integer total_fee; //金额(分)
|
|||
public String spbill_create_ip;//终端IP
|
|||
public String time_start;//交易起始时间
|
|||
public String time_expire;//交易结束时间
|
|||
public String goods_tag;//商品标记
|
|||
public String notify_url;//通知地址
|
|||
public String trade_type;//交易类型
|
|||
public String product_id;//商品id
|
|||
public String limit_pay;//指定支付方式
|
|||
public String openid;//用户标识
|
|||
} |
|||
|
|||
/** |
|||
* Prepare pay result |
|||
*/ |
|||
public static class PreparePayResultBean{ |
|||
public String return_code; |
|||
public String return_msg; |
|||
public String result_code; |
|||
public String prepay_id; |
|||
public String err_code; |
|||
public String err_code_des; |
|||
} |
|||
|
|||
/** |
|||
* Prepare pay resign |
|||
*/ |
|||
public static class PreparePayReSignBean{ |
|||
public String nonceStr; |
|||
public String _package; |
|||
public long timeStamp; |
|||
public String paySign; |
|||
public String signType; |
|||
} |
|||
|
|||
private static final String URL_LOGIN |
|||
= "https://api.weixin.qq.com/sns/jscode2session?appid=%1$s&secret=%2$s&js_code=%3$s&grant_type=%4$s"; |
|||
private static final String URL_GET_ACCESS_TOKEN |
|||
= "https://api.weixin.qq.com/cgi-bin/token?grant_type=%1$s&appid=%2$s&secret=%3$s"; |
|||
private static final String URL_GET_WX_CODE_A |
|||
= "https://api.weixin.qq.com/wxa/getwxacode?access_token=%1$s"; |
|||
private static final String URL_GET_WX_CODE_B |
|||
= "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=%1$s"; |
|||
private static final String URL_GET_WX_CODE_C |
|||
= "https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token=%1$s"; |
|||
private static final String URL_PREPARE_PAY |
|||
= "https://api.mch.weixin.qq.com/pay/unifiedorder"; |
|||
private static final String URL_PAY_TO_USR_WX |
|||
= "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers"; |
|||
private static final String URL_PAY_TO_USR_BANK |
|||
= "https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank"; |
|||
private static final String URL_CREATE_MENU |
|||
= " https://api.weixin.qq.com/cgi-bin/menu/create?access_token=%1$s"; |
|||
|
|||
private static final String appid = "wx7af1bf1e14facf82"; |
|||
private static final String secret = "a6613fae11b497639c0224b820aaf6d9"; |
|||
private static final String mchid = ""; |
|||
private static final String key = ""; |
|||
|
|||
/** |
|||
* 小程序登陆,根据code获取用户信息(openid,sessionKey,) |
|||
* @param code |
|||
* @return |
|||
* @throws ConnectException |
|||
* @throws Exception |
|||
*/ |
|||
public static WechatUser getUserInfo(String code) throws Exception { |
|||
WechatUser wechatUser = null; |
|||
String url = String.format(URL_LOGIN, appid, secret, code, "authorization_code"); |
|||
String response = HttpRequest.get(url).execute().body(); |
|||
try { |
|||
if(StrUtil.isEmpty(response) || null == (wechatUser = JacksonUtil.jsonToBean(response, WechatUser.class))) { |
|||
throw new BusinessException(-1,"the response of HttpRequest is empty."); |
|||
} |
|||
} catch (IOException e) { |
|||
throw new BusinessException(-1,e.getMessage()); |
|||
} |
|||
|
|||
if(null != wechatUser.errcode){ |
|||
throw new WxException(wechatUser.errcode, wechatUser.errmsg); |
|||
} |
|||
return wechatUser; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 获取小程序二维码/小程序码 |
|||
* @return |
|||
* @throws Exception |
|||
*/ |
|||
public static void getWxCode(String page,String scene,String path) throws Exception { |
|||
String url = String.format(URL_GET_WX_CODE_B, WxGzhUtil.getAccessToken()); |
|||
|
|||
WechatCode wechatCode = new WechatCode(); |
|||
wechatCode.page = page; |
|||
wechatCode.scene = scene; |
|||
|
|||
String postStr = JacksonUtil.beanToJson(wechatCode); |
|||
System.out.println(postStr); |
|||
|
|||
HttpsUtil.httpsRequest(url,"POST",postStr,path); |
|||
} |
|||
|
|||
/** |
|||
* 统一下单 |
|||
*/ |
|||
public static PreparePayReSignBean preparePay(String openid,String out_trade_no,String body,int total_fee,String spbill_create_ip, |
|||
String notify_url) throws Exception { |
|||
PreparePayBean preparePayBean = new PreparePayBean(); |
|||
preparePayBean.appid = appid; |
|||
preparePayBean.mch_id = mchid; |
|||
preparePayBean.openid = openid; |
|||
preparePayBean.total_fee = total_fee; |
|||
preparePayBean.out_trade_no = out_trade_no; |
|||
//以utf-8编码放入paymentPo,微信支付要求字符编码统一采用UTF-8字符编码
|
|||
preparePayBean.body = new String(body.getBytes("ISO-8859-1"),"UTF-8"); |
|||
//preparePayBean.body = new String("小程序-充值");
|
|||
preparePayBean.spbill_create_ip = spbill_create_ip; |
|||
preparePayBean.notify_url = notify_url; |
|||
preparePayBean.trade_type = "JSAPI"; |
|||
preparePayBean.nonce_str = createNonceStr(); |
|||
|
|||
// 把请求参数打包成数组
|
|||
Map<String,Object> sParaTemp = new HashMap(); |
|||
sParaTemp.put("appid", preparePayBean.appid); |
|||
sParaTemp.put("mch_id", preparePayBean.mch_id); |
|||
sParaTemp.put("openid", preparePayBean.openid); |
|||
sParaTemp.put("total_fee",preparePayBean.total_fee + ""); |
|||
sParaTemp.put("out_trade_no", preparePayBean.out_trade_no); |
|||
sParaTemp.put("body", preparePayBean.body); |
|||
sParaTemp.put("spbill_create_ip", preparePayBean.spbill_create_ip); |
|||
sParaTemp.put("notify_url",preparePayBean.notify_url); |
|||
sParaTemp.put("trade_type", preparePayBean.trade_type); |
|||
sParaTemp.put("nonce_str", preparePayBean.nonce_str); |
|||
|
|||
preparePayBean.sign = createSign(sParaTemp); |
|||
|
|||
String reqrXml = JacksonUtil.beanToXml(preparePayBean,"xml"); |
|||
String respXml = HttpsUtil.httpsRequest(URL_PREPARE_PAY,"POST",reqrXml); |
|||
|
|||
System.out.println("---------------PreparePay Request Xml-----------------"); |
|||
System.out.println(reqrXml); |
|||
System.out.println("---------------PreparePay Response Xml-----------------"); |
|||
System.out.println(respXml); |
|||
System.out.println("---------------PreparePay end-----------------"); |
|||
|
|||
PreparePayResultBean resultBean = null; |
|||
PreparePayReSignBean reSignBean = new PreparePayReSignBean(); |
|||
resultBean = JacksonUtil.xmlToBean(new ByteArrayInputStream(respXml.getBytes()),PreparePayResultBean.class); |
|||
|
|||
if(ObjectUtil.isNull(resultBean)) { |
|||
throw new PayException("PreparePay 返回的resultBean为空"); |
|||
} |
|||
if(!StrUtil.isEmpty(resultBean.return_code) |
|||
&& !StrUtil.isEmpty(resultBean.result_code)){ |
|||
if(resultBean.result_code.equals("SUCCESS") && resultBean.return_code.equals(resultBean.result_code)){ |
|||
reSignBean.nonceStr = createNonceStr(); |
|||
reSignBean._package = "prepay_id="+resultBean.prepay_id; |
|||
reSignBean.timeStamp = System.currentTimeMillis() / 1000; |
|||
reSignBean.signType = "MD5"; |
|||
|
|||
// 把请求参数打包成数组
|
|||
sParaTemp = new HashMap(); |
|||
sParaTemp.put("appId", appid); |
|||
sParaTemp.put("package", reSignBean._package); |
|||
sParaTemp.put("nonceStr", reSignBean.nonceStr); |
|||
sParaTemp.put("signType", reSignBean.signType); |
|||
sParaTemp.put("timeStamp",reSignBean.timeStamp + ""); |
|||
|
|||
reSignBean.paySign = createSign(sParaTemp); |
|||
|
|||
return reSignBean; |
|||
}else{ |
|||
throw new PayException("[" + resultBean.err_code + "]" |
|||
+ resultBean.err_code_des); |
|||
} |
|||
}else { |
|||
throw new PayException(resultBean.return_msg); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Create Sign |
|||
* @param sParaTemp |
|||
* @return |
|||
*/ |
|||
public static String createSign(Map<String,Object> sParaTemp){ |
|||
// 除去数组中的空值和签名参数
|
|||
Map sPara = paraFilter(sParaTemp); |
|||
// 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
|
|||
String prestr = createLinkString(sPara); |
|||
//MD5运算生成签名
|
|||
String sign = sign(prestr, key, "utf-8").toUpperCase(); |
|||
return sign; |
|||
} |
|||
|
|||
/** |
|||
* 除去数组中的空值和签名参数 |
|||
* @param sArray 签名参数组 |
|||
* @return 去掉空值与签名参数后的新签名参数组 |
|||
*/ |
|||
private static Map paraFilter(Map<String,Object> sArray) { |
|||
Map result = new HashMap(); |
|||
if (sArray == null || sArray.size() <= 0) { |
|||
return result; |
|||
} |
|||
for (String key : sArray.keySet()) { |
|||
String value = "" + sArray.get(key); |
|||
if (StrUtil.isEmpty(value) || key.equalsIgnoreCase("sign") || key.equalsIgnoreCase("sign_type")) { |
|||
continue; |
|||
} |
|||
result.put(key, value); |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
/** |
|||
* 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串 |
|||
* @param params 需要排序并参与字符拼接的参数组 |
|||
* @return 拼接后字符串 |
|||
*/ |
|||
private static String createLinkString(Map<String,String> params) { |
|||
List<String> keys = new ArrayList<String>(params.keySet()); |
|||
Collections.sort(keys); |
|||
StringBuilder prestr = new StringBuilder(); |
|||
for (int i = 0; i < keys.size(); i++) { |
|||
String key = keys.get(i); |
|||
String value = params.get(key); |
|||
if (i == keys.size() - 1) { |
|||
prestr.append(key).append("=").append(value); |
|||
} else { |
|||
prestr.append(key).append("=").append(value).append("&"); |
|||
} |
|||
} |
|||
return prestr.toString(); |
|||
} |
|||
|
|||
/** |
|||
* 签名字符串 |
|||
* @param text 需要签名的字符串 |
|||
* @param key 密钥 |
|||
* @param input_charset 编码格式 |
|||
* @return 签名结果 |
|||
*/ |
|||
private static String sign(String text, String key, String input_charset) { |
|||
text = text + "&key=" + key; |
|||
return DigestUtils.md5Hex(getContentBytes(text, input_charset)); |
|||
} |
|||
|
|||
/** |
|||
* getContentBytes |
|||
*/ |
|||
private static byte[] getContentBytes(String content, String charset) { |
|||
if (charset == null || "".equals(charset)) { |
|||
return content.getBytes(); |
|||
} |
|||
try { |
|||
return content.getBytes(charset); |
|||
} catch (UnsupportedEncodingException e) { |
|||
throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset); |
|||
} |
|||
} |
|||
|
|||
private static String createNonceStr(){ |
|||
return UUID.randomUUID().toString().replace("-",""); |
|||
} |
|||
|
|||
public static Map<String,Object> payToUsrWx( |
|||
String partner_trade_no,String openid,int total_fee,String desc,String spbill_create_ip) |
|||
throws Exception{ |
|||
final String SUCCESS = "SUCCESS"; |
|||
//1.构造请求字符串
|
|||
Map<String,Object> reqMap = new HashMap<>(); |
|||
reqMap.put("mch_appid",appid); |
|||
reqMap.put("mchid",mchid); |
|||
//reqMap.put("device_info",null); //不能添加空字段,Jackson会生成闭包xml <device_info/>导致签名失败
|
|||
reqMap.put("nonce_str",createNonceStr()); |
|||
reqMap.put("partner_trade_no",partner_trade_no); |
|||
reqMap.put("openid",openid); |
|||
reqMap.put("check_name","NO_CHECK"); |
|||
//reqMap.put("re_user_name",null);
|
|||
reqMap.put("amount",total_fee + ""); |
|||
reqMap.put("desc",desc); |
|||
reqMap.put("spbill_create_ip",spbill_create_ip); |
|||
reqMap.put("sign",createSign(reqMap)); |
|||
|
|||
//2.发送付款请求
|
|||
String reqrXml = JacksonUtil.mapToXml(reqMap,"xml"); |
|||
String respXml = HttpsUtil.httpsRequest(URL_PAY_TO_USR_WX,"POST",reqrXml, |
|||
WebConstant.PATH_WX_CRET,mchid); |
|||
System.out.println("---------------PayToUsrWx Request Xml-----------------"); |
|||
System.out.println(reqrXml); |
|||
System.out.println("---------------PayToUsrWx Response Xml-----------------"); |
|||
System.out.println(respXml); |
|||
System.out.println("---------------PayToUsrWx end-----------------"); |
|||
|
|||
//3.判断成功失败
|
|||
Map<String,Object> respMap = JacksonUtil.xmlToMap(new ByteArrayInputStream(respXml.getBytes())); |
|||
String return_code,result_code; |
|||
return_code = (String)respMap.get("return_code"); |
|||
result_code = (String)respMap.get("result_code"); |
|||
|
|||
if(!StrUtil.isEmpty(return_code) && !StrUtil.isEmpty(result_code)){ |
|||
if(return_code.equals(SUCCESS) && return_code.equals(result_code)){ |
|||
return respMap; |
|||
}else{ |
|||
throw new PayException("[" + respMap.get("err_code") + "]" |
|||
+ respMap.get("err_code_des")); |
|||
} |
|||
}else { |
|||
throw new PayException((String) respMap.get("return_msg")); |
|||
} |
|||
//return null;
|
|||
} |
|||
|
|||
public static Map<String,String> payToUsrBank(){ |
|||
//Fix Me
|
|||
return null; |
|||
} |
|||
} |
Loading…
Reference in new issue