mirror of
https://gitee.com/binary/weixin-java-tools.git
synced 2025-06-28 13:16:19 +08:00
🆕 #2385 【开放平台】 增加为小程序设置用户隐私指引的相关接口
This commit is contained in:
parent
23a115fdee
commit
ef99e3d24f
@ -2,6 +2,7 @@ package me.chanjar.weixin.common.error;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import me.chanjar.weixin.common.enums.WxType;
|
||||
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@ -17,6 +18,7 @@ import java.io.Serializable;
|
||||
* @author Daniel Qian & Binary Wang
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class WxError implements Serializable {
|
||||
private static final long serialVersionUID = 7869786563361406291L;
|
||||
@ -39,6 +41,11 @@ public class WxError implements Serializable {
|
||||
|
||||
private String json;
|
||||
|
||||
public WxError(int errorCode, String errorMsg) {
|
||||
this.errorCode = errorCode;
|
||||
this.errorMsg = errorMsg;
|
||||
}
|
||||
|
||||
public static WxError fromJson(String json) {
|
||||
return fromJson(json, null);
|
||||
}
|
||||
|
@ -0,0 +1,65 @@
|
||||
package me.chanjar.weixin.open.api;
|
||||
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.open.bean.ma.privacy.GetPrivacySettingResult;
|
||||
import me.chanjar.weixin.open.bean.ma.privacy.SetPrivacySetting;
|
||||
import me.chanjar.weixin.open.bean.ma.privacy.UploadPrivacyFileResult;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* 微信第三方平台 小程序用户隐私保护指引接口
|
||||
* https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/privacy_config/set_privacy_setting.html
|
||||
*
|
||||
* @author <a href="https://www.sacoc.cn">广州跨界</a>
|
||||
*/
|
||||
public interface WxOpenMaPrivacyService {
|
||||
|
||||
/**
|
||||
* 1 设置小程序用户隐私保护指引
|
||||
*/
|
||||
String OPEN_SET_PRIVACY_SETTING = "https://api.weixin.qq.com/cgi-bin/component/setprivacysetting";
|
||||
|
||||
/**
|
||||
* 2 查询小程序用户隐私保护指引
|
||||
*/
|
||||
String OPEN_GET_PRIVACY_SETTING = "https://api.weixin.qq.com/cgi-bin/component/getprivacysetting";
|
||||
|
||||
/**
|
||||
* 3 上传小程序用户隐私保护指引文件
|
||||
*/
|
||||
String OPEN_UPLOAD_PRIVACY_FILE = "https://api.weixin.qq.com/cgi-bin/component/uploadprivacyextfile";
|
||||
|
||||
|
||||
/**
|
||||
* 查询小程序用户隐私保护指引
|
||||
* 文档地址:https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/privacy_config/get_privacy_setting.html
|
||||
*
|
||||
* @param privacyVer 1表示现网版本,即,传1则该接口返回的内容是现网版本的;2表示开发版,即,传2则该接口返回的内容是开发版本的。默认是2。
|
||||
* @return 查询结果
|
||||
* @throws WxErrorException 如果出错,抛出此异常
|
||||
*/
|
||||
GetPrivacySettingResult getPrivacySetting(@Nullable Integer privacyVer) throws WxErrorException;
|
||||
|
||||
|
||||
/**
|
||||
* 设置小程序用户隐私保护指引
|
||||
* 文档地址:https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/privacy_config/set_privacy_setting.html
|
||||
*
|
||||
* @param dto 参数对象
|
||||
* @throws WxErrorException 如果出错,抛出此异常
|
||||
*/
|
||||
void setPrivacySetting(SetPrivacySetting dto) throws WxErrorException;
|
||||
|
||||
|
||||
/**
|
||||
* 上传小程序用户隐私保护指引文件
|
||||
* 本接口用于上传自定义的小程序的用户隐私保护指引
|
||||
* 仅限文本文件, 限制文件大小为不超过100kb,否则会报错
|
||||
* 文档地址:https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/privacy_config/upload_privacy_exfile.html
|
||||
*
|
||||
* @param content 文本文件内容
|
||||
* @return 上传结果
|
||||
* @throws WxErrorException 如果出错,抛出此异常
|
||||
*/
|
||||
UploadPrivacyFileResult uploadPrivacyFile(String content) throws WxErrorException;
|
||||
}
|
@ -632,6 +632,13 @@ public interface WxOpenMaService extends WxMaService {
|
||||
*/
|
||||
WxOpenMaBasicService getBasicService();
|
||||
|
||||
/**
|
||||
* 小程序用户隐私保护指引服务
|
||||
*
|
||||
* @return 小程序用户隐私保护指引服务
|
||||
*/
|
||||
WxOpenMaPrivacyService getPrivacyService();
|
||||
|
||||
/**
|
||||
* 小程序审核 提审素材上传接口
|
||||
*
|
||||
|
@ -0,0 +1,55 @@
|
||||
package me.chanjar.weixin.open.api.impl;
|
||||
|
||||
import cn.binarywang.wx.miniapp.api.WxMaService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import me.chanjar.weixin.common.error.WxError;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.open.api.WxOpenMaPrivacyService;
|
||||
import me.chanjar.weixin.open.bean.ma.privacy.GetPrivacySettingResult;
|
||||
import me.chanjar.weixin.open.bean.ma.privacy.SetPrivacySetting;
|
||||
import me.chanjar.weixin.open.bean.ma.privacy.UploadPrivacyFileResult;
|
||||
import me.chanjar.weixin.open.util.json.WxOpenGsonBuilder;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 微信第三方平台 小程序用户隐私保护指引接口
|
||||
* https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/privacy_config/set_privacy_setting.html
|
||||
*
|
||||
* @author <a href="https://www.sacoc.cn">广州跨界</a>
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public class WxOpenMaPrivacyServiceImpl implements WxOpenMaPrivacyService {
|
||||
|
||||
private final WxMaService wxMaService;
|
||||
|
||||
|
||||
@Override
|
||||
public GetPrivacySettingResult getPrivacySetting(@Nullable Integer privacyVer) throws WxErrorException {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
if (privacyVer != null) {
|
||||
params.put("privacy_ver", privacyVer);
|
||||
}
|
||||
String json = wxMaService.post(OPEN_GET_PRIVACY_SETTING, params);
|
||||
return WxOpenGsonBuilder.create().fromJson(json, GetPrivacySettingResult.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPrivacySetting(SetPrivacySetting dto) throws WxErrorException {
|
||||
wxMaService.post(OPEN_SET_PRIVACY_SETTING, dto);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public UploadPrivacyFileResult uploadPrivacyFile(String content) throws WxErrorException {
|
||||
// TODO 应实现通过InputStream上传的功能,一下代码暂时无法正常运行
|
||||
// ByteArrayInputStream data = new ByteArrayInputStream(content.getBytes("GBK"));
|
||||
// GenericUploadRequestExecutor executor = new GenericUploadRequestExecutor(wxMaService.getRequestHttp(), "POST", "file", "/temp.txt");
|
||||
// String json = wxMaService.execute(executor, OPEN_UPLOAD_PRIVACY_FILE, data);
|
||||
// return WxOpenGsonBuilder.create().fromJson(json, UploadPrivacyFileResult.class);
|
||||
throw new WxErrorException(new WxError(5003, "暂未实现用户隐私指引内容上传"));
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@ import lombok.Getter;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.open.api.WxOpenComponentService;
|
||||
import me.chanjar.weixin.open.api.WxOpenMaBasicService;
|
||||
import me.chanjar.weixin.open.api.WxOpenMaPrivacyService;
|
||||
import me.chanjar.weixin.open.api.WxOpenMaService;
|
||||
import me.chanjar.weixin.open.bean.ma.WxMaQrcodeParam;
|
||||
import me.chanjar.weixin.open.bean.ma.WxMaScheme;
|
||||
@ -42,12 +43,15 @@ public class WxOpenMaServiceImpl extends WxMaServiceImpl implements WxOpenMaServ
|
||||
private final String appId;
|
||||
@Getter
|
||||
private final WxOpenMaBasicService basicService;
|
||||
@Getter
|
||||
private final WxOpenMaPrivacyService privacyService;
|
||||
|
||||
public WxOpenMaServiceImpl(WxOpenComponentService wxOpenComponentService, String appId, WxMaConfig wxMaConfig) {
|
||||
this.wxOpenComponentService = wxOpenComponentService;
|
||||
this.appId = appId;
|
||||
this.wxMaConfig = wxMaConfig;
|
||||
this.basicService = new WxOpenMaBasicServiceImpl(this);
|
||||
this.privacyService = new WxOpenMaPrivacyServiceImpl(this);
|
||||
initHttp();
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,118 @@
|
||||
package me.chanjar.weixin.open.bean.ma.privacy;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import me.chanjar.weixin.open.bean.result.WxOpenResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 查询小程序用户隐私保护指引 响应
|
||||
*
|
||||
* @author <a href="https://www.sacoc.cn">广州跨界</a>
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class GetPrivacySettingResult extends WxOpenResult {
|
||||
|
||||
/**
|
||||
* 代码是否存在, 0 不存在, 1 存在 。如果最近没有通过commit接口上传代码,则会出现 code_exist=0的情况。
|
||||
*/
|
||||
@SerializedName("code_exist")
|
||||
private Integer codeExist;
|
||||
|
||||
/**
|
||||
* 代码检测出来的用户信息类型(privacy_key)
|
||||
*/
|
||||
@SerializedName("privacy_list")
|
||||
private List<String> privacyList;
|
||||
|
||||
/**
|
||||
* 要收集的用户信息配置
|
||||
*/
|
||||
@SerializedName("setting_list")
|
||||
private List<Setting> settingList;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@SerializedName("update_time")
|
||||
private Long updateTime;
|
||||
|
||||
/**
|
||||
* 收集方(开发者)信息配置
|
||||
*/
|
||||
@SerializedName("owner_setting")
|
||||
private PrivacyOwnerSetting ownerSetting;
|
||||
|
||||
/**
|
||||
* 收集方(开发者)信息配置
|
||||
*/
|
||||
@SerializedName("privacy_desc")
|
||||
private PrivacyDesc privacyDesc;
|
||||
|
||||
|
||||
@Data
|
||||
public static class Setting {
|
||||
|
||||
/**
|
||||
* 官方的可选值参考下方说明;该字段也支持自定义
|
||||
*
|
||||
* @see PrivacyKeyEnum
|
||||
* @see PrivacyKeyEnum#getKey()
|
||||
*/
|
||||
@SerializedName("privacy_key")
|
||||
private String privacyKey;
|
||||
|
||||
/**
|
||||
* 请填写收集该信息的用途。例如privacy_key=Location(位置信息),那么privacy_text则填写收集位置信息的用途。
|
||||
* 无需再带上“为了”或者“用于”这些字眼,小程序端的显示格式是为了xxx,因此开发者只需要直接填写用途即可。
|
||||
*/
|
||||
@SerializedName("privacy_text")
|
||||
private String privacyText;
|
||||
|
||||
/**
|
||||
* 用户信息类型的中文名称
|
||||
*
|
||||
* @see PrivacyKeyEnum#getDesc() ()
|
||||
*/
|
||||
@SerializedName("privacy_label")
|
||||
private String privacyLabel;
|
||||
}
|
||||
|
||||
|
||||
@Data
|
||||
public static class PrivacyDesc {
|
||||
|
||||
/**
|
||||
* 用户信息类型
|
||||
*/
|
||||
@SerializedName("privacy_desc_list")
|
||||
private List<PrivacyDescItem> privacyDescList;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class PrivacyDescItem {
|
||||
|
||||
/**
|
||||
* 用户信息类型的英文key
|
||||
*
|
||||
* @see PrivacyKeyEnum
|
||||
* @see PrivacyKeyEnum#getKey()
|
||||
*/
|
||||
@SerializedName("privacy_key")
|
||||
private String privacyKey;
|
||||
|
||||
/**
|
||||
* 用户信息类型的中文描述
|
||||
*
|
||||
* @see PrivacyKeyEnum#getDesc()
|
||||
*/
|
||||
@SerializedName("privacy_desc")
|
||||
private String privacyDesc;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
package me.chanjar.weixin.open.bean.ma.privacy;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 隐私key枚举
|
||||
*
|
||||
* @author <a href="https://www.sacoc.cn">广州跨界</a>
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum PrivacyKeyEnum {
|
||||
|
||||
USER_INFO("UserInfo", "用户信息(微信昵称、头像)"),
|
||||
|
||||
LOCATION("Location", "位置信息"),
|
||||
|
||||
ADDRESS("Address", "地址"),
|
||||
|
||||
INVOICE("Invoice", "发票信息"),
|
||||
|
||||
RUN_DATA("RunData", "微信运动数据"),
|
||||
|
||||
RECORD("Record", "麦克风"),
|
||||
|
||||
ALBUM("Album", "选中的照片或视频信息"),
|
||||
|
||||
CAMERA("Camera", "摄像头"),
|
||||
|
||||
PHONE_NUMBER("PhoneNumber", "手机号码"),
|
||||
|
||||
CONTACT("Contact", "通讯录(仅写入)权限"),
|
||||
|
||||
DEVICE_INFO("DeviceInfo", "设备信息"),
|
||||
|
||||
EXID_NUMBER("EXIDNumber", "身份证号码"),
|
||||
|
||||
EX_ORDER_INFO("EXOrderInfo", "订单信息"),
|
||||
|
||||
EX_USER_PUBLISH_CONTENT("EXUserPublishContent", "发布内容"),
|
||||
|
||||
EX_USER_FOLLOW_ACCT("EXUserFollowAcct", "所关注账号"),
|
||||
|
||||
EX_USER_OP_LOG("EXUserOpLog", "操作日志"),
|
||||
|
||||
ALBUM_WRITE_ONLY("AlbumWriteOnly", "相册(仅写入)权限"),
|
||||
|
||||
LICENSE_PLATE("LicensePlate", "车牌号"),
|
||||
|
||||
BLUE_TOOTH("BlueTooth", "蓝牙"),
|
||||
|
||||
CALENDAR_WRITE_ONLY("CalendarWriteOnly", "日历(仅写入)权限"),
|
||||
|
||||
EMAIL("Email", "邮箱"),
|
||||
|
||||
MESSAGE_FILE("MessageFile", "选中的文件"),
|
||||
;
|
||||
|
||||
private final String key;
|
||||
private final String desc;
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
package me.chanjar.weixin.open.bean.ma.privacy;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* 小程序用户隐私保护指引 收集方(开发者)信息配置
|
||||
*
|
||||
* @author <a href="https://www.sacoc.cn">广州跨界</a>
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PrivacyOwnerSetting {
|
||||
|
||||
/**
|
||||
* 信息收集方(开发者)的邮箱地址,4种联系方式至少要填一种
|
||||
*/
|
||||
@SerializedName("contact_email")
|
||||
private String contactEmail;
|
||||
|
||||
/**
|
||||
* 信息收集方(开发者)的手机号,4种联系方式至少要填一种
|
||||
*/
|
||||
@SerializedName("contact_phone")
|
||||
private String contactPhone;
|
||||
|
||||
/**
|
||||
* 信息收集方(开发者)的qq号,4种联系方式至少要填一种
|
||||
*/
|
||||
@SerializedName("contact_qq")
|
||||
private String contactQq;
|
||||
|
||||
/**
|
||||
* 信息收集方(开发者)的微信号,4种联系方式至少要填一种
|
||||
*/
|
||||
@SerializedName("contact_weixin")
|
||||
private String contactWeixin;
|
||||
|
||||
/**
|
||||
* 如果开发者不使用微信提供的标准化用户隐私保护指引模板,也可以上传自定义的用户隐私保护指引,通过上传接口上传后可获取media_id
|
||||
*/
|
||||
@SerializedName("ext_file_media_id")
|
||||
private String extFileMediaId;
|
||||
|
||||
/**
|
||||
* 通知方式,指的是当开发者收集信息有变动时,通过该方式通知用户。这里服务商需要按照实际情况填写,例如通过弹窗或者公告或者其他方式。
|
||||
*/
|
||||
@NotNull
|
||||
@SerializedName("notice_method")
|
||||
private String noticeMethod;
|
||||
|
||||
/**
|
||||
* 存储期限,指的是开发者收集用户信息存储多久。如果不填则展示为【开发者承诺,除法律法规另有规定,开发者对你的信息保存期限应当为实现处理目的所必要的最短时间】,
|
||||
* 如果填请填数字+天,例如“30天”,否则会出现87072的报错。
|
||||
*/
|
||||
@SerializedName("store_expire_timestamp")
|
||||
private String storeExpireTimestamp;
|
||||
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package me.chanjar.weixin.open.bean.ma.privacy;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 设置小程序用户隐私保护指引参数
|
||||
*
|
||||
* @author <a href="https://www.sacoc.cn">广州跨界</a>
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SetPrivacySetting {
|
||||
|
||||
/**
|
||||
* 用户隐私保护指引的版本,1表示现网版本;2表示开发版。默认是2开发版。
|
||||
*/
|
||||
@SerializedName("privacy_ver")
|
||||
private Integer privacyVer;
|
||||
|
||||
/**
|
||||
* 收集方(开发者)信息配置
|
||||
*/
|
||||
@NotNull
|
||||
@SerializedName("owner_setting")
|
||||
private PrivacyOwnerSetting ownerSetting;
|
||||
|
||||
/**
|
||||
* 要收集的用户信息配置
|
||||
*/
|
||||
@NotNull
|
||||
@SerializedName("setting_list")
|
||||
private List<Setting> settingList;
|
||||
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class Setting {
|
||||
|
||||
/**
|
||||
* 官方的可选值参考下方说明;该字段也支持自定义
|
||||
*
|
||||
* @see PrivacyKeyEnum
|
||||
* @see PrivacyKeyEnum#getKey()
|
||||
*/
|
||||
@NotNull
|
||||
@SerializedName("privacy_key")
|
||||
private String privacyKey;
|
||||
|
||||
/**
|
||||
* 请填写收集该信息的用途。例如privacy_key=Location(位置信息),那么privacy_text则填写收集位置信息的用途。
|
||||
* 无需再带上“为了”或者“用于”这些字眼,小程序端的显示格式是为了xxx,因此开发者只需要直接填写用途即可。
|
||||
*/
|
||||
@NotNull
|
||||
@SerializedName("privacy_text")
|
||||
private String privacyText;
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package me.chanjar.weixin.open.bean.ma.privacy;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import me.chanjar.weixin.open.bean.result.WxOpenResult;
|
||||
|
||||
/**
|
||||
* 上传小程序用户隐私保护指引文件 响应
|
||||
*
|
||||
* @author <a href="https://www.sacoc.cn">广州跨界</a>
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class UploadPrivacyFileResult extends WxOpenResult {
|
||||
|
||||
/**
|
||||
* 文件的media_id
|
||||
*/
|
||||
@SerializedName("ext_file_media_id")
|
||||
private String extFileMediaId;
|
||||
}
|
@ -0,0 +1,184 @@
|
||||
package me.chanjar.weixin.open.executor;
|
||||
|
||||
import jodd.http.HttpConnectionProvider;
|
||||
import jodd.http.HttpRequest;
|
||||
import jodd.http.HttpResponse;
|
||||
import jodd.http.ProxyInfo;
|
||||
import lombok.Data;
|
||||
import me.chanjar.weixin.common.enums.WxType;
|
||||
import me.chanjar.weixin.common.error.WxError;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.common.util.http.RequestExecutor;
|
||||
import me.chanjar.weixin.common.util.http.RequestHttp;
|
||||
import me.chanjar.weixin.common.util.http.ResponseHandler;
|
||||
import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler;
|
||||
import okhttp3.*;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.methods.*;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.mime.HttpMultipartMode;
|
||||
import org.apache.http.entity.mime.MultipartEntityBuilder;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 通用的上传请求执行器
|
||||
*/
|
||||
public class GenericUploadRequestExecutor implements RequestExecutor<String, InputStream> {
|
||||
|
||||
private final Executor<?, ?> executor;
|
||||
|
||||
/**
|
||||
* 构造通用执行器
|
||||
*
|
||||
* @param requestHttp http请求
|
||||
* @param httpMethod http方法(POST PUT PATCH)
|
||||
* @param paramName 参数名
|
||||
* @param fileName 文件名
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public GenericUploadRequestExecutor(RequestHttp<?, ?> requestHttp, String httpMethod, String paramName, String fileName) {
|
||||
switch (requestHttp.getRequestType()) {
|
||||
case APACHE_HTTP:
|
||||
executor = new ApacheExecutor();
|
||||
break;
|
||||
case OK_HTTP:
|
||||
executor = new OkExecutor();
|
||||
break;
|
||||
case JODD_HTTP:
|
||||
executor = new JoddExecutor();
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("使用了暂不支持的HTTP客户端:" + requestHttp.getRequestType());
|
||||
}
|
||||
executor.setRequestHttp((RequestHttp) requestHttp);
|
||||
executor.setHttpMethod(httpMethod);
|
||||
executor.setParamName(paramName);
|
||||
executor.setFileName(fileName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String execute(String uri, InputStream data, WxType wxType) throws WxErrorException, IOException {
|
||||
String json = executor.execute(uri, data, wxType);
|
||||
WxError error = WxError.fromJson(json, wxType);
|
||||
if (error.getErrorCode() != 0) {
|
||||
throw new WxErrorException(error);
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(String uri, InputStream data, ResponseHandler<String> handler, WxType wxType) throws WxErrorException, IOException {
|
||||
handler.handle(this.execute(uri, data, wxType));
|
||||
}
|
||||
|
||||
/**
|
||||
* 内部请求执行器
|
||||
*
|
||||
* @param <CLIENT> http客户端
|
||||
* @param <PROXY> http代理
|
||||
*/
|
||||
@Data
|
||||
public static abstract class Executor<CLIENT, PROXY> {
|
||||
|
||||
private RequestHttp<CLIENT, PROXY> requestHttp;
|
||||
private String httpMethod;
|
||||
private String paramName;
|
||||
private String fileName;
|
||||
|
||||
public abstract String execute(String uri, InputStream data, WxType wxType) throws WxErrorException, IOException;
|
||||
}
|
||||
|
||||
/**
|
||||
* 阿帕奇执行器
|
||||
*/
|
||||
public static class ApacheExecutor extends Executor<CloseableHttpClient, HttpHost> {
|
||||
|
||||
@Override
|
||||
public String execute(String uri, InputStream data, WxType wxType) throws WxErrorException, IOException {
|
||||
HttpEntityEnclosingRequestBase bodyRequest;
|
||||
switch (getHttpMethod()) {
|
||||
case "POST":
|
||||
bodyRequest = new HttpPost(uri);
|
||||
break;
|
||||
case "PUT":
|
||||
bodyRequest = new HttpPut(uri);
|
||||
break;
|
||||
case "PATCH":
|
||||
bodyRequest = new HttpPatch(uri);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalAccessError("不支持的请求方式:" + getHttpMethod());
|
||||
}
|
||||
if (getRequestHttp().getRequestHttpProxy() != null) {
|
||||
RequestConfig config = RequestConfig.custom().setProxy(getRequestHttp().getRequestHttpProxy()).build();
|
||||
bodyRequest.setConfig(config);
|
||||
}
|
||||
|
||||
HttpEntity entity = MultipartEntityBuilder
|
||||
.create()
|
||||
.addBinaryBody(getParamName(), data, ContentType.create("multipart/form-data", StandardCharsets.UTF_8), getFileName())
|
||||
.setMode(HttpMultipartMode.RFC6532)
|
||||
.build();
|
||||
bodyRequest.setEntity(entity);
|
||||
bodyRequest.setHeader("Content-Type", ContentType.MULTIPART_FORM_DATA.toString());
|
||||
|
||||
try (CloseableHttpResponse response = getRequestHttp().getRequestHttpClient().execute(bodyRequest)) {
|
||||
return Utf8ResponseHandler.INSTANCE.handleResponse(response);
|
||||
} finally {
|
||||
bodyRequest.releaseConnection();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ok执行器
|
||||
*/
|
||||
public static class OkExecutor extends Executor<OkHttpClient, HttpHost> {
|
||||
|
||||
@Override
|
||||
public String execute(String uri, InputStream data, WxType wxType) throws WxErrorException, IOException {
|
||||
OkHttpClient client = getRequestHttp().getRequestHttpClient();
|
||||
|
||||
byte[] bytes = data instanceof ByteArrayInputStream ? ((ByteArrayInputStream) data).readAllBytes() : IOUtils.toByteArray(data);
|
||||
RequestBody body = new MultipartBody.Builder()
|
||||
.setType(Objects.requireNonNull(MediaType.parse("multipart/form-data")))
|
||||
.addFormDataPart("media", getFileName(), RequestBody.create(bytes, MediaType.parse("application/octet-stream")))
|
||||
.build();
|
||||
|
||||
Request request = new Request.Builder().url(uri).method(getHttpMethod(), body).build();
|
||||
Response response = client.newCall(request).execute();
|
||||
return response.body().string();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* jodd执行器
|
||||
*/
|
||||
public static class JoddExecutor extends Executor<HttpConnectionProvider, ProxyInfo> {
|
||||
|
||||
@Override
|
||||
public String execute(String uri, InputStream data, WxType wxType) throws WxErrorException, IOException {
|
||||
HttpRequest request = HttpRequest.post(uri);
|
||||
if (getRequestHttp().getRequestHttpProxy() != null) {
|
||||
getRequestHttp().getRequestHttpClient().useProxy(getRequestHttp().getRequestHttpProxy());
|
||||
}
|
||||
request.withConnectionProvider(getRequestHttp().getRequestHttpClient());
|
||||
|
||||
byte[] bytes = data instanceof ByteArrayInputStream ? ((ByteArrayInputStream) data).readAllBytes() : IOUtils.toByteArray(data);
|
||||
request.form(getParamName(), data);
|
||||
|
||||
HttpResponse response = request.send();
|
||||
response.charset(StandardCharsets.UTF_8.name());
|
||||
return response.bodyText();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user