@@ -6,7 +6,7 @@ | |||
<modelVersion>4.0.0</modelVersion> | |||
<groupId>com.github.binarywang</groupId> | |||
<artifactId>wx-java</artifactId> | |||
<version>3.7.0</version> | |||
<version>3.7.0.B</version> | |||
<packaging>pom</packaging> | |||
<name>WxJava - Weixin/Wechat Java SDK</name> | |||
<description>微信开发Java SDK</description> | |||
@@ -126,11 +126,10 @@ | |||
<artifactId>qrcode-utils</artifactId> | |||
<version>1.1</version> | |||
</dependency> | |||
<!-- 由于jodd-http较新的3.8版本需要jdk8,故而此处采用较低版本 --> | |||
<dependency> | |||
<groupId>org.jodd</groupId> | |||
<artifactId>jodd-http</artifactId> | |||
<version>3.7.1</version> | |||
<version>5.2.0</version> | |||
<scope>provided</scope> | |||
</dependency> | |||
<dependency> | |||
@@ -163,7 +162,7 @@ | |||
<dependency> | |||
<groupId>org.apache.commons</groupId> | |||
<artifactId>commons-lang3</artifactId> | |||
<version>3.5</version> | |||
<version>3.10</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.slf4j</groupId> | |||
@@ -6,7 +6,7 @@ | |||
<parent> | |||
<groupId>com.github.binarywang</groupId> | |||
<artifactId>wx-java</artifactId> | |||
<version>3.7.0</version> | |||
<version>3.7.0.B</version> | |||
</parent> | |||
<packaging>pom</packaging> | |||
<artifactId>wx-java-spring-boot-starters</artifactId> | |||
@@ -5,7 +5,7 @@ | |||
<parent> | |||
<artifactId>wx-java-spring-boot-starters</artifactId> | |||
<groupId>com.github.binarywang</groupId> | |||
<version>3.7.0</version> | |||
<version>3.7.0.B</version> | |||
</parent> | |||
<modelVersion>4.0.0</modelVersion> | |||
@@ -5,7 +5,7 @@ | |||
<parent> | |||
<artifactId>wx-java-spring-boot-starters</artifactId> | |||
<groupId>com.github.binarywang</groupId> | |||
<version>3.7.0</version> | |||
<version>3.7.0.B</version> | |||
</parent> | |||
<modelVersion>4.0.0</modelVersion> | |||
@@ -5,7 +5,7 @@ | |||
<parent> | |||
<artifactId>wx-java-spring-boot-starters</artifactId> | |||
<groupId>com.github.binarywang</groupId> | |||
<version>3.7.0</version> | |||
<version>3.7.0.B</version> | |||
</parent> | |||
<modelVersion>4.0.0</modelVersion> | |||
@@ -5,7 +5,7 @@ | |||
<parent> | |||
<artifactId>wx-java-spring-boot-starters</artifactId> | |||
<groupId>com.github.binarywang</groupId> | |||
<version>3.7.0</version> | |||
<version>3.7.0.B</version> | |||
</parent> | |||
<modelVersion>4.0.0</modelVersion> | |||
@@ -50,6 +50,14 @@ public class WxPayAutoConfiguration { | |||
payConfig.setSubMchId(StringUtils.trimToNull(this.properties.getSubMchId())); | |||
payConfig.setKeyPath(StringUtils.trimToNull(this.properties.getKeyPath())); | |||
//以下是apiv3以及支付分相关 | |||
payConfig.setServiceId(StringUtils.trimToNull(this.properties.getServiceId())); | |||
payConfig.setPayScoreNotifyUrl(StringUtils.trimToNull(this.properties.getPayScoreNotifyUrl())); | |||
payConfig.setPrivateKeyPath(StringUtils.trimToNull(this.properties.getPrivateKeyPath())); | |||
payConfig.setPrivateCertPath(StringUtils.trimToNull(this.properties.getPrivateCertPath())); | |||
payConfig.setCertSerialNo(StringUtils.trimToNull(this.properties.getCertSerialNo())); | |||
payConfig.setApiV3Key(StringUtils.trimToNull(this.properties.getApiv3Key())); | |||
wxPayService.setConfig(payConfig); | |||
return wxPayService; | |||
} | |||
@@ -43,4 +43,34 @@ public class WxPayProperties { | |||
* apiclient_cert.p12文件的绝对路径,或者如果放在项目中,请以classpath:开头指定. | |||
*/ | |||
private String keyPath; | |||
/** | |||
* 微信支付分serviceId | |||
*/ | |||
private String serviceId; | |||
/** | |||
* 证书序列号 | |||
*/ | |||
private String certSerialNo; | |||
/** | |||
* apiV3秘钥 | |||
*/ | |||
private String apiv3Key; | |||
/** | |||
* 微信支付分回调地址 | |||
*/ | |||
private String payScoreNotifyUrl; | |||
/** | |||
* apiv3 商户apiclient_key.pem | |||
*/ | |||
private String privateKeyPath; | |||
/** | |||
* apiv3 商户apiclient_cert.pem | |||
*/ | |||
private String privateCertPath; | |||
} |
@@ -6,7 +6,7 @@ | |||
<parent> | |||
<groupId>com.github.binarywang</groupId> | |||
<artifactId>wx-java</artifactId> | |||
<version>3.7.0</version> | |||
<version>3.7.0.B</version> | |||
</parent> | |||
<artifactId>weixin-graal</artifactId> | |||
@@ -6,7 +6,7 @@ | |||
<parent> | |||
<groupId>com.github.binarywang</groupId> | |||
<artifactId>wx-java</artifactId> | |||
<version>3.7.0</version> | |||
<version>3.7.0.B</version> | |||
</parent> | |||
<artifactId>weixin-java-common</artifactId> | |||
@@ -9,6 +9,12 @@ import java.util.Map; | |||
* @author Daniel Qian & binarywang | |||
*/ | |||
public class WxConsts { | |||
/** | |||
* 微信接口返回的参数errcode. | |||
*/ | |||
public static final String ERR_CODE = "errcode"; | |||
/** | |||
* 微信推送过来的消息的类型,和发送给微信xml格式消息的消息类型. | |||
*/ | |||
@@ -88,7 +88,7 @@ public class WxError implements Serializable { | |||
return "错误代码:" + this.errorCode + ", 错误信息:" + this.errorMsg; | |||
} | |||
return "错误代码:" + this.errorCode + ", 错误信息:" + this.errorMsg + ",微信原始报文:" + this.json; | |||
return "错误代码:" + this.errorCode + ", 错误信息:" + this.errorMsg + ",原始报文:" + this.json; | |||
} | |||
} |
@@ -0,0 +1,23 @@ | |||
package me.chanjar.weixin.common.error; | |||
/** | |||
* WxJava专用的runtime exception. | |||
* | |||
* @author <a href="https://github.com/binarywang">Binary Wang</a> | |||
* @date 2020-09-26 | |||
*/ | |||
public class WxRuntimeException extends RuntimeException { | |||
private static final long serialVersionUID = 4881698471192264412L; | |||
public WxRuntimeException(Throwable e) { | |||
super(e); | |||
} | |||
public WxRuntimeException(String msg) { | |||
super(msg); | |||
} | |||
public WxRuntimeException(String msg, Throwable e) { | |||
super(msg, e); | |||
} | |||
} |
@@ -1,15 +1,20 @@ | |||
package me.chanjar.weixin.common.util.http.apache; | |||
import lombok.extern.slf4j.Slf4j; | |||
import me.chanjar.weixin.common.WxType; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.util.http.RequestHttp; | |||
import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; | |||
import me.chanjar.weixin.common.util.http.WxDnsResolver; | |||
import org.apache.http.Header; | |||
import org.apache.http.HttpHost; | |||
import org.apache.http.client.config.RequestConfig; | |||
import org.apache.http.client.methods.CloseableHttpResponse; | |||
import org.apache.http.client.methods.HttpGet; | |||
import org.apache.http.impl.client.CloseableHttpClient; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import java.io.IOException; | |||
@@ -20,6 +25,7 @@ import java.io.IOException; | |||
* @date 2017/5/4 | |||
*/ | |||
public class ApacheHttpClientSimpleGetRequestExecutor extends SimpleGetRequestExecutor<CloseableHttpClient, HttpHost> { | |||
protected final Logger log = LoggerFactory.getLogger(this.getClass()); | |||
public ApacheHttpClientSimpleGetRequestExecutor(RequestHttp requestHttp) { | |||
super(requestHttp); | |||
} | |||
@@ -39,6 +45,11 @@ public class ApacheHttpClientSimpleGetRequestExecutor extends SimpleGetRequestEx | |||
} | |||
try (CloseableHttpResponse response = requestHttp.getRequestHttpClient().execute(httpGet)) { | |||
// Header[] allHeaders = response.getAllHeaders(); | |||
// for (Header header:allHeaders) { | |||
// log.info("\n【header】:"+header.getName()+"="+header.getValue()); | |||
// } | |||
String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response); | |||
WxError error = WxError.fromJson(responseContent, wxType); | |||
if (error.getErrorCode() != 0) { | |||
@@ -4,7 +4,6 @@ import jodd.http.HttpConnectionProvider; | |||
import jodd.http.HttpRequest; | |||
import jodd.http.HttpResponse; | |||
import jodd.http.ProxyInfo; | |||
import jodd.util.StringPool; | |||
import me.chanjar.weixin.common.WxType; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
@@ -19,6 +18,8 @@ import java.io.ByteArrayInputStream; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.nio.charset.StandardCharsets; | |||
/** | |||
* . | |||
@@ -47,7 +48,7 @@ public class JoddHttpMediaDownloadRequestExecutor extends BaseMediaDownloadReque | |||
request.withConnectionProvider(requestHttp.getRequestHttpClient()); | |||
HttpResponse response = request.send(); | |||
response.charset(StringPool.UTF_8); | |||
response.charset(StandardCharsets.UTF_8.name()); | |||
String contentType = response.header("Content-Type"); | |||
if (contentType != null && contentType.startsWith("application/json")) { | |||
@@ -4,7 +4,6 @@ import jodd.http.HttpConnectionProvider; | |||
import jodd.http.HttpRequest; | |||
import jodd.http.HttpResponse; | |||
import jodd.http.ProxyInfo; | |||
import jodd.util.StringPool; | |||
import me.chanjar.weixin.common.WxType; | |||
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | |||
import me.chanjar.weixin.common.error.WxError; | |||
@@ -14,6 +13,7 @@ import me.chanjar.weixin.common.util.http.RequestHttp; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.nio.charset.StandardCharsets; | |||
/** | |||
* . | |||
@@ -35,7 +35,7 @@ public class JoddHttpMediaUploadRequestExecutor extends MediaUploadRequestExecut | |||
request.withConnectionProvider(requestHttp.getRequestHttpClient()); | |||
request.form("media", file); | |||
HttpResponse response = request.send(); | |||
response.charset(StringPool.UTF_8); | |||
response.charset(StandardCharsets.UTF_8.name()); | |||
String responseContent = response.bodyText(); | |||
WxError error = WxError.fromJson(responseContent, wxType); | |||
@@ -4,7 +4,6 @@ import jodd.http.HttpConnectionProvider; | |||
import jodd.http.HttpRequest; | |||
import jodd.http.HttpResponse; | |||
import jodd.http.ProxyInfo; | |||
import jodd.util.StringPool; | |||
import me.chanjar.weixin.common.WxType; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
@@ -12,6 +11,7 @@ import me.chanjar.weixin.common.util.http.RequestHttp; | |||
import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor; | |||
import java.io.IOException; | |||
import java.nio.charset.StandardCharsets; | |||
/** | |||
* . | |||
@@ -39,7 +39,7 @@ public class JoddHttpSimpleGetRequestExecutor extends SimpleGetRequestExecutor<H | |||
} | |||
request.withConnectionProvider(requestHttp.getRequestHttpClient()); | |||
HttpResponse response = request.send(); | |||
response.charset(StringPool.UTF_8); | |||
response.charset(StandardCharsets.UTF_8.name()); | |||
String responseContent = response.bodyText(); | |||
@@ -4,7 +4,6 @@ import jodd.http.HttpConnectionProvider; | |||
import jodd.http.HttpRequest; | |||
import jodd.http.HttpResponse; | |||
import jodd.http.ProxyInfo; | |||
import jodd.util.StringPool; | |||
import me.chanjar.weixin.common.WxType; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
@@ -12,6 +11,7 @@ import me.chanjar.weixin.common.util.http.RequestHttp; | |||
import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor; | |||
import java.io.IOException; | |||
import java.nio.charset.StandardCharsets; | |||
/** | |||
* . | |||
@@ -38,7 +38,7 @@ public class JoddHttpSimplePostRequestExecutor extends SimplePostRequestExecutor | |||
request.bodyText(postEntity); | |||
} | |||
HttpResponse response = request.send(); | |||
response.charset(StringPool.UTF_8); | |||
response.charset(StandardCharsets.UTF_8.name()); | |||
String responseContent = response.bodyText(); | |||
if (responseContent.isEmpty()) { | |||
@@ -0,0 +1,26 @@ | |||
package me.chanjar.weixin.common.util.json; | |||
import com.google.gson.JsonObject; | |||
import com.google.gson.JsonParser; | |||
import com.google.gson.stream.JsonReader; | |||
import java.io.Reader; | |||
/** | |||
* @author niefy | |||
*/ | |||
public class GsonParser { | |||
private static final JsonParser JSON_PARSER = new JsonParser(); | |||
public static JsonObject parse(String json) { | |||
return JSON_PARSER.parse(json).getAsJsonObject(); | |||
} | |||
public static JsonObject parse(Reader json) { | |||
return JSON_PARSER.parse(json).getAsJsonObject(); | |||
} | |||
public static JsonObject parse(JsonReader json) { | |||
return JSON_PARSER.parse(json).getAsJsonObject(); | |||
} | |||
} |
@@ -18,9 +18,18 @@ public class WxErrorAdapter implements JsonDeserializer<WxError> { | |||
if (wxErrorJsonObject.get("errcode") != null && !wxErrorJsonObject.get("errcode").isJsonNull()) { | |||
errorBuilder.errorCode(GsonHelper.getAsPrimitiveInt(wxErrorJsonObject.get("errcode"))); | |||
} else if(wxErrorJsonObject.get("err_no") != null && !wxErrorJsonObject.get("err_no").isJsonNull()) { | |||
errorBuilder.errorCode(GsonHelper.getAsPrimitiveInt(wxErrorJsonObject.get("err_no"))); | |||
} else if(wxErrorJsonObject.get("error_code") != null && !wxErrorJsonObject.get("error_code").isJsonNull()){ | |||
errorBuilder.errorCode(GsonHelper.getAsPrimitiveInt(wxErrorJsonObject.get("error_code"))); | |||
} | |||
if (wxErrorJsonObject.get("errmsg") != null && !wxErrorJsonObject.get("errmsg").isJsonNull()) { | |||
errorBuilder.errorMsg(GsonHelper.getAsString(wxErrorJsonObject.get("errmsg"))); | |||
} else if (wxErrorJsonObject.get("err_tips") != null && !wxErrorJsonObject.get("err_tips").isJsonNull()) { | |||
errorBuilder.errorMsg(GsonHelper.getAsString(wxErrorJsonObject.get("err_tips"))); | |||
} else if (wxErrorJsonObject.get("description") != null && !wxErrorJsonObject.get("description").isJsonNull()) { | |||
errorBuilder.errorMsg(GsonHelper.getAsString(wxErrorJsonObject.get("description"))); | |||
} | |||
errorBuilder.json(json.toString()); | |||
@@ -7,7 +7,7 @@ | |||
<parent> | |||
<groupId>com.github.binarywang</groupId> | |||
<artifactId>wx-java</artifactId> | |||
<version>3.7.0</version> | |||
<version>3.7.0.B</version> | |||
</parent> | |||
<artifactId>weixin-java-cp</artifactId> | |||
@@ -3,8 +3,8 @@ package me.chanjar.weixin.cp.api.impl; | |||
import jodd.http.HttpConnectionProvider; | |||
import jodd.http.HttpRequest; | |||
import jodd.http.HttpResponse; | |||
import jodd.http.JoddHttp; | |||
import jodd.http.ProxyInfo; | |||
import jodd.http.net.SocketHttpConnectionProvider; | |||
import me.chanjar.weixin.common.WxType; | |||
import me.chanjar.weixin.common.bean.WxAccessToken; | |||
import me.chanjar.weixin.common.error.WxError; | |||
@@ -68,7 +68,7 @@ public class WxCpServiceJoddHttpImpl extends BaseWxCpServiceImpl<HttpConnectionP | |||
configStorage.getHttpProxyPort(), configStorage.getHttpProxyUsername(), configStorage.getHttpProxyPassword()); | |||
} | |||
httpClient = JoddHttp.httpConnectionProvider; | |||
httpClient = new SocketHttpConnectionProvider(); | |||
} | |||
@Override | |||
@@ -7,7 +7,7 @@ | |||
<parent> | |||
<groupId>com.github.binarywang</groupId> | |||
<artifactId>wx-java</artifactId> | |||
<version>3.7.0</version> | |||
<version>3.7.0.B</version> | |||
</parent> | |||
<artifactId>weixin-java-miniapp</artifactId> | |||
@@ -0,0 +1,62 @@ | |||
package cn.binarywang.wx.miniapp.api; | |||
import cn.binarywang.wx.miniapp.bean.WxMaGetLiveInfo; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import java.util.List; | |||
/** | |||
* <pre> | |||
* 直播相关操作接口. | |||
* Created by yjwang on 2020/4/5. | |||
* </pre> | |||
* | |||
* @author <a href="https://github.com/yjwang3300300">yjwang</a> | |||
*/ | |||
public interface WxMaLiveService { | |||
String GET_LIVE_INFO = "https://api.weixin.qq.com/wxa/business/getliveinfo"; | |||
/** | |||
* 获取直播房间列表.(分页) | |||
* | |||
* @param start 起始拉取房间,start = 0 表示从第 1 个房间开始拉取 | |||
* @param limit 每次拉取的个数上限,不要设置过大,建议 100 以内 | |||
* @return . | |||
* @throws WxErrorException . | |||
*/ | |||
WxMaGetLiveInfo getLiveInfo(Integer start, Integer limit) throws WxErrorException; | |||
/** | |||
* 获取所有直播间信息(没有分页直接获取全部) | |||
* @return | |||
* @throws WxErrorException | |||
*/ | |||
List<WxMaGetLiveInfo.RoomInfo> getLiveinfos() throws WxErrorException; | |||
/** | |||
* | |||
* 获取直播房间回放数据信息. | |||
* | |||
* @param action 获取回放 | |||
* @param room_id 直播间 id | |||
* @param start 起始拉取视频,start = 0 表示从第 1 个视频片段开始拉取 | |||
* @param limit 每次拉取的个数上限,不要设置过大,建议 100 以内 | |||
* @return | |||
* @throws WxErrorException | |||
*/ | |||
WxMaGetLiveInfo getLiveReplay(String action, Integer room_id, Integer start, Integer limit) throws WxErrorException; | |||
/** | |||
* | |||
* 获取直播房间回放数据信息. | |||
* | |||
* 获取回放 (默认:get_replay) | |||
* @param room_id 直播间 id | |||
* @param start 起始拉取视频,start = 0 表示从第 1 个视频片段开始拉取 | |||
* @param limit 每次拉取的个数上限,不要设置过大,建议 100 以内 | |||
* @return | |||
* @throws WxErrorException | |||
*/ | |||
WxMaGetLiveInfo getLiveReplay(Integer room_id, Integer start, Integer limit) throws WxErrorException; | |||
} |
@@ -0,0 +1,36 @@ | |||
package cn.binarywang.wx.miniapp.api; | |||
import cn.binarywang.wx.miniapp.bean.scheme.WxMaGenerateNfcSchemeRequest; | |||
import cn.binarywang.wx.miniapp.bean.scheme.WxMaGenerateSchemeRequest; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
/** | |||
* <pre> | |||
* 小程序Scheme码相关操作接口. | |||
* | |||
* | |||
* </pre> | |||
* | |||
* @author : cofedream | |||
* created on : 2021-01-26 | |||
*/ | |||
public interface WxMaSchemeService { | |||
String GENERATE_SCHEME_URL = "https://api.weixin.qq.com/wxa/generatescheme"; | |||
String GENERATE_NFC_SCHEME_URL = "https://api.weixin.qq.com/wxa/generatenfcscheme"; | |||
/** | |||
* 获取小程序scheme码 | |||
*文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/url-scheme/urlscheme.generate.html | |||
* @param request 请求参数 | |||
* @throws WxErrorException 生成失败时抛出,具体错误码请看文档 | |||
*/ | |||
String generate(WxMaGenerateSchemeRequest request) throws WxErrorException; | |||
/** | |||
* 获取NFC 的小程序 scheme | |||
*文档地址:https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/qrcode-link/url-scheme/generateNFCScheme.html | |||
* @param request 请求参数 | |||
* @throws WxErrorException 生成失败时抛出,具体错误码请看文档 | |||
*/ | |||
String generateNFC(WxMaGenerateNfcSchemeRequest request) throws WxErrorException; | |||
} |
@@ -156,6 +156,13 @@ public interface WxMaService { | |||
*/ | |||
WxMaQrcodeService getQrcodeService(); | |||
/** | |||
* 返回获取小程序scheme码实现对象,以方便调用其各个接口. | |||
* | |||
* @return WxMaSchemeService wx ma scheme service | |||
*/ | |||
WxMaSchemeService getWxMaSchemeService(); | |||
/** | |||
* 返回模板配置相关接口方法的实现类对象, 以方便调用其各个接口. | |||
* | |||
@@ -247,4 +254,11 @@ public interface WxMaService { | |||
* 获取云开发接口服务对象 | |||
*/ | |||
WxMaCloudService getCloudService(); | |||
/** | |||
* 获取直播接口服务对象 | |||
* | |||
* @return . | |||
*/ | |||
WxMaLiveService getLiveService(); | |||
} |
@@ -0,0 +1,100 @@ | |||
package cn.binarywang.wx.miniapp.api.impl; | |||
import cn.binarywang.wx.miniapp.api.WxMaLiveService; | |||
import cn.binarywang.wx.miniapp.api.WxMaService; | |||
import cn.binarywang.wx.miniapp.bean.WxMaGetLiveInfo; | |||
import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; | |||
import com.google.gson.JsonObject; | |||
import com.google.gson.JsonParser; | |||
import lombok.AllArgsConstructor; | |||
import me.chanjar.weixin.common.WxType; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import java.util.ArrayList; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
/** | |||
* <pre> | |||
* Created by yjwang on 2020/4/5. | |||
* </pre> | |||
* | |||
* @author <a href="https://github.com/yjwang3300300">yjwang</a> | |||
*/ | |||
@AllArgsConstructor | |||
public class WxMaLiveServiceImpl implements WxMaLiveService { | |||
private static final JsonParser JSON_PARSER = new JsonParser(); | |||
private WxMaService service; | |||
@Override | |||
public WxMaGetLiveInfo getLiveInfo(Integer start, Integer limit) throws WxErrorException { | |||
JsonObject jsonObject = getJsonObject(start, limit, null); | |||
return WxMaGetLiveInfo.fromJson(jsonObject.toString()); | |||
} | |||
@Override | |||
public List<WxMaGetLiveInfo.RoomInfo> getLiveinfos() throws WxErrorException { | |||
List<WxMaGetLiveInfo.RoomInfo> results = new ArrayList<>(); | |||
Integer start = 0; | |||
Integer limit = 80; | |||
Integer tatal = 0; | |||
WxMaGetLiveInfo liveInfo = null; | |||
do { | |||
if (tatal != 0 && tatal <= start) { | |||
break; | |||
} | |||
liveInfo = getLiveInfo(start, limit); | |||
if (liveInfo == null) { | |||
return null; | |||
} | |||
results.addAll(liveInfo.getRoomInfos()); | |||
tatal = liveInfo.getTotal(); | |||
start = results.size(); | |||
try { | |||
Thread.sleep(100); | |||
} catch (InterruptedException e) { | |||
e.printStackTrace(); | |||
} | |||
} while (results.size() <= tatal); | |||
return results; | |||
} | |||
@Override | |||
public WxMaGetLiveInfo getLiveReplay(String action, Integer room_id, Integer start, Integer limit) throws WxErrorException { | |||
Map<String, Object> map = new HashMap(4); | |||
map.put("action", action); | |||
map.put("room_id", room_id); | |||
JsonObject jsonObject = getJsonObject(start, limit, map); | |||
return WxMaGetLiveInfo.fromJson(jsonObject.toString()); | |||
} | |||
@Override | |||
public WxMaGetLiveInfo getLiveReplay(Integer room_id, Integer start, Integer limit) throws WxErrorException { | |||
return getLiveReplay("get_replay", room_id, start, limit); | |||
} | |||
/** | |||
* 包装一下 | |||
* | |||
* @param start | |||
* @param limit | |||
* @param map | |||
* @return | |||
* @throws WxErrorException | |||
*/ | |||
private JsonObject getJsonObject(Integer start, Integer limit, Map<String, Object> map) throws WxErrorException { | |||
if (map == null) { | |||
map = new HashMap(2); | |||
} | |||
map.put("start", start); | |||
map.put("limit", limit); | |||
String responseContent = service.post(GET_LIVE_INFO, WxMaGsonBuilder.create().toJson(map)); | |||
JsonObject jsonObject = JSON_PARSER.parse(responseContent).getAsJsonObject(); | |||
if (jsonObject.get("errcode").getAsInt() != 0) { | |||
throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); | |||
} | |||
return jsonObject; | |||
} | |||
} |
@@ -0,0 +1,56 @@ | |||
package cn.binarywang.wx.miniapp.api.impl; | |||
import cn.binarywang.wx.miniapp.api.WxMaSchemeService; | |||
import cn.binarywang.wx.miniapp.api.WxMaService; | |||
import cn.binarywang.wx.miniapp.bean.scheme.WxMaGenerateNfcSchemeRequest; | |||
import cn.binarywang.wx.miniapp.bean.scheme.WxMaGenerateSchemeRequest; | |||
import com.google.gson.JsonObject; | |||
import lombok.AllArgsConstructor; | |||
import me.chanjar.weixin.common.WxType; | |||
import me.chanjar.weixin.common.api.WxConsts; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.util.json.GsonParser; | |||
/** | |||
* @author : cofedream | |||
* created on : 2021-01-28 | |||
*/ | |||
@AllArgsConstructor | |||
public class WxMaSchemeServiceImpl implements WxMaSchemeService { | |||
private final WxMaService wxMaService; | |||
/** | |||
* 获取小程序scheme码 | |||
* 文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/url-scheme/urlscheme.generate.html | |||
* | |||
* @param request 请求参数 | |||
* @throws WxErrorException 生成失败时抛出,具体错误码请看文档 | |||
*/ | |||
@Override | |||
public String generate(WxMaGenerateSchemeRequest request) throws WxErrorException { | |||
String responseContent = this.wxMaService.post(GENERATE_SCHEME_URL, request.toJson()); | |||
JsonObject jsonObject = GsonParser.parse(responseContent); | |||
if (jsonObject.get(WxConsts.ERR_CODE).getAsInt() != 0) { | |||
throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); | |||
} | |||
return jsonObject.get("openlink").getAsString(); | |||
} | |||
/** | |||
* 获取NFC 的小程序 scheme | |||
* 文档地址:https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/qrcode-link/url-scheme/generateNFCScheme.html | |||
* | |||
* @param request 请求参数 | |||
* @throws WxErrorException 生成失败时抛出,具体错误码请看文档 | |||
*/ | |||
@Override | |||
public String generateNFC(WxMaGenerateNfcSchemeRequest request) throws WxErrorException { | |||
String responseContent = this.wxMaService.post(GENERATE_NFC_SCHEME_URL, request.toJson()); | |||
JsonObject jsonObject = GsonParser.parse(responseContent); | |||
if (jsonObject.get(WxConsts.ERR_CODE).getAsInt() != 0) { | |||
throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); | |||
} | |||
return jsonObject.get("openlink").getAsString(); | |||
} | |||
} |
@@ -46,6 +46,7 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl | |||
private WxMaMediaService materialService = new WxMaMediaServiceImpl(this); | |||
private WxMaUserService userService = new WxMaUserServiceImpl(this); | |||
private WxMaQrcodeService qrCodeService = new WxMaQrcodeServiceImpl(this); | |||
private WxMaSchemeService schemeService = new WxMaSchemeServiceImpl(this); | |||
private WxMaTemplateService templateService = new WxMaTemplateServiceImpl(this); | |||
private WxMaAnalysisService analysisService = new WxMaAnalysisServiceImpl(this); | |||
private WxMaCodeService codeService = new WxMaCodeServiceImpl(this); | |||
@@ -58,6 +59,7 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl | |||
private WxMaExpressService expressService = new WxMaExpressServiceImpl(this); | |||
private WxMaSubscribeService subscribeService = new WxMaSubscribeServiceImpl(this); | |||
private WxMaCloudService cloudService = new WxMaCloudServiceImpl(this); | |||
private WxMaLiveService liveService = new WxMaLiveServiceImpl(this); | |||
private int retrySleepMillis = 1000; | |||
private int maxRetryTimes = 5; | |||
@@ -330,6 +332,11 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl | |||
return this.qrCodeService; | |||
} | |||
@Override | |||
public WxMaSchemeService getWxMaSchemeService() { | |||
return schemeService; | |||
} | |||
@Override | |||
public WxMaTemplateService getTemplateService() { | |||
return this.templateService; | |||
@@ -389,4 +396,9 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl | |||
public WxMaCloudService getCloudService() { | |||
return this.cloudService; | |||
} | |||
@Override | |||
public WxMaLiveService getLiveService() { | |||
return this.liveService; | |||
} | |||
} |
@@ -0,0 +1,88 @@ | |||
package cn.binarywang.wx.miniapp.bean; | |||
import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.Data; | |||
import java.io.Serializable; | |||
import java.util.List; | |||
/** | |||
* 获取直播房间列表 | |||
* | |||
* @author yjwang | |||
* @date 2020/4/5 | |||
*/ | |||
@Data | |||
public class WxMaGetLiveInfo implements Serializable { | |||
private static final long serialVersionUID = 7285263767524755887L; | |||
private Integer errcode; | |||
private String errmsg; | |||
private Integer total; | |||
/** | |||
* 直播间列表 | |||
*/ | |||
@SerializedName("room_info") | |||
private List<RoomInfo> roomInfos; | |||
/** | |||
* 获取回放源视频列表 | |||
*/ | |||
@SerializedName("live_replay") | |||
private List<LiveReplay> liveReplay; | |||
public static WxMaGetLiveInfo fromJson(String json) { | |||
return WxMaGsonBuilder.create().fromJson(json, WxMaGetLiveInfo.class); | |||
} | |||
/** | |||
* 直播列表 | |||
*/ | |||
@Data | |||
public static class RoomInfo implements Serializable { | |||
private static final long serialVersionUID = 7745775280267417154L; | |||
private String name; | |||
private Integer roomid; | |||
@SerializedName("cover_img") | |||
private String coverImg; | |||
@SerializedName("live_status") | |||
private Integer liveStatus; | |||
@SerializedName("start_time") | |||
private Long startTime; | |||
@SerializedName("end_time") | |||
private Long endTime; | |||
@SerializedName("anchor_name") | |||
private String anchorName; | |||
@SerializedName("anchor_img") | |||
private String anchorImg; | |||
private List<Goods> goods; | |||
} | |||
/** | |||
* 商品列表 | |||
*/ | |||
@Data | |||
public static class Goods implements Serializable { | |||
private static final long serialVersionUID = 5769245932149287574L; | |||
@SerializedName("cover_img") | |||
private String coverImg; | |||
private String url; | |||
private String price; | |||
private String name; | |||
} | |||
/** | |||
* 回放数据列表 | |||
*/ | |||
@Data | |||
public static class LiveReplay implements Serializable { | |||
private static final long serialVersionUID = 7683927205627536320L; | |||
@SerializedName("expire_time") | |||
private String expireTime; | |||
@SerializedName("create_time") | |||
private String createTime; | |||
@SerializedName("media_url") | |||
private String mediaUrl; | |||
} | |||
} |
@@ -4,6 +4,7 @@ import java.io.Serializable; | |||
import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; | |||
import lombok.Data; | |||
import lombok.extern.slf4j.Slf4j; | |||
/** | |||
* 微信用户绑定的手机号相关信息 | |||
@@ -0,0 +1,75 @@ | |||
package cn.binarywang.wx.miniapp.bean.scheme; | |||
import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.Builder; | |||
import lombok.Data; | |||
/** | |||
* @author : lyt | |||
* created on : 2023-07-31 | |||
*/ | |||
@Data | |||
@Builder(builderMethodName = "newBuilder") | |||
public class WxMaGenerateNfcSchemeRequest { | |||
/** | |||
* 跳转到的目标小程序信息。 | |||
* <pre> | |||
* 是否必填:否 | |||
* </pre> | |||
*/ | |||
@SerializedName("jump_wxa") | |||
private JumpWxa jumpWxa; | |||
/** | |||
* scheme对应的设备model_id | |||
* <pre> | |||
* 是否必填:是 | |||
* </pre> | |||
*/ | |||
@SerializedName("model_id") | |||
private String modelId; | |||
/** | |||
* scheme对应的设备sn,仅一机一码时填写 | |||
* <pre> | |||
* 是否必填:否 | |||
* </pre> | |||
*/ | |||
@SerializedName("sn") | |||
private String sn; | |||
@Data | |||
@Builder(builderMethodName = "newBuilder") | |||
public static class JumpWxa { | |||
/** | |||
* 通过scheme码进入的小程序页面路径,必须是已经发布的小程序存在的页面,不可携带query。path为空时会跳转小程序主页。 | |||
* <pre> | |||
* 是否必填:是 | |||
* </pre> | |||
*/ | |||
@SerializedName("path") | |||
private String path; | |||
/** | |||
* 通过scheme码进入小程序时的query,最大128个字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~ | |||
* 返回值 | |||
* <pre> | |||
* 是否必填:是 | |||
* </pre> | |||
*/ | |||
@SerializedName("query") | |||
private String query; | |||
/** | |||
* 要打开的小程序版本。正式版为"release",体验版为"trial",开发版为"develop"默认值:release | |||
*/ | |||
@SerializedName("env_version") | |||
private String envVersion = "release"; | |||
} | |||
public String toJson() { | |||
return WxMaGsonBuilder.create().toJson(this); | |||
} | |||
} |
@@ -0,0 +1,94 @@ | |||
package cn.binarywang.wx.miniapp.bean.scheme; | |||
import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.Builder; | |||
import lombok.Data; | |||
/** | |||
* @author : cofedream | |||
* created on : 2021-01-26 | |||
*/ | |||
@Data | |||
@Builder(builderMethodName = "newBuilder") | |||
public class WxMaGenerateSchemeRequest { | |||
/** | |||
* 跳转到的目标小程序信息。 | |||
* <pre> | |||
* 是否必填:否 | |||
* </pre> | |||
*/ | |||
@SerializedName("jump_wxa") | |||
private JumpWxa jumpWxa; | |||
/** | |||
* 生成的scheme码类型,到期失效:true,永久有效:false。 | |||
* <pre> | |||
* 是否必填:否 | |||
* </pre> | |||
*/ | |||
@SerializedName("is_expire") | |||
private Boolean isExpire; | |||
/** | |||
* 到期失效的scheme码的失效时间,为Unix时间戳。生成的到期失效scheme码在该时间前有效。最长有效期为1年。生成到期失效的scheme时必填。 | |||
* <pre> | |||
* 是否必填:否 | |||
* </pre> | |||
*/ | |||
@SerializedName("expire_time") | |||
private Long expireTime; | |||
/** | |||
* 到期失效的 scheme 码失效类型,失效时间:0,失效间隔天数:1 | |||
* <pre> | |||
* 是否必填:否 | |||
* </pre> | |||
*/ | |||
@SerializedName("expire_type") | |||
private Integer expireType; | |||
/** | |||
* 到期失效的 scheme 码的失效间隔天数。 | |||
* <pre> | |||
* 生成的到期失效 scheme 码在该间隔时间到达前有效。最长间隔天数为365天。is_expire 为 true 且 expire_type 为 1 时必填 * <pre> | |||
* 是否必填:否 | |||
* </pre> | |||
*/ | |||
@SerializedName("expire_interval") | |||
private Integer expireInterval; | |||
@Data | |||
@Builder(builderMethodName = "newBuilder") | |||
public static class JumpWxa { | |||
/** | |||
* 通过scheme码进入的小程序页面路径,必须是已经发布的小程序存在的页面,不可携带query。path为空时会跳转小程序主页。 | |||
* <pre> | |||
* 是否必填:是 | |||
* </pre> | |||
*/ | |||
@SerializedName("path") | |||
private String path; | |||
/** | |||
* 通过scheme码进入小程序时的query,最大128个字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~ | |||
* 返回值 | |||
* <pre> | |||
* 是否必填:是 | |||
* </pre> | |||
*/ | |||
@SerializedName("query") | |||
private String query; | |||
/** | |||
* 要打开的小程序版本。正式版为"release",体验版为"trial",开发版为"develop"默认值:release | |||
*/ | |||
@SerializedName("env_version") | |||
private String envVersion = "release"; | |||
} | |||
public String toJson() { | |||
return WxMaGsonBuilder.create().toJson(this); | |||
} | |||
} |
@@ -0,0 +1,55 @@ | |||
package cn.binarywang.wx.miniapp.api.impl; | |||
import cn.binarywang.wx.miniapp.api.WxMaService; | |||
import cn.binarywang.wx.miniapp.bean.WxMaGetLiveInfo; | |||
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; | |||
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo; | |||
import cn.binarywang.wx.miniapp.test.ApiTestModule; | |||
import cn.binarywang.wx.miniapp.test.TestConfig; | |||
import com.google.common.collect.ImmutableMap; | |||
import com.google.gson.JsonObject; | |||
import com.google.inject.Inject; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
import org.testng.annotations.Guice; | |||
import org.testng.annotations.Test; | |||
import java.util.List; | |||
import java.util.stream.Collectors; | |||
import static org.testng.Assert.assertNotNull; | |||
import static org.testng.Assert.assertTrue; | |||
/** | |||
* 测试直播相关的接口 | |||
* | |||
* @author <a href="https://github.com/yjwang3300300">yjwang</a> | |||
*/ | |||
@Test | |||
@Guice(modules = ApiTestModule.class) | |||
public class WxMaLiveServiceImplTest { | |||
@Inject | |||
private WxMaService wxService; | |||
@Test | |||
public void getLiveInfo() throws Exception { | |||
WxMaGetLiveInfo list = this.wxService.getLiveService().getLiveInfo(0,10); | |||
assertNotNull(list); | |||
System.out.println(list.toString()); | |||
} | |||
@Test | |||
public void getLiveReplay() throws Exception { | |||
// [12, 11, 10, 9, 8, 7, 6, 5, 3, 2] | |||
WxMaGetLiveInfo list = this.wxService.getLiveService().getLiveReplay(11,0,10); | |||
assertNotNull(list); | |||
System.out.println(list.toString()); | |||
} | |||
@Test | |||
public void getLiveinfos() throws Exception { | |||
List<WxMaGetLiveInfo.RoomInfo> list = this.wxService.getLiveService().getLiveinfos(); | |||
assertNotNull(list); | |||
System.out.println(list.toString()); | |||
} | |||
} |
@@ -7,7 +7,7 @@ | |||
<parent> | |||
<groupId>com.github.binarywang</groupId> | |||
<artifactId>wx-java</artifactId> | |||
<version>3.7.0</version> | |||
<version>3.7.0.B</version> | |||
</parent> | |||
<artifactId>weixin-java-mp</artifactId> | |||
@@ -46,7 +46,7 @@ public class WxMpServiceJoddHttpImpl extends BaseWxMpServiceImpl<HttpConnectionP | |||
httpProxy = new ProxyInfo(ProxyInfo.ProxyType.HTTP, configStorage.getHttpProxyHost(), configStorage.getHttpProxyPort(), configStorage.getHttpProxyUsername(), configStorage.getHttpProxyPassword()); | |||
} | |||
httpClient = JoddHttp.httpConnectionProvider; | |||
httpClient = new SocketHttpConnectionProvider(); | |||
} | |||
@Override | |||
@@ -4,7 +4,6 @@ import jodd.http.HttpConnectionProvider; | |||
import jodd.http.HttpRequest; | |||
import jodd.http.HttpResponse; | |||
import jodd.http.ProxyInfo; | |||
import jodd.util.StringPool; | |||
import me.chanjar.weixin.common.WxType; | |||
import me.chanjar.weixin.common.error.WxError; | |||
@@ -12,6 +11,7 @@ import me.chanjar.weixin.common.error.WxErrorException; | |||
import me.chanjar.weixin.common.util.http.RequestHttp; | |||
import java.io.IOException; | |||
import java.nio.charset.StandardCharsets; | |||
/** | |||
* Created by ecoolper on 2017/5/5. | |||
@@ -31,7 +31,7 @@ public class MaterialDeleteJoddHttpRequestExecutor extends MaterialDeleteRequest | |||
request.query("media_id", materialId); | |||
HttpResponse response = request.send(); | |||
response.charset(StringPool.UTF_8); | |||
response.charset(StandardCharsets.UTF_8.name()); | |||
String responseContent = response.bodyText(); | |||
WxError error = WxError.fromJson(responseContent, WxType.MP); | |||
if (error.getErrorCode() != 0) { | |||
@@ -5,7 +5,6 @@ import jodd.http.HttpConnectionProvider; | |||
import jodd.http.HttpRequest; | |||
import jodd.http.HttpResponse; | |||
import jodd.http.ProxyInfo; | |||
import jodd.util.StringPool; | |||
import me.chanjar.weixin.common.WxType; | |||
import me.chanjar.weixin.common.error.WxError; | |||
@@ -18,6 +17,7 @@ import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import java.io.IOException; | |||
import java.nio.charset.StandardCharsets; | |||
/** | |||
* Created by ecoolper on 2017/5/5. | |||
@@ -38,7 +38,7 @@ public class MaterialNewsInfoJoddHttpRequestExecutor extends MaterialNewsInfoReq | |||
.withConnectionProvider(requestHttp.getRequestHttpClient()) | |||
.body(WxGsonBuilder.create().toJson(ImmutableMap.of("media_id", materialId))); | |||
HttpResponse response = request.send(); | |||
response.charset(StringPool.UTF_8); | |||
response.charset(StandardCharsets.UTF_8.name()); | |||
String responseContent = response.bodyText(); | |||
this.logger.debug("响应原始数据:{}", responseContent); | |||
@@ -4,7 +4,6 @@ import jodd.http.HttpConnectionProvider; | |||
import jodd.http.HttpRequest; | |||
import jodd.http.HttpResponse; | |||
import jodd.http.ProxyInfo; | |||
import jodd.util.StringPool; | |||
import me.chanjar.weixin.common.WxType; | |||
import me.chanjar.weixin.common.error.WxError; | |||
@@ -17,6 +16,7 @@ import me.chanjar.weixin.mp.bean.material.WxMpMaterialUploadResult; | |||
import java.io.File; | |||
import java.io.FileNotFoundException; | |||
import java.io.IOException; | |||
import java.nio.charset.StandardCharsets; | |||
import java.util.Map; | |||
/** | |||
@@ -50,7 +50,7 @@ public class MaterialUploadJoddHttpRequestExecutor extends MaterialUploadRequest | |||
} | |||
HttpResponse response = request.send(); | |||
response.charset(StringPool.UTF_8); | |||
response.charset(StandardCharsets.UTF_8.name()); | |||
String responseContent = response.bodyText(); | |||
WxError error = WxError.fromJson(responseContent, WxType.MP); | |||
if (error.getErrorCode() != 0) { | |||
@@ -4,7 +4,6 @@ import jodd.http.HttpConnectionProvider; | |||
import jodd.http.HttpRequest; | |||
import jodd.http.HttpResponse; | |||
import jodd.http.ProxyInfo; | |||
import jodd.util.StringPool; | |||
import me.chanjar.weixin.common.WxType; | |||
import me.chanjar.weixin.common.error.WxError; | |||
@@ -13,6 +12,7 @@ import me.chanjar.weixin.common.util.http.RequestHttp; | |||
import me.chanjar.weixin.mp.bean.material.WxMpMaterialVideoInfoResult; | |||
import java.io.IOException; | |||
import java.nio.charset.StandardCharsets; | |||
/** | |||
* Created by ecoolper on 2017/5/5. | |||
@@ -32,7 +32,7 @@ public class MaterialVideoInfoJoddHttpRequestExecutor extends MaterialVideoInfoR | |||
request.query("media_id", materialId); | |||
HttpResponse response = request.send(); | |||
response.charset(StringPool.UTF_8); | |||
response.charset(StandardCharsets.UTF_8.name()); | |||
String responseContent = response.bodyText(); | |||
WxError error = WxError.fromJson(responseContent, WxType.MP); | |||
if (error.getErrorCode() != 0) { | |||
@@ -37,7 +37,7 @@ public class MaterialVoiceAndImageDownloadJoddHttpRequestExecutor extends Materi | |||
request.query("media_id", materialId); | |||
HttpResponse response = request.send(); | |||
response.charset(StringPool.UTF_8); | |||
response.charset(StandardCharsets.UTF_8.name()); | |||
try (InputStream inputStream = new ByteArrayInputStream(response.bodyBytes())) { | |||
// 下载媒体文件出错 | |||
byte[] responseContent = IOUtils.toByteArray(inputStream); | |||
@@ -4,7 +4,6 @@ import jodd.http.HttpConnectionProvider; | |||
import jodd.http.HttpRequest; | |||
import jodd.http.HttpResponse; | |||
import jodd.http.ProxyInfo; | |||
import jodd.util.StringPool; | |||
import me.chanjar.weixin.common.WxType; | |||
import me.chanjar.weixin.common.error.WxError; | |||
@@ -14,6 +13,7 @@ import me.chanjar.weixin.mp.bean.material.WxMediaImgUploadResult; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.nio.charset.StandardCharsets; | |||
/** | |||
* Created by ecoolper on 2017/5/5. | |||
@@ -39,7 +39,7 @@ public class MediaImgUploadHttpRequestExecutor extends MediaImgUploadRequestExec | |||
request.form("media", data); | |||
HttpResponse response = request.send(); | |||
response.charset(StringPool.UTF_8); | |||
response.charset(StandardCharsets.UTF_8.name()); | |||
String responseContent = response.bodyText(); | |||
WxError error = WxError.fromJson(responseContent, WxType.MP); | |||
if (error.getErrorCode() != 0) { | |||
@@ -4,9 +4,8 @@ import jodd.http.HttpConnectionProvider; | |||
import jodd.http.HttpRequest; | |||
import jodd.http.HttpResponse; | |||
import jodd.http.ProxyInfo; | |||
import jodd.util.MimeTypes; | |||
import jodd.util.StringPool; | |||
import jodd.net.MimeTypes; | |||
import me.chanjar.weixin.common.WxType; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
@@ -19,6 +18,7 @@ import java.io.File; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.net.URLEncoder; | |||
import java.nio.charset.StandardCharsets; | |||
import java.util.UUID; | |||
/** | |||
@@ -47,7 +47,7 @@ public class QrCodeJoddHttpRequestExecutor extends QrCodeRequestExecutor<HttpCon | |||
request.withConnectionProvider(requestHttp.getRequestHttpClient()); | |||
HttpResponse response = request.send(); | |||
response.charset(StringPool.UTF_8); | |||
response.charset(StandardCharsets.UTF_8.name()); | |||
String contentTypeHeader = response.header("Content-Type"); | |||
if (MimeTypes.MIME_TEXT_PLAIN.equals(contentTypeHeader)) { | |||
String responseContent = response.bodyText(); | |||
@@ -7,7 +7,7 @@ | |||
<parent> | |||
<groupId>com.github.binarywang</groupId> | |||
<artifactId>wx-java</artifactId> | |||
<version>3.7.0</version> | |||
<version>3.7.0.B</version> | |||
</parent> | |||
<artifactId>weixin-java-open</artifactId> | |||
@@ -166,6 +166,7 @@ public class WxOpenComponentServiceImpl implements WxOpenComponentService { | |||
String componentAccessToken = getComponentAccessToken(false); | |||
String uriWithComponentAccessToken = uri + (uri.contains("?") ? "&" : "?") + accessTokenKey + "=" + componentAccessToken; | |||
try { | |||
this.log.info("wxopencomponent excute url:"+uriWithComponentAccessToken); | |||
return getWxOpenService().get(uriWithComponentAccessToken, null); | |||
} catch (WxErrorException e) { | |||
WxError error = e.getError(); | |||
@@ -246,6 +247,7 @@ public class WxOpenComponentServiceImpl implements WxOpenComponentService { | |||
@Override | |||
public String route(final WxOpenXmlMessage wxMessage) throws WxErrorException { | |||
log.info("wxopencomponent route :"+wxMessage); | |||
if (wxMessage == null) { | |||
throw new NullPointerException("message is empty"); | |||
} | |||
@@ -8,6 +8,7 @@ import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; | |||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage; | |||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; | |||
import me.chanjar.weixin.open.api.WxOpenConfigStorage; | |||
import me.chanjar.weixin.open.api.impl.WxOpenInMemoryConfigStorage; | |||
import me.chanjar.weixin.open.util.WxOpenCryptUtil; | |||
import me.chanjar.weixin.open.util.xml.XStreamTransformer; | |||
import org.apache.commons.io.IOUtils; | |||
@@ -140,6 +141,7 @@ public class WxOpenXmlMessage implements Serializable { | |||
String timestamp, String nonce, String msgSignature) { | |||
WxOpenCryptUtil cryptUtil = new WxOpenCryptUtil(wxOpenConfigStorage); | |||
String plainText = cryptUtil.decrypt(msgSignature, timestamp, nonce, encryptedXml); | |||
log.debug("解密后的原始xml消息内容:{}", plainText); | |||
return WxMpXmlMessage.fromXml(plainText); | |||
} | |||
@@ -152,4 +154,31 @@ public class WxOpenXmlMessage implements Serializable { | |||
throw new RuntimeException(e); | |||
} | |||
} | |||
public static void main(String[] args) { | |||
WxOpenInMemoryConfigStorage wxOpenConfigStorage = new WxOpenInMemoryConfigStorage(); | |||
wxOpenConfigStorage.setComponentAesKey(""); | |||
wxOpenConfigStorage.setComponentToken(""); | |||
wxOpenConfigStorage.setComponentAppId(""); | |||
WxOpenCryptUtil cryptUtil = new WxOpenCryptUtil(wxOpenConfigStorage); | |||
/** | |||
* 接收微信APP回调:[appId=[wx3cb90ab25f132468], openid=[ok9Xtt7rErEqlQKBjaluwroxsHaM], signature=[50e3ddd2d2817cbc309ed0a4b9b6eafe6e4c8648], encType=[aes], msgSignature=[00c9b32600e67276a56e2092fe3dfe1c486318f5], timestamp=[1653534263], nonce=[897774971], requestBody=[ | |||
* <xml> | |||
* <ToUserName><![CDATA[gh_ddfa54d85724]]></ToUserName> | |||
* <Encrypt><![CDATA[EUzw+5L2Vsqs6fxq4ZGw1S/Hu/4Gx04Z4v2ZqE45OM5OHvK/6z0K21D2wdVv20YmswbsxW7bThe2vvoMqf8dktp4MbOqLMACpYt9B1UeQBoG0tnwiQo1PggTLr3iomBVxRERVpLcyIRZHbyGW0sg3zKjecVGlvMgL4fQFCZmi5swzuR8zXsHQ9LlPiB0jSaF37cj0g7YMyYlzZ1GRyleGljLER3P+Plqa727bpJjGwRgSkBBco8vm4bEcOyTiO0Yy5gARMHC2bcQkhqgUgp6XRyz5YM9jW6DwXPhVCY+X/vvTL1gPm/UAZpwY+YUNh+1o+xm45MX+FjHXN/kbdeVV6NqO8VGF0sP0XYBlenBm4a3CmxU5AjNTauM1f6KSpoLV0R1c02l2hbvpwZ32CEgD5uriOh2NWOnWuLD58AScA8xyIUzdENUsYlq60H9tRd4KRbSydcwp2ALCcm0B1KS/GDT/587TntnL+Ai2VrUSnlZej/ByV8D4dvEuAU+5/ky]]></Encrypt> | |||
* </xml> | |||
* | |||
* ] | |||
*/ | |||
String msgSignature = "50e3ddd2d2817cbc309ed0a4b9b6eafe6e4c8648"; | |||
String timestamp = "1653534263"; | |||
String nonce = "897774971"; | |||
String encryptedXml = "<xml>\n" + | |||
" <ToUserName><![CDATA[gh_ddfa54d85724]]></ToUserName>\n" + | |||
" <Encrypt><![CDATA[EUzw+5L2Vsqs6fxq4ZGw1S/Hu/4Gx04Z4v2ZqE45OM5OHvK/6z0K21D2wdVv20YmswbsxW7bThe2vvoMqf8dktp4MbOqLMACpYt9B1UeQBoG0tnwiQo1PggTLr3iomBVxRERVpLcyIRZHbyGW0sg3zKjecVGlvMgL4fQFCZmi5swzuR8zXsHQ9LlPiB0jSaF37cj0g7YMyYlzZ1GRyleGljLER3P+Plqa727bpJjGwRgSkBBco8vm4bEcOyTiO0Yy5gARMHC2bcQkhqgUgp6XRyz5YM9jW6DwXPhVCY+X/vvTL1gPm/UAZpwY+YUNh+1o+xm45MX+FjHXN/kbdeVV6NqO8VGF0sP0XYBlenBm4a3CmxU5AjNTauM1f6KSpoLV0R1c02l2hbvpwZ32CEgD5uriOh2NWOnWuLD58AScA8xyIUzdENUsYlq60H9tRd4KRbSydcwp2ALCcm0B1KS/GDT/587TntnL+Ai2VrUSnlZej/ByV8D4dvEuAU+5/ky]]></Encrypt>\n" + | |||
"</xml>"; | |||
String plainText = cryptUtil.decrypt(msgSignature, timestamp, nonce, encryptedXml); | |||
System.out.println(plainText); | |||
} | |||
} |
@@ -4,8 +4,7 @@ import jodd.http.HttpConnectionProvider; | |||
import jodd.http.HttpRequest; | |||
import jodd.http.HttpResponse; | |||
import jodd.http.ProxyInfo; | |||
import jodd.util.MimeTypes; | |||
import jodd.util.StringPool; | |||
import jodd.net.MimeTypes; | |||
import me.chanjar.weixin.common.WxType; | |||
import me.chanjar.weixin.common.error.WxError; | |||
import me.chanjar.weixin.common.error.WxErrorException; | |||
@@ -19,6 +18,7 @@ import java.io.File; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.net.URLEncoder; | |||
import java.nio.charset.StandardCharsets; | |||
import java.util.UUID; | |||
/** | |||
@@ -49,7 +49,7 @@ public class MaQrCodeJoddHttpRequestExecutor extends MaQrCodeRequestExecutor<Htt | |||
request.withConnectionProvider(requestHttp.getRequestHttpClient()); | |||
HttpResponse response = request.send(); | |||
response.charset(StringPool.UTF_8); | |||
response.charset(StandardCharsets.UTF_8.name()); | |||
String contentTypeHeader = response.header("Content-Type"); | |||
if (MimeTypes.MIME_TEXT_PLAIN.equals(contentTypeHeader)) { | |||
String responseContent = response.bodyText(); | |||
@@ -5,13 +5,25 @@ | |||
<parent> | |||
<groupId>com.github.binarywang</groupId> | |||
<artifactId>wx-java</artifactId> | |||
<version>3.7.0</version> | |||
<version>3.7.0.B</version> | |||
</parent> | |||
<modelVersion>4.0.0</modelVersion> | |||
<artifactId>weixin-java-pay</artifactId> | |||
<name>WxJava - PAY Java SDK</name> | |||
<description>微信支付 Java SDK</description> | |||
<build> | |||
<plugins> | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-compiler-plugin</artifactId> | |||
<configuration> | |||
<source>8</source> | |||
<target>8</target> | |||
</configuration> | |||
</plugin> | |||
</plugins> | |||
</build> | |||
<dependencies> | |||
<dependency> | |||
@@ -0,0 +1,87 @@ | |||
package com.github.binarywang.wxpay.bean.applyment; | |||
import com.github.binarywang.wxpay.bean.applyment.enums.ApplymentStateEnum; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Builder; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import lombok.experimental.Accessors; | |||
import java.io.Serializable; | |||
import java.util.List; | |||
/** | |||
* 查询申请单状态返回对象信息 | |||
*/ | |||
@Data | |||
@Builder | |||
@NoArgsConstructor | |||
@AllArgsConstructor | |||
@Accessors(chain = true) | |||
public class ApplymentStateQueryResult implements Serializable { | |||
private static final long serialVersionUID = 6539090917423486409L; | |||
/** | |||
* 业务申请编号 | |||
*/ | |||
@SerializedName("business_code") | |||
private String businessCode; | |||
/** | |||
* 微信支付申请单号 | |||
*/ | |||
@SerializedName("applyment_id") | |||
private String applymentId; | |||
/** | |||
* 特约商户号 | |||
*/ | |||
@SerializedName("sub_mchid") | |||
private String subMchid; | |||
/** | |||
* 超级管理员签约链接 | |||
*/ | |||
@SerializedName("sign_url") | |||
private String signUrl; | |||
/** | |||
* 申请单状态 | |||
*/ | |||
@SerializedName("applyment_state") | |||
private ApplymentStateEnum applymentState; | |||
/** | |||
* 申请状态描述 | |||
*/ | |||
@SerializedName("applyment_state_msg") | |||
private String applymentStateMsg; | |||
/** | |||
* 驳回原因详情 | |||
*/ | |||
@SerializedName("audit_detail") | |||
private List<AuditDetail> auditDetail; | |||
/** | |||
* 驳回原因详情 | |||
*/ | |||
@Data | |||
@Builder | |||
@NoArgsConstructor | |||
@AllArgsConstructor | |||
@Accessors(chain = true) | |||
public static class AuditDetail { | |||
/** | |||
* 字段名 | |||
*/ | |||
@SerializedName("field") | |||
private String field; | |||
/** | |||
* 字段名称 | |||
*/ | |||
@SerializedName("field_name") | |||
private String fieldName; | |||
/** | |||
* 驳回原因 | |||
*/ | |||
@SerializedName("reject_reason") | |||
private String rejectReason; | |||
} | |||
} |
@@ -0,0 +1,62 @@ | |||
package com.github.binarywang.wxpay.bean.applyment; | |||
import com.github.binarywang.wxpay.bean.applyment.enums.AccountTypeEnum; | |||
import com.github.binarywang.wxpay.v3.SpecEncrypt; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Builder; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import lombok.experimental.Accessors; | |||
import java.io.Serializable; | |||
/** | |||
* 修改结算账户请求对象 | |||
*/ | |||
@Data | |||
@Builder | |||
@NoArgsConstructor | |||
@AllArgsConstructor | |||
@Accessors(chain = true) | |||
public class ModifySettlementRequest implements Serializable { | |||
private static final long serialVersionUID = 4568552340365230872L; | |||
/** | |||
* 账户类型 | |||
*/ | |||
@SerializedName("account_type") | |||
private AccountTypeEnum accountType; | |||
/** | |||
* 开户名称 | |||
*/ | |||
@SpecEncrypt | |||
@SerializedName("account_name") | |||
private String accountName; | |||
/** | |||
* 开户银行 | |||
*/ | |||
@SerializedName("account_bank") | |||
private String accountBank; | |||
/** | |||
* 开户银行省市编码 | |||
*/ | |||
@SerializedName("bank_address_code") | |||
private String bankAddressCode; | |||
/** | |||
* 开户银行全称(含支行) | |||
*/ | |||
@SerializedName("bank_name") | |||
private String bankName; | |||
/** | |||
* 开户银行联行号 | |||
*/ | |||
@SerializedName("bank_branch_id") | |||
private String bankBranchId; | |||
/** | |||
* 银行账号 | |||
*/ | |||
@SpecEncrypt | |||
@SerializedName("account_number") | |||
private String accountNumber; | |||
} |
@@ -0,0 +1,62 @@ | |||
package com.github.binarywang.wxpay.bean.applyment; | |||
import com.github.binarywang.wxpay.bean.applyment.enums.AccountTypeEnum; | |||
import com.github.binarywang.wxpay.bean.applyment.enums.SettlementVerifyResultEnum; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Builder; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import lombok.experimental.Accessors; | |||
import java.io.Serializable; | |||
/** | |||
* 查询结算账户返回对象信息 | |||
*/ | |||
@Data | |||
@Builder | |||
@NoArgsConstructor | |||
@AllArgsConstructor | |||
@Accessors(chain = true) | |||
public class SettlementInfoResult implements Serializable { | |||
private static final long serialVersionUID = 4568552340365230872L; | |||
/** | |||
* 账户类型 | |||
*/ | |||
@SerializedName("account_type") | |||
private AccountTypeEnum accountType; | |||
/** | |||
* 开户银行 | |||
*/ | |||
@SerializedName("account_bank") | |||
private String accountBank; | |||
/** | |||
* 开户银行全称(含支行] | |||
*/ | |||
@SerializedName("bank_name") | |||
private String bankName; | |||
/** | |||
* 开户银行联行号 | |||
*/ | |||
@SerializedName("bank_branch_id") | |||
private String bankBranchId; | |||
/** | |||
* 银行账号 | |||
*/ | |||
@SerializedName("account_number") | |||
private String accountNumber; | |||
/** | |||
* 汇款验证结果 | |||
* | |||
* @see com.github.binarywang.wxpay.bean.applyment.enums.SettlementVerifyResultEnum | |||
*/ | |||
@SerializedName("verify_result") | |||
private SettlementVerifyResultEnum verifyResult; | |||
/** | |||
* 汇款验证失败原因 | |||
*/ | |||
@SerializedName("verify_fail_reason") | |||
private String verifyFailReason; | |||
} |
@@ -0,0 +1,31 @@ | |||
package com.github.binarywang.wxpay.bean.applyment; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Builder; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import lombok.experimental.Accessors; | |||
import java.io.Serializable; | |||
/** | |||
* 特约商户进件 提交申请结果响应 | |||
* | |||
* @author zhouyongshen | |||
*/ | |||
@Data | |||
@Builder | |||
@NoArgsConstructor | |||
@AllArgsConstructor | |||
@Accessors(chain = true) | |||
public class WxPayApplymentCreateResult implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* 微信支付申请单号 | |||
*/ | |||
@SerializedName("applyment_id") | |||
private String applymentId; | |||
} |
@@ -0,0 +1,18 @@ | |||
package com.github.binarywang.wxpay.bean.applyment.enums; | |||
/** | |||
* 银行结算账户枚举类 | |||
*/ | |||
public enum AccountTypeEnum { | |||
/** | |||
* 对公银行账户 | |||
*/ | |||
ACCOUNT_TYPE_BUSINESS, | |||
/** | |||
* 经营者个人银行卡 | |||
*/ | |||
ACCOUNT_TYPE_PRIVATE, | |||
; | |||
} |
@@ -0,0 +1,42 @@ | |||
package com.github.binarywang.wxpay.bean.applyment.enums; | |||
/** | |||
* 申请单状态枚举类 | |||
* | |||
* @author zhouyongshen | |||
*/ | |||
public enum ApplymentStateEnum { | |||
/** | |||
* (编辑中):提交申请发生错误导致,请尝试重新提交。 | |||
*/ | |||
APPLYMENT_STATE_EDITTING, | |||
/** | |||
* (审核中):申请单正在审核中,超级管理员用微信打开“签约链接”,完成绑定微信号后,申请单进度将通过微信公众号通知超级管理员,引导完成后续步骤。 | |||
*/ | |||
APPLYMENT_STATE_AUDITING, | |||
/** | |||
* (已驳回):请按照驳回原因修改申请资料,超级管理员用微信打开“签约链接”,完成绑定微信号,后续申请单进度将通过微信公众号通知超级管理员。 | |||
*/ | |||
APPLYMENT_STATE_REJECTED, | |||
/** | |||
* (待账户验证):请超级管理员使用微信打开返回的“签约链接”,根据页面指引完成账户验证。 | |||
*/ | |||
APPLYMENT_STATE_TO_BE_CONFIRMED, | |||
/** | |||
* (待签约):请超级管理员使用微信打开返回的“签约链接”,根据页面指引完成签约。 | |||
*/ | |||
APPLYMENT_STATE_TO_BE_SIGNED, | |||
/** | |||
* (开通权限中):系统开通相关权限中,请耐心等待。 | |||
*/ | |||
APPLYMENT_STATE_SIGNING, | |||
/** | |||
* (已完成):商户入驻申请已完成。 | |||
*/ | |||
APPLYMENT_STATE_FINISHED, | |||
/** | |||
* (已作废):申请单已被撤销。 | |||
*/ | |||
APPLYMENT_STATE_CANCELED | |||
} |
@@ -0,0 +1,18 @@ | |||
package com.github.binarywang.wxpay.bean.applyment.enums; | |||
/** | |||
* 银行结算账户枚举类 | |||
*/ | |||
public enum BankAccountTypeEnum { | |||
/** | |||
* 对公银行账户 | |||
*/ | |||
BANK_ACCOUNT_TYPE_CORPORATE, | |||
/** | |||
* 经营者个人银行卡 | |||
*/ | |||
BANK_ACCOUNT_TYPE_PERSONAL, | |||
; | |||
} |
@@ -0,0 +1,64 @@ | |||
package com.github.binarywang.wxpay.bean.applyment.enums; | |||
/** | |||
* 登记证书的类型枚举 | |||
*/ | |||
public enum CertTypeEnum { | |||
/** | |||
* 事业单位法人证书 | |||
*/ | |||
CERTIFICATE_TYPE_2388, | |||
/** | |||
* 统一社会信用代码证书 | |||
*/ | |||
CERTIFICATE_TYPE_2389, | |||
/** | |||
* 有偿服务许可证(军队医院适用) | |||
*/ | |||
CERTIFICATE_TYPE_2390, | |||
/** | |||
* 医疗机构执业许可证(军队医院适用) | |||
*/ | |||
CERTIFICATE_TYPE_2391, | |||
/** | |||
* 企业营业执照(挂靠企业的党组织适用) | |||
*/ | |||
CERTIFICATE_TYPE_2392, | |||
/** | |||
* 组织机构代码证(政府机关适用) | |||
*/ | |||
CERTIFICATE_TYPE_2393, | |||
/** | |||
* 社会团体法人登记证书 | |||
*/ | |||
CERTIFICATE_TYPE_2394, | |||
/** | |||
* 民办非企业单位登记证书 | |||
*/ | |||
CERTIFICATE_TYPE_2395, | |||
/** | |||
* 基金会法人登记证书 | |||
*/ | |||
CERTIFICATE_TYPE_2396, | |||
/** | |||
* 宗教活动场所登记证 | |||
*/ | |||
CERTIFICATE_TYPE_2399, | |||
/** | |||
* 其他证书/批文/证明 | |||
*/ | |||
CERTIFICATE_TYPE_2400, | |||
/** | |||
* 执业许可证/执业证 | |||
*/ | |||
CERTIFICATE_TYPE_2520, | |||
/** | |||
* 基层群众性自治组织特别法人统一社会信用代码证 | |||
*/ | |||
CERTIFICATE_TYPE_2521, | |||
/** | |||
* 农村集体经济组织登记证 | |||
*/ | |||
CERTIFICATE_TYPE_2522, | |||
; | |||
} |
@@ -0,0 +1,17 @@ | |||
package com.github.binarywang.wxpay.bean.applyment.enums; | |||
/** | |||
* 1、主体为“个体工商户/企业/政府机关/事业单位/社会组织”,可选择:LEGAL:经营者/法人,SUPER:经办人 。(经办人:经商户授权办理微信支付业务的人员)。 | |||
* 枚举值 | |||
*/ | |||
public enum ContactTypeEnum { | |||
/** | |||
* 法人 | |||
*/ | |||
LEGAL, | |||
/** | |||
* 经办人 | |||
*/ | |||
SUPER, | |||
; | |||
} |
@@ -0,0 +1,20 @@ | |||
package com.github.binarywang.wxpay.bean.applyment.enums; | |||
/** | |||
* 1. 主体类型为政府机关、事业单位时选传: | |||
* (1)若上传的是法人证件,则不需要上传该字段 | |||
* (2)若因特殊情况,无法提供法人证件时,可上传经办人。 (经办人:经商户授权办理微信支付业务的人员,授权范围包括但不限于签约,入驻过程需完成账户验证)。 | |||
* 2. 主体类型为企业、个体户、社会组织时,默认为经营者/法人,不需要上传该字段。 | |||
* 枚举值 | |||
*/ | |||
public enum IdHolderEnum { | |||
/** | |||
* 法人 | |||
*/ | |||
LEGAL, | |||
/** | |||
* 经办人 | |||
*/ | |||
SUPER, | |||
; | |||
} |
@@ -0,0 +1,41 @@ | |||
package com.github.binarywang.wxpay.bean.applyment.enums; | |||
/** | |||
* 个体户/企业/党政、机关及事业单位/其他组织:可选择任一证件类型。 | |||
* 枚举值 | |||
*/ | |||
public enum IdTypeEnum { | |||
/** | |||
* 中国大陆居民-身份证 | |||
*/ | |||
IDENTIFICATION_TYPE_IDCARD, | |||
/** | |||
* 其他国家或地区居民-护照 | |||
*/ | |||
IDENTIFICATION_TYPE_OVERSEA_PASSPORT, | |||
/** | |||
* 中国香港居民-来往内地通行证 | |||
*/ | |||
IDENTIFICATION_TYPE_HONGKONG_PASSPORT, | |||
/** | |||
* 中国澳门居民-来往内地通行证 | |||
*/ | |||
IDENTIFICATION_TYPE_MACAO_PASSPORT, | |||
/** | |||
* 中国台湾居民-来往大陆通行证 | |||
*/ | |||
IDENTIFICATION_TYPE_TAIWAN_PASSPORT, | |||
/** | |||
* 外国人居留证 | |||
*/ | |||
IDENTIFICATION_TYPE_FOREIGN_RESIDENT, | |||
/** | |||
* 港澳居民证 | |||
*/ | |||
IDENTIFICATION_TYPE_HONGKONG_MACAO_RESIDENT, | |||
/** | |||
* 台湾居民证 | |||
*/ | |||
IDENTIFICATION_TYPE_TAIWAN_RESIDENT, | |||
; | |||
} |
@@ -0,0 +1,20 @@ | |||
package com.github.binarywang.wxpay.bean.applyment.enums; | |||
/** | |||
* 小微经营类型 | |||
*/ | |||
public enum MicroBizTypeEnum { | |||
/** | |||
* 门店场所 | |||
*/ | |||
MICRO_TYPE_STORE, | |||
/** | |||
* 流动经营/便民服务 | |||
*/ | |||
MICRO_TYPE_MOBILE, | |||
/** | |||
* 线上商品/服务交易 | |||
*/ | |||
MICRO_TYPE_ONLINE, | |||
; | |||
} |
@@ -0,0 +1,32 @@ | |||
package com.github.binarywang.wxpay.bean.applyment.enums; | |||
/** | |||
* 经营场景类型枚举值 | |||
*/ | |||
public enum SalesScenesTypeEnum { | |||
/** | |||
* 线下门店 | |||
*/ | |||
SALES_SCENES_STORE, | |||
/** | |||
* 公众号 | |||
*/ | |||
SALES_SCENES_MP, | |||
/** | |||
* 小程序 | |||
*/ | |||
SALES_SCENES_MINI_PROGRAM, | |||
/** | |||
* 互联网 | |||
*/ | |||
SALES_SCENES_WEB, | |||
/** | |||
* APP | |||
*/ | |||
SALES_SCENES_APP, | |||
/** | |||
* 企业微信 | |||
*/ | |||
SALES_SCENES_WEWORK, | |||
; | |||
} |
@@ -0,0 +1,23 @@ | |||
package com.github.binarywang.wxpay.bean.applyment.enums; | |||
/** | |||
* 返回特约商户的结算账户-汇款验证结果枚举类 | |||
* | |||
* @author zhouyognshen | |||
*/ | |||
public enum SettlementVerifyResultEnum { | |||
/** | |||
* 系统汇款验证中,商户可发起提现尝试。 | |||
*/ | |||
VERIFYING, | |||
/** | |||
* 系统成功汇款,该账户可正常发起提现。 | |||
*/ | |||
VERIFY_SUCCESS, | |||
/** | |||
* 系统汇款失败,该账户无法发起提现,请检查修改。 | |||
*/ | |||
VERIFY_FAIL, | |||
; | |||
} |
@@ -0,0 +1,34 @@ | |||
package com.github.binarywang.wxpay.bean.applyment.enums; | |||
/** | |||
* 主体类型枚举类 | |||
* <pre> | |||
* 商户申请接入时如何选择主体类型? https://kf.qq.com/faq/180910IBZVnQ180910naQ77b.html | |||
* </pre> | |||
* | |||
* @author zhouyongshen | |||
*/ | |||
public enum SubjectTypeEnum { | |||
/** | |||
* (个体户):营业执照上的主体类型一般为个体户、个体工商户、个体经营; | |||
*/ | |||
SUBJECT_TYPE_INDIVIDUAL, | |||
/** | |||
* (企业):营业执照上的主体类型一般为有限公司、有限责任公司; | |||
*/ | |||
SUBJECT_TYPE_ENTERPRISE, | |||
/** | |||
* (党政、机关及事业单位):包括国内各级、各类政府机构、事业单位等(如:公安、党团、司法、交通、旅游、工商税务、市政、医疗、教育、学校等机构); | |||
*/ | |||
SUBJECT_TYPE_INSTITUTIONS, | |||
/** | |||
* (其他组织):不属于企业、政府/事业单位的组织机构(如社会团体、民办非企业、基金会),要求机构已办理组织机构代码证。 | |||
*/ | |||
SUBJECT_TYPE_OTHERS, | |||
/** | |||
* (小微):无营业执照、免办理工商注册登记的实体商户 | |||
*/ | |||
SUBJECT_TYPE_MICRO, | |||
; | |||
} |
@@ -0,0 +1,28 @@ | |||
package com.github.binarywang.wxpay.bean.bank; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.Data; | |||
import java.io.Serializable; | |||
import java.util.List; | |||
/** | |||
* 对私银行卡号开户银行信息 | |||
* | |||
* @author zhongjun | |||
**/ | |||
@Data | |||
public class BankAccountResult implements Serializable { | |||
private static final long serialVersionUID = -8226859146533243501L; | |||
/** | |||
* 根据卡号查询到的银行列表数据的总条数,未查询到对应银行列表时默认返回0,最大不超过两百条。 | |||
*/ | |||
@SerializedName("total_count") | |||
private Integer totalCount; | |||
@SerializedName("data") | |||
private List<BankInfo> data; | |||
} |
@@ -0,0 +1,176 @@ | |||
package com.github.binarywang.wxpay.bean.bank; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.Data; | |||
import lombok.Getter; | |||
import lombok.Setter; | |||
import java.io.Serializable; | |||
import java.util.List; | |||
/** | |||
* 支行列表 | |||
* | |||
* @author hupeng | |||
**/ | |||
@Data | |||
public class BankBranchesResult implements Serializable { | |||
private static final long serialVersionUID = -3500020131951579476L; | |||
/** | |||
* <pre> | |||
* 字段名:查询数据总条数 | |||
* 变量名:total_count | |||
* 是否必填:是 | |||
* 类型:int | |||
* 描述: | |||
* 经过条件筛选,查询到的支行总数 | |||
* 示例值:10 | |||
* </pre> | |||
*/ | |||
@SerializedName("total_count") | |||
private Integer totalCount; | |||
/** | |||
* <pre> | |||
* 字段名:本次查询条数 | |||
* 变量名:count | |||
* 是否必填:是 | |||
* 类型:int | |||
* 描述: | |||
* 本次查询到的支行数据条数 | |||
* 示例值:10 | |||
* </pre> | |||
*/ | |||
@SerializedName("count") | |||
private Integer count; | |||
/** | |||
* <pre> | |||
* 字段名:支行列表 | |||
* 变量名:data | |||
* 是否必填:否 | |||
* 类型:array | |||
* 描述: | |||
* 单次查询返回的支行列表结果数组 | |||
* </pre> | |||
*/ | |||
@SerializedName("data") | |||
private List<BankBranch> data; | |||
/** | |||
* <pre> | |||
* 字段名:本次查询偏移量 | |||
* 变量名:offset | |||
* 是否必填:是 | |||
* 类型:int | |||
* 描述: | |||
* 该次请求资源的起始位置,请求中包含偏移量时应答消息返回相同偏移量,否则返回默认值0 | |||
* 示例值:0 | |||
* </pre> | |||
*/ | |||
@SerializedName("offset") | |||
private Integer offset; | |||
/** | |||
* <pre> | |||
* 字段名:分页链接 | |||
* 变量名:offset | |||
* 是否必填:是 | |||
* 类型:object | |||
* 描述: | |||
* 返回前后页和当前页面的访问链接 | |||
* </pre> | |||
*/ | |||
@SerializedName("links") | |||
private PageLink links; | |||
/** | |||
* <pre> | |||
* 字段名:开户银行 | |||
* 变量名:account_bank | |||
* 是否必填:是 | |||
* 类型:string[1, 128] | |||
* 描述: | |||
* 查询到的支行所属开户银行的名称,非直连银行统一为其他银行 | |||
* 示例值:招商银行其他银行 | |||
* </pre> | |||
*/ | |||
@SerializedName("account_bank") | |||
private String accountBank; | |||
/** | |||
* <pre> | |||
* 字段名:开户银行编码 | |||
* 变量名:account_bank_code | |||
* 是否必填:是 | |||
* 类型:int | |||
* 描述: | |||
* 查询到的支行所属开户银行的开户银行编码,可用于付款到银行卡等场景中指定银行卡的开户银行 | |||
* 示例值:1001 | |||
* </pre> | |||
*/ | |||
@SerializedName("account_bank_code") | |||
private Integer accountBankCode; | |||
/** | |||
* <pre> | |||
* 字段名:银行别名 | |||
* 变量名:bank_alias | |||
* 是否必填:是 | |||
* 类型:string[1, 128] | |||
* 描述: | |||
* 查询到的支行所属银行的银行别名 | |||
* 示例值:工商银行深圳前海微众银行 | |||
* </pre> | |||
*/ | |||
@SerializedName("bank_alias") | |||
private String bankAlias; | |||
/** | |||
* <pre> | |||
* 字段名:银行别名编码 | |||
* 变量名:bank_alias_code | |||
* 是否必填:是 | |||
* 类型:string[1, 32] | |||
* 描述: | |||
* 查询到的支行所属银行的银行别名编码,用于校验回包 | |||
* 示例值:1000006247 | |||
* </pre> | |||
*/ | |||
@SerializedName("bank_alias_code") | |||
private String bankAliasCode; | |||
@Getter | |||
@Setter | |||
public static class BankBranch { | |||
/** | |||
* <pre> | |||
* 字段名:开户银行支行名称 | |||
* 变量名:bank_branch_name | |||
* 是否必填:是 | |||
* 类型:string[1, 128] | |||
* 描述: | |||
* 开户银行支行名称,用于开户银行为其他银行的情况下,在入驻、修改结算银行卡、企业付款等场景下填写结算银行卡信息。 | |||
* 示例值:中国工商银行上海市周浦支行 | |||
* </pre> | |||
*/ | |||
@SerializedName("bank_branch_name") | |||
private String bankBranchName; | |||
/** | |||
* <pre> | |||
* 字段名:开户银行支行联行号 | |||
* 变量名:bank_branch_id | |||
* 是否必填:是 | |||
* 类型:string[1, 64] | |||
* 描述: | |||
* 开户银行支行的联行号,用于开户银行为其他银行的情况下,在入驻、修改结算银行卡、企业付款等场景下填写结算银行卡信息。 | |||
* 示例值:102290072311 | |||
* </pre> | |||
*/ | |||
@SerializedName("bank_branch_id") | |||
private String bankBranchId; | |||
} | |||
} |
@@ -0,0 +1,39 @@ | |||
package com.github.binarywang.wxpay.bean.bank; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.Data; | |||
/** | |||
* 银行信息 | |||
* | |||
* @author zhongjun | |||
* @date 2022/5/12 | |||
**/ | |||
@Data | |||
public class BankInfo { | |||
/** | |||
* 银行别名 | |||
*/ | |||
@SerializedName("bank_alias") | |||
private String bankAlias; | |||
/** | |||
* 银行别名编码 | |||
*/ | |||
@SerializedName("bank_alias_code") | |||
private String bankAliasCode; | |||
/** | |||
* 开户银行 | |||
*/ | |||
@SerializedName("account_bank") | |||
private String accountBank; | |||
/** | |||
* 开户银行编码 | |||
*/ | |||
@SerializedName("account_bank_code") | |||
private Integer accountBankCode; | |||
/** | |||
* 是否需要填写支行 | |||
*/ | |||
@SerializedName("need_bank_branch") | |||
private Boolean needBankBranch; | |||
} |
@@ -0,0 +1,64 @@ | |||
package com.github.binarywang.wxpay.bean.bank; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.Data; | |||
import lombok.Getter; | |||
import lombok.Setter; | |||
import java.io.Serializable; | |||
import java.util.List; | |||
/** | |||
* 个人业务的银行列表 | |||
* | |||
* @author zhongjun | |||
**/ | |||
@Data | |||
public class BankingResult implements Serializable { | |||
private static final long serialVersionUID = -8372812998971715894L; | |||
/** | |||
* 银行列表数据的总条数,调用方需要根据总条数分页查询 | |||
*/ | |||
@SerializedName("total_count") | |||
private Integer totalCount; | |||
/** | |||
* 本次查询银行列表返回的数据条数 | |||
*/ | |||
@SerializedName("count") | |||
private Integer count; | |||
/** | |||
* 该次请求资源的起始位置,请求中包含偏移量时应答消息返回相同偏移量,否则返回默认值0。 | |||
*/ | |||
@SerializedName("offset") | |||
private Integer offset; | |||
@SerializedName("data") | |||
private List<BankInfo> data; | |||
@SerializedName("links") | |||
private Link links; | |||
@Getter | |||
@Setter | |||
public static class Link { | |||
/** | |||
* 下一页链接 | |||
*/ | |||
@SerializedName("next") | |||
private String next; | |||
/** | |||
* 上一页链接 | |||
*/ | |||
@SerializedName("prev") | |||
private String prev; | |||
/** | |||
* 当前链接 | |||
*/ | |||
@SerializedName("self") | |||
private String self; | |||
} | |||
} |
@@ -0,0 +1,80 @@ | |||
package com.github.binarywang.wxpay.bean.bank; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.Data; | |||
import lombok.Getter; | |||
import lombok.Setter; | |||
import java.io.Serializable; | |||
import java.util.List; | |||
/** | |||
* 城市列表 | |||
* | |||
* @author hupeng | |||
**/ | |||
@Data | |||
public class CitiesResult implements Serializable { | |||
private static final long serialVersionUID = -6089905695087974693L; | |||
/** | |||
* <pre> | |||
* 字段名:查询数据总条数 | |||
* 变量名:total_count | |||
* 是否必填:是 | |||
* 类型:int | |||
* 描述: | |||
* 查询到的省份数据总条数 | |||
* 示例值:10 | |||
* </pre> | |||
*/ | |||
@SerializedName("total_count") | |||
private Integer totalCount; | |||
/** | |||
* <pre> | |||
* 字段名:城市列表 | |||
* 变量名:data | |||
* 是否必填:否 | |||
* 类型:array | |||
* 描述: | |||
* 查询返回的城市列表结果 | |||
* </pre> | |||
*/ | |||
@SerializedName("data") | |||
private List<CityInfo> data; | |||
@Getter | |||
@Setter | |||
public static class CityInfo { | |||
/** | |||
* <pre> | |||
* 字段名:城市名称 | |||
* 变量名:city_name | |||
* 是否必填:是 | |||
* 类型:string[1, 256] | |||
* 描述: | |||
* 城市名称 | |||
* 示例值:北京市 | |||
* </pre> | |||
*/ | |||
@SerializedName("city_name") | |||
private String cityName; | |||
/** | |||
* <pre> | |||
* 字段名:城市编码 | |||
* 变量名:city_code | |||
* 是否必填:是 | |||
* 类型:int | |||
* 描述: | |||
* 城市编码,唯一标识一座城市,用于结合银行别名编码查询支行列表 | |||
* 示例值:10 | |||
* </pre> | |||
*/ | |||
@SerializedName("city_code") | |||
private Integer cityCode; | |||
} | |||
} |
@@ -0,0 +1,59 @@ | |||
package com.github.binarywang.wxpay.bean.bank; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.Data; | |||
import java.io.Serializable; | |||
/** | |||
* 支行列表 | |||
* | |||
* @author hupeng | |||
**/ | |||
@Data | |||
public class PageLink implements Serializable { | |||
private static final long serialVersionUID = -2624233403271204837L; | |||
/** | |||
* <pre> | |||
* 字段名:下一页链接 | |||
* 变量名:next | |||
* 是否必填:否 | |||
* 类型:string[1, 2048] | |||
* 描述: | |||
* 使用同样的limit进行下一页查询时的相对请求链接,使用方需要自行根据当前域名进行拼接。如果已经到最后时,为空 | |||
* 示例值:/v3/capital/capitallhh/banks/1001/branches?offset=10&limit=5 | |||
* </pre> | |||
*/ | |||
@SerializedName("next") | |||
private String next; | |||
/** | |||
* <pre> | |||
* 字段名:上一页链接 | |||
* 变量名:prev | |||
* 是否必填:否 | |||
* 类型:string[1, 2048] | |||
* 描述: | |||
* 使用同样的limit进行上一页查询时的相对请求链接,使用方需要自行根据当前域名进行拼接。如果是第一页,为空 | |||
* 示例值:/v3/capital/capitallhh/banks/1001/branchesoffset=0&limit=5 | |||
* </pre> | |||
*/ | |||
@SerializedName("prev") | |||
private String prev; | |||
/** | |||
* <pre> | |||
* 字段名:当前链接 | |||
* 变量名:self | |||
* 是否必填:否 | |||
* 类型:string[1, 2048] | |||
* 描述: | |||
* 当前的相对请求链接,使用方需要自行根据当前域名进行拼接 | |||
* 示例值:/v3/capital/capitallhh/banks/1001/branches?offset=5&limit=5 | |||
* </pre> | |||
*/ | |||
@SerializedName("self") | |||
private String self; | |||
} |
@@ -0,0 +1,81 @@ | |||
package com.github.binarywang.wxpay.bean.bank; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.Data; | |||
import lombok.Getter; | |||
import lombok.Setter; | |||
import java.io.Serializable; | |||
import java.util.List; | |||
/** | |||
* 省份列表 | |||
* | |||
* @author hupeng | |||
**/ | |||
@Data | |||
public class ProvincesResult implements Serializable { | |||
private static final long serialVersionUID = -4118613374545722650L; | |||
/** | |||
* <pre> | |||
* 字段名:查询数据总条数 | |||
* 变量名:total_count | |||
* 是否必填:是 | |||
* 类型:int | |||
* 描述: | |||
* 查询到的省份数据总条数 | |||
* 示例值:10 | |||
* </pre> | |||
*/ | |||
@SerializedName("total_count") | |||
private Integer totalCount; | |||
/** | |||
* <pre> | |||
* 字段名:省份列表 | |||
* 变量名:data | |||
* 是否必填:否 | |||
* 类型:array | |||
* 描述: | |||
* 查询到的省份列表数组 | |||
* </pre> | |||
*/ | |||
@SerializedName("data") | |||
private List<ProvinceInfo> data; | |||
@Getter | |||
@Setter | |||
public static class ProvinceInfo { | |||
/** | |||
* <pre> | |||
* 字段名:省份名称 | |||
* 变量名:province_name | |||
* 是否必填:是 | |||
* 类型:string[1, 256] | |||
* 描述: | |||
* 省份名称 | |||
* 示例值:广东省 | |||
* </pre> | |||
*/ | |||
@SerializedName("province_name") | |||
private String provinceName; | |||
/** | |||
* <pre> | |||
* 字段名:省份编码 | |||
* 变量名:province_code | |||
* 是否必填:是 | |||
* 类型:int | |||
* 描述: | |||
* 省份编码,唯一标识一个省份,用于根据省份编码查询省份下的城市列表数据 | |||
* 示例值:22 | |||
* </pre> | |||
*/ | |||
@SerializedName("province_code") | |||
private Integer provinceCode; | |||
} | |||
} |
@@ -0,0 +1,93 @@ | |||
package com.github.binarywang.wxpay.bean.businesscircle; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import java.io.Serializable; | |||
/** | |||
* 智慧商圈回调通知对象 | |||
* <pre> | |||
* 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/businesscircle/chapter3_1.shtml | |||
* https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/businesscircle/chapter3_3.shtml | |||
* </pre> | |||
* | |||
* @author thinsstar | |||
*/ | |||
@NoArgsConstructor | |||
@Data | |||
public class BusinessCircleNotifyData implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* 通知ID | |||
*/ | |||
@SerializedName("id") | |||
private String id; | |||
/** | |||
* 通知创建时间 | |||
*/ | |||
@SerializedName("create_time") | |||
private String createTime; | |||
/** | |||
* 通知类型 | |||
*/ | |||
@SerializedName("event_type") | |||
private String eventType; | |||
/** | |||
* 通知数据类型 | |||
*/ | |||
@SerializedName("resource_type") | |||
private String resourceType; | |||
/** | |||
* 回调摘要 | |||
* summary | |||
*/ | |||
@SerializedName("summary") | |||
private String summary; | |||
/** | |||
* 通知数据 | |||
*/ | |||
@SerializedName("resource") | |||
private Resource resource; | |||
@Data | |||
public static class Resource implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* 加密算法类型 | |||
*/ | |||
@SerializedName("algorithm") | |||
private String algorithm; | |||
/** | |||
* 数据密文 | |||
*/ | |||
@SerializedName("ciphertext") | |||
private String cipherText; | |||
/** | |||
* 附加数据 | |||
*/ | |||
@SerializedName("associated_data") | |||
private String associatedData; | |||
/** | |||
* 随机串 | |||
*/ | |||
@SerializedName("nonce") | |||
private String nonce; | |||
/** | |||
* 原始回调类型 | |||
*/ | |||
@SerializedName("original_type") | |||
private String originalType; | |||
} | |||
} |
@@ -0,0 +1,52 @@ | |||
package com.github.binarywang.wxpay.bean.businesscircle; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import java.io.Serializable; | |||
/** | |||
* 商圈授权结果通知内容 | |||
* <pre> | |||
* 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter8_6_6.shtml | |||
* </pre> | |||
* | |||
* @author thinsstar | |||
*/ | |||
@NoArgsConstructor | |||
@Data | |||
public class MemberCardAuthorizeNotifyResult implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* 用户标识 | |||
* <p> | |||
* 顾客授权时使用的小程序上的openid | |||
* 示例值:oUpF8uMuAJ2pxb1Q9zNjWeS6o | |||
*/ | |||
@SerializedName("openid") | |||
private String openid; | |||
/** | |||
* 会员在card_id下的唯一标识, | |||
*/ | |||
@SerializedName("code") | |||
private String code; | |||
/** | |||
* 用户开会员卡时的商圈商户号 | |||
*/ | |||
@SerializedName("mchid") | |||
private String mchid; | |||
/** | |||
* 用户授权类型 | |||
* REGISTERED_MODE :会员开卡(进卡包) + 未授权会员积分服务 | |||
* REGISTERED_AND_AUTHORIZATION_MODE:会员开卡(进卡包)+授权会员积分服务 | |||
*/ | |||
@SerializedName("auth_type") | |||
private String authType; | |||
} |
@@ -0,0 +1,53 @@ | |||
package com.github.binarywang.wxpay.bean.businesscircle; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import java.io.Serializable; | |||
/** | |||
* 商圈授权结果查询内容 | |||
* <pre> | |||
* 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter8_6_4.shtml | |||
* </pre> | |||
* | |||
* @author thinsstar | |||
*/ | |||
@NoArgsConstructor | |||
@Data | |||
public class MemberCardAuthorizeResult implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* 用户标识 | |||
* <p> | |||
* 顾客授权时使用的小程序上的openid | |||
* 示例值:oUpF8uMuAJ2pxb1Q9zNjWeS6o | |||
*/ | |||
@SerializedName("openid") | |||
private String openid; | |||
/** | |||
* 顾客授权商圈积分结果 | |||
* UNAUTHORIZED:未授权 | |||
* AUTHORIZED:已授权 | |||
* DEAUTHORIZED:已取消授权 | |||
*/ | |||
@SerializedName("authorize_state") | |||
private String authorizeState; | |||
/** | |||
* 顾客成功授权商圈积分的时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss+TIMEZONE | |||
*/ | |||
@SerializedName("authorize_time") | |||
private String authorizeTime; | |||
/** | |||
* 顾客关闭授权商圈积分的时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss+TIMEZONE | |||
*/ | |||
@SerializedName("deauthorize_time") | |||
private String deauthorizeTime; | |||
} |
@@ -0,0 +1,112 @@ | |||
package com.github.binarywang.wxpay.bean.businesscircle; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import java.io.Serializable; | |||
/** | |||
* 商圈支付结果通知内容 | |||
* <pre> | |||
* 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/businesscircle/chapter3_1.shtml | |||
* </pre> | |||
* | |||
* @author thinsstar | |||
*/ | |||
@NoArgsConstructor | |||
@Data | |||
public class PaidResult implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* 商户号 | |||
* <p> | |||
* 微信支付分配的商户号 | |||
* 示例值:1230000109 | |||
*/ | |||
@SerializedName("mchid") | |||
private String mchid; | |||
/** | |||
* 商圈商户名称 | |||
* <p> | |||
* 商圈商户名称 | |||
* 示例值:微信支付 | |||
*/ | |||
@SerializedName("merchant_name") | |||
private String merchantName; | |||
/** | |||
* 门店名称 | |||
* <p> | |||
* 门店名称,商圈在商圈小程序上圈店时填写的门店名称 | |||
* 示例值:微信支付 | |||
*/ | |||
@SerializedName("shop_name") | |||
private String shopName; | |||
/** | |||
* 门店编号 | |||
* <p> | |||
* 门店编号,商圈在商圈小程序上圈店时填写的门店编号,用于跟商圈自身已有的商户识别码对齐 | |||
* 示例值:123456 | |||
*/ | |||
@SerializedName("shop_number") | |||
private String shopNumber; | |||
/** | |||
* 小程序APPID | |||
* <p> | |||
* 顾客授权积分时使用的小程序的appid | |||
* 示例值:wxd678efh567hg6787 | |||
*/ | |||
@SerializedName("appid") | |||
private String appid; | |||
/** | |||
* 用户标识 | |||
* <p> | |||
* 顾客授权时使用的小程序上的openid | |||
* 示例值:oUpF8uMuAJ2pxb1Q9zNjWeS6o | |||
*/ | |||
@SerializedName("openid") | |||
private String openid; | |||
/** | |||
* 交易完成时间 | |||
* <p> | |||
* 交易完成时间,遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示北京时间2015年05月20日13点29分35秒(需要增加所有跟时间有关的参数的描述) | |||
* 示例值:2015-05-20T13:29:35+08:00 | |||
*/ | |||
@SerializedName("time_end") | |||
private String timeEnd; | |||
/** | |||
* 金额 | |||
* <p> | |||
* 用户实际消费金额,单位(分) | |||
* 示例值:200 | |||
*/ | |||
@SerializedName("amount") | |||
private Integer amount; | |||
/** | |||
* 微信支付订单号 | |||
* <p> | |||
* 微信支付订单号 | |||
* 示例值:1234567890 | |||
*/ | |||
@SerializedName("transaction_id") | |||
private String transactionId; | |||
/** | |||
* 手动提交积分标记 | |||
* <p> | |||
* 手动提交积分标记,自动提交时无该字段,用于区分用户手动申请后推送的积分数据 | |||
* 示例值:oUpF8uMuAJ2pxb1Q9zNjWUHsd | |||
*/ | |||
@SerializedName("commit_tag") | |||
private String commitTag; | |||
} |
@@ -0,0 +1,103 @@ | |||
package com.github.binarywang.wxpay.bean.businesscircle; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Builder; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import java.io.Serializable; | |||
/** | |||
* 商圈停车同步 | |||
* <pre> | |||
* 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter8_6_5.shtml | |||
* </pre> | |||
* | |||
* @author thinsstar | |||
*/ | |||
@Data | |||
@Builder | |||
@NoArgsConstructor | |||
@AllArgsConstructor | |||
public class ParkingNotifyRequest implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* <pre> | |||
* 字段名:商圈商户ID | |||
* 变量名:sub_mchid | |||
* 是否必填:否 | |||
* 类型:string[1,64] | |||
* 描述: | |||
* 当以服务商模式管理商圈积分能力时,则要带上商圈商户ID,否则留空 | |||
* 示例值:1234567890 | |||
* </pre> | |||
*/ | |||
@SerializedName(value = "sub_mchid") | |||
private String subMchid; | |||
/** | |||
* <pre> | |||
* 调用方商户号对应的品牌brandid,调用方商户号需为此品牌brandid的品牌主商户号或品牌服务商商户号 | |||
* </pre> | |||
*/ | |||
@SerializedName(value = "brandid") | |||
private String brandid; | |||
/** | |||
* <pre> | |||
* 字段名:小程序appid | |||
* 变量名:appid | |||
* 是否必填:是 | |||
* 类型:string[1,128] | |||
* 描述: | |||
* 顾客授权积分时使用的小程序的appid | |||
* 示例值:wx1234567890abcdef | |||
* </pre> | |||
*/ | |||
@SerializedName(value = "appid") | |||
private String appid; | |||
/** | |||
* <pre> | |||
* 字段名:用户标识 | |||
* 变量名:openid | |||
* 是否必填:是 | |||
* 类型:string[1,64] | |||
* 描述: | |||
* 顾客授权时使用的小程序上的openid | |||
* 示例值:oWmnN4xxxxxxxxxxe92NHIGf1xd8 | |||
* </pre> | |||
*/ | |||
@SerializedName(value = "openid") | |||
private String openid; | |||
/** | |||
* <pre> | |||
* 首位需为省份的中文简称,第二位起支持大写字母、数字、中文 | |||
* </pre> | |||
*/ | |||
@SerializedName(value = "plate_number") | |||
private String plateNumber; | |||
/** | |||
* <pre> | |||
* 停车状态,服务商模式下必传 | |||
* IN:入场,用户开车进入商圈 | |||
* OUT:离场,用户开车离开商圈 | |||
* </pre> | |||
*/ | |||
@SerializedName(value = "state") | |||
private String state; | |||
/** | |||
* <pre> | |||
* 在场状态更新时间,按照使用rfc3339所定义的格式,格式为yyyy-MM-DDThh:mm:ss+TIMEZONE | |||
* </pre> | |||
*/ | |||
@SerializedName(value = "time") | |||
private String time; | |||
} |
@@ -0,0 +1,31 @@ | |||
package com.github.binarywang.wxpay.bean.businesscircle; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import java.io.Serializable; | |||
/** | |||
* 商圈积分状态查询 | |||
* <pre> | |||
* 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter8_6_7.shtml | |||
* </pre> | |||
* | |||
* @author thinsstar | |||
*/ | |||
@NoArgsConstructor | |||
@Data | |||
public class PointsCommitStatusResult implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* 商圈会员待积分状态 | |||
* PENDING:有积分待提交,商圈会员有待提交的积分记录,可引导会员跳转插件提交积分申请 | |||
* FINISHED:无积分可提交,商圈会员没有待提交的积分记录 | |||
*/ | |||
@SerializedName("points_commit_status") | |||
private String pointsCommitStatus; | |||
} |
@@ -0,0 +1,154 @@ | |||
package com.github.binarywang.wxpay.bean.businesscircle; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Builder; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import java.io.Serializable; | |||
/** | |||
* 商圈积分同步 | |||
* <pre> | |||
* 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/businesscircle/chapter3_2.shtml | |||
* </pre> | |||
* | |||
* @author thinsstar | |||
*/ | |||
@Data | |||
@Builder | |||
@NoArgsConstructor | |||
@AllArgsConstructor | |||
public class PointsNotifyRequest implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* <pre> | |||
* 字段名:商圈商户ID | |||
* 变量名:sub_mchid | |||
* 是否必填:否 | |||
* 类型:string[1,64] | |||
* 描述: | |||
* 当以服务商模式管理商圈积分能力时,则要带上商圈商户ID,否则留空 | |||
* 示例值:1234567890 | |||
* </pre> | |||
*/ | |||
@SerializedName(value = "sub_mchid") | |||
private String subMchid; | |||
/** | |||
* <pre> | |||
* 字段名:微信订单号 | |||
* 变量名:transaction_id | |||
* 是否必填:是 | |||
* 类型:string[1,64] | |||
* 描述: | |||
* 微信支付推送的商圈内交易通知里携带的微信订单号 | |||
* 示例值:1217752501201407033233368018 | |||
* </pre> | |||
*/ | |||
@SerializedName(value = "transaction_id") | |||
private String transactionId; | |||
/** | |||
* <pre> | |||
* 字段名:小程序appid | |||
* 变量名:appid | |||
* 是否必填:是 | |||
* 类型:string[1,128] | |||
* 描述: | |||
* 顾客授权积分时使用的小程序的appid | |||
* 示例值:wx1234567890abcdef | |||
* </pre> | |||
*/ | |||
@SerializedName(value = "appid") | |||
private String appid; | |||
/** | |||
* <pre> | |||
* 字段名:用户标识 | |||
* 变量名:openid | |||
* 是否必填:是 | |||
* 类型:string[1,64] | |||
* 描述: | |||
* 顾客授权时使用的小程序上的openid | |||
* 示例值:oWmnN4xxxxxxxxxxe92NHIGf1xd8 | |||
* </pre> | |||
*/ | |||
@SerializedName(value = "openid") | |||
private String openid; | |||
/** | |||
* <pre> | |||
* 字段名:是否获得积分 | |||
* 变量名:earn_points | |||
* 是否必填:是 | |||
* 类型:boolean | |||
* 描述: | |||
* 用于标明此单是否获得积分, | |||
* true为获得积分, | |||
* false为未获得 | |||
* 示例值:true | |||
* </pre> | |||
*/ | |||
@SerializedName(value = "earn_points") | |||
private Boolean earnPoints; | |||
/** | |||
* <pre> | |||
* 字段名:订单新增积分值 | |||
* 变量名:increased_points | |||
* 是否必填:是 | |||
* 类型:int | |||
* 描述: | |||
* 顾客此笔交易新增的积分值 | |||
* 示例值:100 | |||
* </pre> | |||
*/ | |||
@SerializedName(value = "increased_points") | |||
private Integer increasedPoints; | |||
/** | |||
* <pre> | |||
* 字段名:积分更新时间 | |||
* 变量名:points_update_time | |||
* 是否必填:是 | |||
* 类型:string[1,32] | |||
* 描述: | |||
* 为顾客此笔交易成功积分的时间 | |||
* 示例值:2020-05-20T13:29:35.120+08:00 | |||
* </pre> | |||
*/ | |||
@SerializedName(value = "points_update_time") | |||
private String pointsUpdateTime; | |||
/** | |||
* <pre> | |||
* 字段名:未获得积分的备注信息 | |||
* 变量名:no_points_remarks | |||
* 是否必填:否 | |||
* 类型:string[1,128] | |||
* 描述: | |||
* 当未获得积分时,提供未获得积分的原因等备注信息 | |||
* 示例值:商品不参与积分活动 | |||
* </pre> | |||
*/ | |||
@SerializedName(value = "no_points_remarks") | |||
private String noPointsRemarks; | |||
/** | |||
* <pre> | |||
* 字段名:顾客积分总额 | |||
* 变量名:total_points | |||
* 是否必填:否 | |||
* 类型:int | |||
* 描述: | |||
* 当前顾客积分总额 | |||
* 示例值:888888 | |||
* </pre> | |||
*/ | |||
@SerializedName(value = "total_points") | |||
private Integer totalPoints; | |||
} |
@@ -0,0 +1,121 @@ | |||
package com.github.binarywang.wxpay.bean.businesscircle; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import java.io.Serializable; | |||
/** | |||
* 商圈退款成功通知内容 | |||
* <pre> | |||
* 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/businesscircle/chapter3_3.shtml | |||
* </pre> | |||
* | |||
* @author thinsstar | |||
*/ | |||
@NoArgsConstructor | |||
@Data | |||
public class RefundResult implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* 商户号 | |||
* <p> | |||
* 微信支付分配的商户号 | |||
* 示例值:1230000109 | |||
*/ | |||
@SerializedName("mchid") | |||
private String mchid; | |||
/** | |||
* 商圈商户名称 | |||
* <p> | |||
* 商圈商户名称 | |||
* 示例值:微信支付 | |||
*/ | |||
@SerializedName("merchant_name") | |||
private String merchantName; | |||
/** | |||
* 门店名称 | |||
* <p> | |||
* 门店名称,商圈在商圈小程序上圈店时填写的门店名称 | |||
* 示例值:微信支付 | |||
*/ | |||
@SerializedName("shop_name") | |||
private String shopName; | |||
/** | |||
* 门店编号 | |||
* <p> | |||
* 门店编号,商圈在商圈小程序上圈店时填写的门店编号,用于跟商圈自身已有的商户识别码对齐 | |||
* 示例值:123456 | |||
*/ | |||
@SerializedName("shop_number") | |||
private String shopNumber; | |||
/** | |||
* 小程序APPID | |||
* <p> | |||
* 顾客授权积分时使用的小程序的appid | |||
* 示例值:wxd678efh567hg6787 | |||
*/ | |||
@SerializedName("appid") | |||
private String appid; | |||
/** | |||
* 用户标识 | |||
* <p> | |||
* 顾客授权时使用的小程序上的openid | |||
* 示例值:oUpF8uMuAJ2pxb1Q9zNjWeS6o | |||
*/ | |||
@SerializedName("openid") | |||
private String openid; | |||
/** | |||
* 退款完成时间 | |||
* <p> | |||
* 退款完成时间,遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示北京时间2015年05月20日13点29分35秒(需要增加所有跟时间有关的参数的描述) | |||
* 示例值:2015-05-20T13:29:35+08:00 | |||
*/ | |||
@SerializedName("refund_time") | |||
private String refundTime; | |||
/** | |||
* 消费金额 | |||
* <p> | |||
* 用户实际消费金额,单位(分) | |||
* 示例值:100 | |||
*/ | |||
@SerializedName("pay_amount") | |||
private Integer payAmount; | |||
/** | |||
* 退款金额 | |||
* <p> | |||
* 用户退款金额,单位(分) | |||
* 示例值:100 | |||
*/ | |||
@SerializedName("refund_amount") | |||
private Integer refundAmount; | |||
/** | |||
* 微信支付订单号 | |||
* <p> | |||
* 微信支付订单号 | |||
* 示例值:1234567890 | |||
*/ | |||
@SerializedName("transaction_id") | |||
private String transactionId; | |||
/** | |||
* 微信支付退款单号 | |||
* <p> | |||
* 微信支付退款单号 | |||
* 示例值:1217752501201407033233368999 | |||
*/ | |||
@SerializedName("refund_id") | |||
private String refundId; | |||
} |
@@ -0,0 +1,35 @@ | |||
package com.github.binarywang.wxpay.bean.ecommerce; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import java.io.Serializable; | |||
/** | |||
* 微信通知接口头部信息,需要做签名验证 | |||
* 文档地址: https://wechatpay-api.gitbook.io/wechatpay-api-v3/qian-ming-zhi-nan-1/qian-ming-yan-zheng | |||
*/ | |||
@Data | |||
@NoArgsConstructor | |||
public class SignatureHeader implements Serializable { | |||
private static final long serialVersionUID = -6958015499416059949L; | |||
/** | |||
* 时间戳 | |||
*/ | |||
private String timeStamp; | |||
/** | |||
* 随机串 | |||
*/ | |||
private String nonce; | |||
/** | |||
* 已签名字符串 | |||
*/ | |||
private String signed; | |||
/** | |||
* 证书序列号 | |||
*/ | |||
private String serialNo; | |||
} |
@@ -0,0 +1,28 @@ | |||
package com.github.binarywang.wxpay.bean.media; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import me.chanjar.weixin.common.util.json.WxGsonBuilder; | |||
/** | |||
* 媒体文件上传返回结果对象 | |||
* @author zhouyongshen | |||
*/ | |||
@NoArgsConstructor | |||
@Data | |||
public class ImageUploadResult { | |||
public static ImageUploadResult fromJson(String json) { | |||
return WxGsonBuilder.create().fromJson(json, ImageUploadResult.class); | |||
} | |||
/** | |||
* 媒体文件标识 Id | |||
* | |||
* 微信返回的媒体文件标识Id。 | |||
* 示例值:6uqyGjGrCf2GtyXP8bxrbuH9-aAoTjH-rKeSl3Lf4_So6kdkQu4w8BYVP3bzLtvR38lxt4PjtCDXsQpzqge_hQEovHzOhsLleGFQVRF-U_0 | |||
* | |||
*/ | |||
@SerializedName("media_id") | |||
private String mediaId; | |||
} |
@@ -0,0 +1,29 @@ | |||
package com.github.binarywang.wxpay.bean.media; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import me.chanjar.weixin.common.util.json.WxGsonBuilder; | |||
/** | |||
* 媒体文件上传返回结果对象 | |||
* | |||
* @author thinsstar | |||
*/ | |||
@NoArgsConstructor | |||
@Data | |||
public class MarketingImageUploadResult { | |||
public static MarketingImageUploadResult fromJson(String json) { | |||
return WxGsonBuilder.create().fromJson(json, MarketingImageUploadResult.class); | |||
} | |||
/** | |||
* 媒体文件URL地址 | |||
* <p> | |||
* 微信返回的媒体文件标识url。有效期为永久 | |||
* 示例值:https://qpic.cn/xxx | |||
*/ | |||
@SerializedName("media_url") | |||
private String mediaUrl; | |||
} |
@@ -0,0 +1,82 @@ | |||
package com.github.binarywang.wxpay.bean.membercard; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import java.io.Serializable; | |||
/** | |||
* 商圈支付结果通知内容 | |||
* <pre> | |||
* 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_9_32.shtml | |||
* </pre> | |||
* | |||
* @author thinsstar | |||
*/ | |||
@NoArgsConstructor | |||
@Data | |||
public class MemberCardActivateResult implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* 业务细分事件类型,枚举值: | |||
* MEMBER_CARD_ACTIVATE:激活会员卡 | |||
* | |||
* USER_VIEW_MEMBERCARD:用户查看会员卡详情 | |||
* USER_DELETE_MEMBERCARD:用户删除会员卡 | |||
* USER_MODIFY_INFORMATION:用户修改个人信息 | |||
*/ | |||
@SerializedName("event_type") | |||
private String eventType; | |||
/** | |||
* 商户创建微信会员卡模板成功后系统返回的会员卡模板id | |||
*/ | |||
@SerializedName("card_id") | |||
private String cardId; | |||
/** | |||
* 会员在card_id下的唯一标识, | |||
*/ | |||
@SerializedName("code") | |||
private String code; | |||
/** | |||
* 事件发生时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss.sss+TIMEZONE | |||
*/ | |||
@SerializedName("event_time") | |||
private String eventTime; | |||
/** | |||
* 激活场景,用于区分用户新开卡激活或删卡后重新领取激活。枚举值: | |||
* NEW_ACTIVATE 新开卡激活 | |||
* RECOVER 删卡后重新领取激活 | |||
*/ | |||
@SerializedName("activate_scene") | |||
private String activateScene; | |||
/** | |||
* 用户标识 | |||
* <p> | |||
* 顾客授权时使用的小程序上的openid | |||
* 示例值:oUpF8uMuAJ2pxb1Q9zNjWeS6o | |||
*/ | |||
@SerializedName("openid") | |||
private String openid; | |||
/** | |||
* 微信用户在同一个微信开放平台账号下的唯一用户标识,unionid获取方式请参见《UnionID机制说明》文档。 | |||
*/ | |||
@SerializedName("unionid") | |||
private String unionid; | |||
/** | |||
* 自定义场景值,商户可以用于标记投放场景,如门店/来源等。只能录入数字及中英文/半角标点 | |||
* 匹配正则表达式: ^[0-9a-zA-Z\u0000-\u00FF\u4e00-\u9fa5]+$ | |||
*/ | |||
@SerializedName("outer_str") | |||
private String outerStr; | |||
} |
@@ -0,0 +1,93 @@ | |||
package com.github.binarywang.wxpay.bean.membercard; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import java.io.Serializable; | |||
/** | |||
* 会员卡回调通知对象 | |||
* <pre> | |||
* 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_9_32.shtml | |||
* https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_9_33.shtml | |||
* </pre> | |||
* | |||
* @author thinsstar | |||
*/ | |||
@NoArgsConstructor | |||
@Data | |||
public class MemberCardNotifyData implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* 通知ID | |||
*/ | |||
@SerializedName("id") | |||
private String id; | |||
/** | |||
* 通知创建时间 | |||
*/ | |||
@SerializedName("create_time") | |||
private String createTime; | |||
/** | |||
* 通知类型 | |||
*/ | |||
@SerializedName("event_type") | |||
private String eventType; | |||
/** | |||
* 通知数据类型 | |||
*/ | |||
@SerializedName("resource_type") | |||
private String resourceType; | |||
/** | |||
* 回调摘要 | |||
* summary | |||
*/ | |||
@SerializedName("summary") | |||
private String summary; | |||
/** | |||
* 通知数据 | |||
*/ | |||
@SerializedName("resource") | |||
private Resource resource; | |||
@Data | |||
public static class Resource implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* 加密算法类型 | |||
*/ | |||
@SerializedName("algorithm") | |||
private String algorithm; | |||
/** | |||
* 数据密文 | |||
*/ | |||
@SerializedName("ciphertext") | |||
private String cipherText; | |||
/** | |||
* 附加数据 | |||
*/ | |||
@SerializedName("associated_data") | |||
private String associatedData; | |||
/** | |||
* 随机串 | |||
*/ | |||
@SerializedName("nonce") | |||
private String nonce; | |||
/** | |||
* 原始回调类型 | |||
*/ | |||
@SerializedName("original_type") | |||
private String originalType; | |||
} | |||
} |
@@ -0,0 +1,360 @@ | |||
package com.github.binarywang.wxpay.bean.membercard; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import java.io.Serializable; | |||
import java.util.List; | |||
/** | |||
* 查询用户会员卡信息API | |||
* <pre> | |||
* 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_9_6.shtml | |||
* </pre> | |||
* | |||
* @author thinsstar | |||
*/ | |||
@NoArgsConstructor | |||
@Data | |||
public class MemberCardResult implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* 商户创建微信会员卡模板成功后系统返回的会员卡模板id | |||
*/ | |||
@SerializedName("card_id") | |||
private String cardId; | |||
/** | |||
* 会员在card_id下的唯一标识,用户领取会员卡后获得的code | |||
*/ | |||
@SerializedName("code") | |||
private String code; | |||
/** | |||
* 用户在会员卡绑定品牌appid下的唯一标识,如通过手机号同步会员身份且用户未领取到卡包,无法查询该字段 | |||
*/ | |||
@SerializedName("openid") | |||
private String openid; | |||
/** | |||
* 在用户会员卡上展示的会员卡编号,默认使用会员卡code作为membership_number。只能录入数字/英文/半角标点。商家可通过修改用户单张会员卡信息更新 | |||
*/ | |||
@SerializedName("membership_number") | |||
private String membershipNumber; | |||
/** | |||
* 用户会员等级 | |||
*/ | |||
@SerializedName("level") | |||
private String level; | |||
/** | |||
* 用户的微信昵称,如通过手机号同步会员身份且用户未领取到卡包,无法查询该字段 | |||
*/ | |||
@SerializedName("nickname") | |||
private String nickname; | |||
/** | |||
* 用户的微信头像url,如通过手机号同步会员身份且用户未领取到卡包,无法查询该字段 | |||
*/ | |||
@SerializedName("head_image_url") | |||
private String headImageUrl; | |||
/** | |||
* 商家给当前用户设置的会员卡背景图。仅支持通过《图片上传API》接口获取的图片URL地址。支持JPG/JPEG/PNG格式,且图片小于1M。 | |||
*/ | |||
@SerializedName("background_picture_url") | |||
private String backgroundPictureUrl; | |||
/** | |||
* 用户储值的最新余额,单位分 | |||
*/ | |||
@SerializedName("balance") | |||
private Integer balance; | |||
/** | |||
* 用户当前的卡状态: | |||
* NOT_ACTIVATE:未激活 | |||
* EFFECTIVE:生效中 | |||
* EXPIRE:已过期 | |||
* UNAVAILABLE:已失效 | |||
* DELETE:已删除 | |||
* IMPORTED:已导入 | |||
*/ | |||
@SerializedName("user_card_status") | |||
private String userCardStatus; | |||
/** | |||
* 用户开卡时填写的个人信息 | |||
*/ | |||
@SerializedName("user_information") | |||
private UserInformation userInformation; | |||
/** | |||
* 用户当前的积分值 | |||
*/ | |||
@SerializedName("bonus_value") | |||
private Integer bonusValue; | |||
/** | |||
* 用户当前的积分值 | |||
*/ | |||
@SerializedName("service_modules") | |||
private List<ServiceModule> serviceModules; | |||
/** | |||
* 用户会员卡详情页会员优惠栏目中的会员专享价文案 | |||
*/ | |||
@SerializedName("member_price_word") | |||
private String memberPriceWord; | |||
/** | |||
*发票栏跳转小程序的引导文案 | |||
*/ | |||
@SerializedName("fapiao_jump_word") | |||
private String fapiaoJumpWord; | |||
/** | |||
*设置商家联系人员的名字、头像和联系方式 | |||
*/ | |||
@SerializedName("guide") | |||
private List<Guide> guide; | |||
@Data | |||
public static class UserInformation implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* 平台提供的通用开卡信息字段 | |||
* 包含性别、手机、头像、昵称、姓名等基本信息字段 | |||
*/ | |||
@SerializedName("common_field_list") | |||
private List<CommonField> commonFieldList; | |||
/** | |||
* 商户自定义的开卡信息字段 | |||
*/ | |||
@SerializedName("custom_field_list") | |||
private List<CustomField> customFieldList; | |||
} | |||
@Data | |||
public static class CommonField implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* 平台提供了一些通用的开卡字段供开发者选用 | |||
* USER_FORM_FLAG_MOBILE:手机号 | |||
* USER_FORM_FLAG_SEX:性别 | |||
* USER_FORM_FLAG_NAME:姓名 | |||
* USER_FORM_FLAG_BIRTHDAY:生日 | |||
* USER_FORM_FLAG_ADDRESS:地址 | |||
* USER_FORM_FLAG_EMAIL:邮箱 | |||
* USER_FORM_FLAG_CITY:城市 | |||
*/ | |||
@SerializedName("name") | |||
private String name; | |||
/** | |||
* 平台提供的通用开卡信息字段,用户在开卡时填写的信息 | |||
*/ | |||
@SerializedName("value") | |||
private String value; | |||
} | |||
@Data | |||
public static class CustomField implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* 商户自定义的开卡信息字段名称 | |||
*/ | |||
@SerializedName("name") | |||
private String name; | |||
/** | |||
* 商户自定义的开卡信息字段值,用户在开卡时需填写。填写项目为单选时的返回 | |||
*/ | |||
@SerializedName("value") | |||
private String value; | |||
/** | |||
* 商户自定义的开卡信息字段值,用户在开卡时需填写。填写项目为多选时的返回 | |||
* 特殊规则:列表最多支持10个,单个列表限制8个字符 | |||
*/ | |||
@SerializedName("value_list") | |||
private List<String> valueList; | |||
} | |||
@Data | |||
public static class ServiceModule implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* 会员服务项的唯一识别ID,创建服务项后由微信支付生成的服务项ID。商户可通过服务项id查询服务项的配置信息及用途。 | |||
*/ | |||
@SerializedName("service_module_id") | |||
private String serviceModuleId; | |||
/** | |||
* 用户的服务状态设置,这些设置会展示在用户的会员卡详情页。可设置状态的内容字段、按钮、消息内容等 | |||
*/ | |||
@SerializedName("state_setting") | |||
private StateSetting stateSetting; | |||
} | |||
@Data | |||
public static class StateSetting implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* 状态的id。一个服务项通常包含多个状态,商户可根据服务流程选择其中的状态进行设置,模板内容展示在用户的会员卡详情页,并支持通过公众号给用户发送触达消息 | |||
*/ | |||
@SerializedName("state_id") | |||
private String stateId; | |||
/** | |||
* 用户的服务内容模板设置,这些设置会展示在用户的会员卡详情页。可设置状态的内容字段、按钮等 | |||
*/ | |||
@SerializedName("content_template_data") | |||
private ContentTemplateData contentTemplateData; | |||
/** | |||
* 公众号模板消息设置。部分服务项支持给用户发送触达消息,商户可通过模板id选择模板消息样式,并设置字段值。API调用成功后会通过微信公众号自动给用户发送此模板消息。不填则默认不发消息 | |||
*/ | |||
@SerializedName("message_template_setting") | |||
private MessageTemplateSetting messageTemplateSetting; | |||
} | |||
@Data | |||
public static class ContentTemplateData implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* 当前服务状态下,可以设置的内容字段列表 | |||
*/ | |||
@SerializedName("field_list") | |||
private List<Field> fieldList; | |||
/** | |||
* 服务状态对应的操作设置,可配置跳转文案和跳转小程序路径 | |||
* 需配置跳转文案及跳转小程序路径时必填 | |||
*/ | |||
@SerializedName("action_setting") | |||
private ActionSetting actionSetting; | |||
} | |||
@Data | |||
public static class Field implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* 服务内容列表,最多包含5条内容 | |||
*/ | |||
@SerializedName("field_id") | |||
private String fieldId; | |||
/** | |||
* 服务状态字段的值 | |||
*/ | |||
@SerializedName("field_value") | |||
private String fieldValue; | |||
} | |||
@Data | |||
public static class ActionSetting implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* 操作名称 | |||
*/ | |||
@SerializedName("action_name") | |||
private String actionName; | |||
/** | |||
* 服务状态指定跳转小程序 | |||
*/ | |||
@SerializedName("jump_miniprogram") | |||
private JumpMiniprogram jumpMiniprogram; | |||
} | |||
@Data | |||
public static class JumpMiniprogram implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* 小程序的appid | |||
*/ | |||
@SerializedName("appid") | |||
private String appid; | |||
/** | |||
* 小程序的页面path | |||
* 示例值:pages/index/index | |||
*/ | |||
@SerializedName("path") | |||
private String path; | |||
} | |||
@Data | |||
public static class MessageTemplateSetting implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* 公众号模板消息的id | |||
*/ | |||
@SerializedName("message_template_id") | |||
private String messageTemplateId; | |||
/** | |||
* 模板消息字段列表。商户在此设置模板消息每个字段需展示的内容 | |||
* 特殊规则:限制最多可提交9条 | |||
*/ | |||
@SerializedName("field_list") | |||
private List<Field> fieldList; | |||
} | |||
@Data | |||
public static class Guide implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* 设置商家咨询联系人的名称 | |||
*/ | |||
@SerializedName("staff_name") | |||
private String staffName; | |||
/** | |||
* 设置商家咨询联系人的头像。仅支持通过《图片上传API》接口获取的图片URL地址。 | |||
*/ | |||
@SerializedName("head_image_url") | |||
private String headImageUrl; | |||
/** | |||
* 展示说明商家咨询联系人的联系方式,例如“微信号”“企业微信号” | |||
*/ | |||
@SerializedName("contact_information_name") | |||
private String contactInformationName; | |||
/** | |||
* 展示说明商家咨询联系人的联系方式信息,例如“weixin123”“135266664” | |||
*/ | |||
@SerializedName("contact_information_value") | |||
private String contactInformationValue; | |||
/** | |||
* 商家咨询联系人的联系电话 | |||
*/ | |||
@SerializedName("phone_number") | |||
private String phoneNumber; | |||
} | |||
} |
@@ -0,0 +1,104 @@ | |||
package com.github.binarywang.wxpay.bean.membercard; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import java.io.Serializable; | |||
/** | |||
* 设置用户会员权益信息api | |||
* <pre> | |||
* 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_9_23.shtml | |||
* </pre> | |||
* | |||
* @author thinsstar | |||
*/ | |||
@NoArgsConstructor | |||
@Data | |||
public class MemberCardRightsRequest implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* 变更前的用户的积分值 | |||
*/ | |||
@SerializedName("before_bonus_value") | |||
private Integer beforeBonusValue; | |||
/** | |||
* 变更后的用户最新积分值,该值会展示在会员卡详页上 | |||
*/ | |||
@SerializedName("bonus_value") | |||
private Integer bonusValue; | |||
/** | |||
* 本次变更的积分值 | |||
*/ | |||
@SerializedName("add_bonus_value") | |||
private Integer addBonusValue; | |||
/** | |||
* 商户凭据号。商户自定义,注意保持唯一性,仅供参考的格式:商户id+日期+流水号。可包含英文字母,数字,|,_,*,-等内容,不允许出现其他不合法符号。 | |||
*/ | |||
@SerializedName("out_request_no") | |||
private String outRequestNo; | |||
/** | |||
* 积分变更时是否触发系统模板消息,默认为true | |||
*/ | |||
@SerializedName("need_inform_bonus") | |||
private Boolean needInformBonus; | |||
/** | |||
* 用户会员卡详情页会员优惠栏目中的会员专享价文案 | |||
*/ | |||
@SerializedName("member_price_word") | |||
private String memberPriceWord; | |||
/** | |||
*发票栏跳转小程序的引导文案 | |||
*/ | |||
@SerializedName("fapiao_jump_word") | |||
private String fapiaoJumpWord; | |||
/** | |||
*设置商家联系人员的名字、头像和联系方式 | |||
*/ | |||
@SerializedName("guide") | |||
private Guide guide; | |||
@Data | |||
public static class Guide implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* 设置商家咨询联系人的名称 | |||
*/ | |||
@SerializedName("staff_name") | |||
private String staffName; | |||
/** | |||
* 设置商家咨询联系人的头像。仅支持通过《图片上传API》接口获取的图片URL地址。 | |||
*/ | |||
@SerializedName("head_image_url") | |||
private String headImageUrl; | |||
/** | |||
* 展示说明商家咨询联系人的联系方式,例如“微信号”“企业微信号” | |||
*/ | |||
@SerializedName("contact_information_name") | |||
private String contactInformationName; | |||
/** | |||
* 展示说明商家咨询联系人的联系方式信息,例如“weixin123”“135266664” | |||
*/ | |||
@SerializedName("contact_information_value") | |||
private String contactInformationValue; | |||
/** | |||
* 商家咨询联系人的联系电话 | |||
*/ | |||
@SerializedName("phone_number") | |||
private String phoneNumber; | |||
} | |||
} |
@@ -0,0 +1,95 @@ | |||
package com.github.binarywang.wxpay.bean.membercard; | |||
import com.google.gson.annotations.SerializedName; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import java.io.Serializable; | |||
import java.util.List; | |||
/** | |||
* 修改用户会员卡信息API | |||
* <pre> | |||
* 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_9_8.shtml | |||
* </pre> | |||
* | |||
* @author thinsstar | |||
*/ | |||
@NoArgsConstructor | |||
@Data | |||
public class MemberCardUpdRequest implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* 在用户会员卡上展示的会员卡编号,默认使用会员卡code作为membership_number。只能录入数字/英文/半角标点。商家可通过修改用户单张会员卡信息更新 | |||
*/ | |||
@SerializedName("membership_number") | |||
private String membershipNumber; | |||
/** | |||
* 商家给当前用户设置的会员卡背景图。仅支持通过《图片上传API》接口获取的图片URL地址。支持JPG/JPEG/PNG格式,且图片小于1M。 | |||
*/ | |||
@SerializedName("background_picture_url") | |||
private String backgroundPictureUrl; | |||
/** | |||
* 用户会员等级 | |||
*/ | |||
@SerializedName("level") | |||
private String level; | |||
/** | |||
* 商户据号。商户自定义,注意保持唯一性,仅供参考的格式:商户id+日期+流水号。可包含英文字母,数字,|,_,*,-等内容,不允许出现其他不合法符号。 | |||
*/ | |||
@SerializedName("out_request_no") | |||
private String outRequestNo; | |||
/** | |||
* 用户储值变更信息 | |||
*/ | |||
@SerializedName("balance_information") | |||
private BalanceInformation balanceInformation; | |||
/** | |||
* 用户储值变更信息 | |||
*/ | |||
@SerializedName("need_inform_balance") | |||
private Boolean needInformBalance; | |||
/** | |||
* 用户储值变更信息 | |||
*/ | |||
@SerializedName("need_inform_level") | |||
private Boolean needInformLevel; | |||
@Data | |||
public static class BalanceInformation implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* 用户储值的更新前余额,单位分 | |||
*/ | |||
@SerializedName("before_balance") | |||
private Integer beforeBalance; | |||
/** | |||
* 用户储值的更新后余额,单位分 | |||
*/ | |||
@SerializedName("balance") | |||
private Integer balance; | |||
/** | |||
* 用户储值余额本次的变动值,单位分,等于balance减去before_balance,传入正数表示余额增加,传入负数表示余额减少 | |||
*/ | |||
@SerializedName("add_balance") | |||
private Integer addBalance; | |||
/** | |||
* 商家自定义储值金额消耗记录,不超过30个字 | |||
*/ | |||
@SerializedName("balance_remark") | |||
private String balanceRemark; | |||
} | |||
} |
@@ -1,15 +1,27 @@ | |||
package com.github.binarywang.wxpay.config; | |||
import com.github.binarywang.wxpay.exception.WxPayException; | |||
import com.github.binarywang.wxpay.v3.WxPayV3HttpClientBuilder; | |||
import com.github.binarywang.wxpay.v3.auth.*; | |||
import com.github.binarywang.wxpay.v3.util.PemUtils; | |||
import jodd.util.ResourcesUtil; | |||
import lombok.Data; | |||
import lombok.EqualsAndHashCode; | |||
import lombok.SneakyThrows; | |||
import org.apache.commons.io.IOUtils; | |||
import org.apache.commons.lang3.RegExUtils; | |||
import org.apache.commons.lang3.StringUtils; | |||
import org.apache.http.impl.client.CloseableHttpClient; | |||
import org.apache.http.ssl.SSLContexts; | |||
import javax.net.ssl.SSLContext; | |||
import java.io.*; | |||
import java.net.URL; | |||
import java.nio.charset.StandardCharsets; | |||
import java.security.KeyStore; | |||
import java.security.PrivateKey; | |||
import java.security.cert.X509Certificate; | |||
import java.util.Collections; | |||
/** | |||
* 微信支付配置 | |||
@@ -17,8 +29,11 @@ import java.security.KeyStore; | |||
* @author Binary Wang (https://github.com/binarywang) | |||
*/ | |||
@Data | |||
@EqualsAndHashCode(exclude = "verifier") | |||
public class WxPayConfig { | |||
private static final String DEFAULT_PAY_BASE_URL = "https://api.mch.weixin.qq.com"; | |||
private static final String PROBLEM_MSG = "证书文件【%s】有问题,请核实!"; | |||
private static final String NOT_FOUND_MSG = "证书文件【%s】不存在,请核实!"; | |||
/** | |||
* 微信支付接口请求地址域名部分. | |||
@@ -85,6 +100,52 @@ public class WxPayConfig { | |||
*/ | |||
private String keyPath; | |||
/** | |||
* apiclient_key.pem证书文件的绝对路径或者以classpath:开头的类路径. | |||
*/ | |||
private String privateKeyPath; | |||
/** | |||
* apiclient_cert.pem证书文件的绝对路径或者以classpath:开头的类路径. | |||
*/ | |||
private String privateCertPath; | |||
/** | |||
* apiV3 秘钥值. | |||
*/ | |||
private String apiV3Key; | |||
/** | |||
* apiV3 证书序列号值 | |||
*/ | |||
private String certSerialNo; | |||
/** | |||
* 微信支付分serviceId | |||
*/ | |||
private String serviceId; | |||
/** | |||
* 微信支付分回调地址 | |||
*/ | |||
private String payScoreNotifyUrl; | |||
/** | |||
* 微信支付分授权回调地址 | |||
*/ | |||
private String payScorePermissionNotifyUrl; | |||
private CloseableHttpClient apiV3HttpClient; | |||
/** | |||
* 私钥信息 | |||
*/ | |||
private PrivateKey privateKey; | |||
/** | |||
* 证书自动更新时间差(分钟),默认一分钟 | |||
*/ | |||
private int certAutoUpdateTime = 60; | |||
/** | |||
* p12证书文件内容的字节数组. | |||
*/ | |||
@@ -106,8 +167,15 @@ public class WxPayConfig { | |||
private String httpProxyUsername; | |||
private String httpProxyPassword; | |||
/** | |||
* v3接口下证书检验对象,通过改对象可以获取到X509Certificate,进一步对敏感信息加密 | |||
* 文档见 https://wechatpay-api.gitbook.io/wechatpay-api-v3/qian-ming-zhi-nan-1/min-gan-xin-xi-jia-mi | |||
*/ | |||
private Verifier verifier; | |||
/** | |||
* 返回所设置的微信支付接口请求地址域名. | |||
* | |||
* @return 微信支付接口请求地址域名 | |||
*/ | |||
public String getPayBaseUrl() { | |||
@@ -118,6 +186,15 @@ public class WxPayConfig { | |||
return this.payBaseUrl; | |||
} | |||
@SneakyThrows | |||
public Verifier getVerifier() { | |||
if (verifier == null) { | |||
//当改对象为null时,初始化api v3的请求头 | |||
initApiV3HttpClient(); | |||
} | |||
return verifier; | |||
} | |||
/** | |||
* 初始化ssl. | |||
* | |||
@@ -136,40 +213,7 @@ public class WxPayConfig { | |||
if (StringUtils.isBlank(this.getKeyPath())) { | |||
throw new WxPayException("请确保证书文件地址keyPath已配置"); | |||
} | |||
final String prefix = "classpath:"; | |||
String fileHasProblemMsg = "证书文件【" + this.getKeyPath() + "】有问题,请核实!"; | |||
String fileNotFoundMsg = "证书文件【" + this.getKeyPath() + "】不存在,请核实!"; | |||
if (this.getKeyPath().startsWith(prefix)) { | |||
String path = StringUtils.removeFirst(this.getKeyPath(), prefix); | |||
if (!path.startsWith("/")) { | |||
path = "/" + path; | |||
} | |||
inputStream = WxPayConfig.class.getResourceAsStream(path); | |||
if (inputStream == null) { | |||
throw new WxPayException(fileNotFoundMsg); | |||
} | |||
} else if (this.getKeyPath().startsWith("http://") || this.getKeyPath().startsWith("https://")) { | |||
try { | |||
inputStream = new URL(this.keyPath).openStream(); | |||
if (inputStream == null) { | |||
throw new WxPayException(fileNotFoundMsg); | |||
} | |||
} catch (IOException e) { | |||
throw new WxPayException(fileNotFoundMsg, e); | |||
} | |||
} else { | |||
try { | |||
File file = new File(this.getKeyPath()); | |||
if (!file.exists()) { | |||
throw new WxPayException(fileNotFoundMsg); | |||
} | |||
inputStream = new FileInputStream(file); | |||
} catch (IOException e) { | |||
throw new WxPayException(fileHasProblemMsg, e); | |||
} | |||
} | |||
inputStream = this.loadConfigInputStream(this.getKeyPath()); | |||
} | |||
try { | |||
@@ -185,4 +229,104 @@ public class WxPayConfig { | |||
} | |||
} | |||
/** | |||
* 初始化api v3请求头 自动签名验签 | |||
* 方法参照微信官方https://github.com/wechatpay-apiv3/wechatpay-apache-httpclient | |||
* | |||
* @return org.apache.http.impl.client.CloseableHttpClient | |||
* @author doger.wang | |||
**/ | |||
public CloseableHttpClient initApiV3HttpClient() throws WxPayException { | |||
String privateKeyPath = this.getPrivateKeyPath(); | |||
String privateCertPath = this.getPrivateCertPath(); | |||
String serialNo = this.getCertSerialNo(); | |||
String apiV3Key = this.getApiV3Key(); | |||
if (StringUtils.isBlank(privateKeyPath)) { | |||
throw new WxPayException("请确保privateKeyPath已设置"); | |||
} | |||
if (StringUtils.isBlank(privateCertPath)) { | |||
throw new WxPayException("请确保privateCertPath已设置"); | |||
} | |||
// if (StringUtils.isBlank(certSerialNo)) { | |||
// throw new WxPayException("请确保certSerialNo证书序列号已设置"); | |||
// } | |||
if (StringUtils.isBlank(apiV3Key)) { | |||
throw new WxPayException("请确保apiV3Key值已设置"); | |||
} | |||
InputStream keyInputStream = this.loadConfigInputStream(privateKeyPath); | |||
InputStream certInputStream = this.loadConfigInputStream(privateCertPath); | |||
try { | |||
PrivateKey merchantPrivateKey = PemUtils.loadPrivateKey(keyInputStream); | |||
X509Certificate certificate = PemUtils.loadCertificate(certInputStream); | |||
if(StringUtils.isBlank(serialNo)){ | |||
this.certSerialNo = certificate.getSerialNumber().toString(16).toUpperCase(); | |||
} | |||
AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier( | |||
new WxPayCredentials(mchId, new PrivateKeySigner(certSerialNo, merchantPrivateKey)), | |||
apiV3Key.getBytes(StandardCharsets.UTF_8), this.getCertAutoUpdateTime()); | |||
CloseableHttpClient httpClient = WxPayV3HttpClientBuilder.create() | |||
.withMerchant(mchId, certSerialNo, merchantPrivateKey) | |||
.withWechatpay(Collections.singletonList(certificate)) | |||
.withValidator(new WxPayValidator(verifier)) | |||
.build(); | |||
this.apiV3HttpClient = httpClient; | |||
this.verifier=verifier; | |||
this.privateKey = merchantPrivateKey; | |||
return httpClient; | |||
} catch (Exception e) { | |||
throw new WxPayException("v3请求构造异常!", e); | |||
} | |||
} | |||
/** | |||
* 从配置路径 加载配置 信息(支持 classpath、本地路径、网络url) | |||
* @param configPath 配置路径 | |||
* @return | |||
* @throws WxPayException | |||
*/ | |||
private InputStream loadConfigInputStream(String configPath) throws WxPayException { | |||
InputStream inputStream; | |||
final String prefix = "classpath:"; | |||
String fileHasProblemMsg = String.format(PROBLEM_MSG, configPath); | |||
String fileNotFoundMsg = String.format(NOT_FOUND_MSG, configPath); | |||
if (configPath.startsWith(prefix)) { | |||
String path = RegExUtils.removeFirst(configPath, prefix); | |||
if (!path.startsWith("/")) { | |||
path = "/" + path; | |||
} | |||
try { | |||
inputStream = ResourcesUtil.getResourceAsStream(path); | |||
if (inputStream == null) { | |||
throw new WxPayException(fileNotFoundMsg); | |||
} | |||
} catch (Exception e) { | |||
throw new WxPayException(fileNotFoundMsg, e); | |||
} | |||
} else if (configPath.startsWith("http://") || configPath.startsWith("https://")) { | |||
try { | |||
inputStream = new URL(configPath).openStream(); | |||
if (inputStream == null) { | |||
throw new WxPayException(fileNotFoundMsg); | |||
} | |||
} catch (IOException e) { | |||
throw new WxPayException(fileNotFoundMsg, e); | |||
} | |||
} else { | |||
try { | |||
File file = new File(configPath); | |||
if (!file.exists()) { | |||
throw new WxPayException(fileNotFoundMsg); | |||
} | |||
inputStream = new FileInputStream(file); | |||
} catch (IOException e) { | |||
throw new WxPayException(fileHasProblemMsg, e); | |||
} | |||
} | |||
return inputStream; | |||
} | |||
} |
@@ -0,0 +1,74 @@ | |||
package com.github.binarywang.wxpay.service; | |||
import com.github.binarywang.wxpay.bean.applyment.*; | |||
import com.github.binarywang.wxpay.exception.WxPayException; | |||
/** | |||
* 特约商户进件 | |||
* 产品介绍:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/tool/applyment4sub/chapter1_1.shtml | |||
* | |||
* @author zhouyongshen | |||
*/ | |||
public interface Applyment4SubService { | |||
/** | |||
* 提交申请单API | |||
* 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/tool/applyment4sub/chapter3_1.shtml | |||
* 接口链接:https://api.mch.weixin.qq.com/v3/applyment4sub/applyment/ | |||
* | |||
* @param request 请求对象 | |||
* @return WxPayApplymentCreateResult 响应结果 | |||
* @throws WxPayException the wx pay exception | |||
*/ | |||
WxPayApplymentCreateResult createApply(WxPayApplyment4SubCreateRequest request) throws WxPayException; | |||
/** | |||
* 通过业务申请编号查询申请状态 | |||
* 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/tool/applyment4sub/chapter3_2.shtml | |||
* 接口链接:https://api.mch.weixin.qq.com/v3/applyment4sub/applyment/business_code/{business_code} | |||
* | |||
* @param businessCode 业务申请编号 | |||
* 1、只能由数字、字母或下划线组成,建议前缀为服务商商户号。 | |||
* 2、服务商自定义的唯一编号。 | |||
* 3、每个编号对应一个申请单,每个申请单审核通过后生成一个微信支付商户号。 | |||
* 4、若申请单被驳回,可填写相同的“业务申请编号”,即可覆盖修改原申请单信息。 | |||
* 示例值:1900013511_10000 | |||
* @return the applyment state query result | |||
* @throws WxPayException the wx pay exception | |||
*/ | |||
ApplymentStateQueryResult queryApplyStatusByBusinessCode(String businessCode) throws WxPayException; | |||
/** | |||
* 通过申请单号查询申请状态 | |||
* 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/tool/applyment4sub/chapter3_2.shtml | |||
* 接口链接:https://api.mch.weixin.qq.com/v3/applyment4sub/applyment/applyment_id/{applyment_id} | |||
* | |||
* @param applymentId 微信支付分的申请单号。示例值:2000001234567890 | |||
* @return the applyment state query result | |||
* @throws WxPayException the wx pay exception | |||
*/ | |||
ApplymentStateQueryResult queryApplyStatusByApplymentId(String applymentId) throws WxPayException; | |||
/** | |||
* 通过商户号查询结算帐号状态 | |||
* 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/tool/applyment4sub/chapter3_4.shtml | |||
* 接口链接:https://api.mch.weixin.qq.com/v3/apply4sub/sub_merchants/{sub_mchid}/settlement | |||
* | |||
* @param subMchid 本服务商进件、已签约的特约商户号。 | |||
* @return the settlement info result | |||
* @throws WxPayException the wx pay exception | |||
*/ | |||
SettlementInfoResult querySettlementBySubMchid(String subMchid) throws WxPayException; | |||
/** | |||
* 修改结算帐号 | |||
* 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/tool/applyment4sub/chapter3_3.shtml | |||
* 接口链接:https://api.mch.weixin.qq.com/v3/apply4sub/sub_merchants/{sub_mchid}/modify-settlement | |||
* | |||
* @param subMchid 特约商户号 | |||
* @param request 修改结算账户请求对象信息 | |||
* @throws WxPayException the wx pay exception | |||
* @return | |||
*/ | |||
String modifySettlement(String subMchid, ModifySettlementRequest request) throws WxPayException; | |||
} |
@@ -0,0 +1,121 @@ | |||
package com.github.binarywang.wxpay.service; | |||
import com.github.binarywang.wxpay.bean.bank.*; | |||
import com.github.binarywang.wxpay.exception.WxPayException; | |||
/** | |||
* <pre> | |||
* 微信支付-银行组件 | |||
* </pre> | |||
* | |||
* @author zhongjun | |||
**/ | |||
public interface BankService { | |||
/** | |||
* <pre> | |||
* | |||
* 获取对私银行卡号开户银行 | |||
* | |||
* 请求方式:GET(HTTPS) | |||
* 请求地址:<a href="https://api.mch.weixin.qq.com/v3/capital/capitallhh/banks/search-banks-by-bank-account">https://api.mch.weixin.qq.com/v3/capital/capitallhh/banks/search-banks-by-bank-account</a> | |||
* | |||
* 文档地址:<a href="https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter11_2_1.shtml">https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter11_2_1.shtml</a> | |||
* </pre> | |||
* | |||
* @param accountNumber 银行卡号 该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial) | |||
* @return BankAccountResult 对私银行卡号开户银行信息 | |||
* @throws WxPayException . | |||
*/ | |||
BankAccountResult searchBanksByBankAccount(String accountNumber) throws WxPayException; | |||
/** | |||
* <pre> | |||
* | |||
* 查询支持个人业务的银行列表 | |||
* | |||
* 请求方式:GET(HTTPS) | |||
* 请求地址:<a href="https://api.mch.weixin.qq.com/v3/capital/capitallhh/banks/personal-banking">https://api.mch.weixin.qq.com/v3/capital/capitallhh/banks/personal-banking</a> | |||
* | |||
* 文档地址:<a href="https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter11_2_2.shtml">https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter11_2_2.shtml</a> | |||
* </pre> | |||
* | |||
* @param offset 本次查询偏移量 | |||
* @param limit 本次请求最大查询条数,最大值为200 | |||
* @return PersonalBankingResult 支持个人业务的银行列表信息 | |||
* @throws WxPayException . | |||
*/ | |||
BankingResult personalBanking(Integer offset, Integer limit) throws WxPayException; | |||
/** | |||
* <pre> | |||
* | |||
* 支持对公业务的银行列表 | |||
* | |||
* 请求方式:GET(HTTPS) | |||
* 请求地址:<a href="https://api.mch.weixin.qq.com/v3/capital/capitallhh/banks/corporate-banking">https://api.mch.weixin.qq.com/v3/capital/capitallhh/banks/corporate-banking</a> | |||
* | |||
* 文档地址:<a href="https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter11_2_3.shtml">https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter11_2_3.shtml</a> | |||
* </pre> | |||
* | |||
* @param offset 本次查询偏移量 | |||
* @param limit 本次请求最大查询条数,最大值为200 | |||
* @return BankingResult 支持对公业务的银行列表信息 | |||
* @throws WxPayException . | |||
*/ | |||
BankingResult corporateBanking(Integer offset, Integer limit) throws WxPayException; | |||
/** | |||
* <pre> | |||
* | |||
* 查询省份列表API | |||
* 通过本接口获取省份列表数据(不包含中国港澳台地区),可用于省份下的城市数据查询 | |||
* | |||
* 请求方式:GET(HTTPS) | |||
* 请求地址:<a href="https://api.mch.weixin.qq.com/v3/capital/capitallhh/areas/provinces">https://api.mch.weixin.qq.com/v3/capital/capitallhh/areas/provinces</a> | |||
* | |||
* 文档地址:<a href="https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter11_2_4.shtml">https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter11_2_4.shtml</a> | |||
* </pre> | |||
* | |||
* @return ProvincesResult 省份列表信息 | |||
* @throws WxPayException . | |||
*/ | |||
ProvincesResult areasProvinces() throws WxPayException; | |||
/** | |||
* <pre> | |||
* | |||
* 查询城市列表API | |||
* 通过本接口根据省份编码获取省份下的城市列表信息,不包含中国港澳台地区城市信息,可用于支行数据过滤查询 | |||
* | |||
* 请求方式:GET(HTTPS) | |||
* 请求地址:<a href="https://api.mch.weixin.qq.com/v3/capital/capitallhh/areas/provinces/{province_code}/cities">https://api.mch.weixin.qq.com/v3/capital/capitallhh/areas/provinces/{province_code}/cities</a> | |||
* | |||
* 文档地址:<a href="https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter11_2_5.shtml">https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter11_2_5.shtml</a> | |||
* </pre> | |||
* | |||
* @return CitiesResult 城市列表信息 | |||
* @throws WxPayException . | |||
*/ | |||
CitiesResult areasCities(Integer provinceCode) throws WxPayException; | |||
/** | |||
* <pre> | |||
* | |||
* 查询支行列表API | |||
* 本接口可以用于根据银行别名编码(仅支持需要填写支行的银行别名编码)和城市编码过滤查询支行列表数据 | |||
* | |||
* 请求方式:GET(HTTPS) | |||
* 请求地址:<a href="https://api.mch.weixin.qq.com/v3/capital/capitallhh/banks/{bank_alias_code}/branches">https://api.mch.weixin.qq.com/v3/capital/capitallhh/banks/{bank_alias_code}/branches</a> | |||
* | |||
* 文档地址:<a href="https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter11_2_5.shtml">https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter11_2_5.shtml</a> | |||
* </pre> | |||
* | |||
* @param bankAliasCode 银行别名的编码,查询支行接口仅支持需要填写支行的银行别名编码。示例值:1000006247 | |||
* @param cityCode 城市编码,唯一标识一座城市,用于结合银行别名编码查询支行列表。示例值:536 | |||
* @param offset 非负整数,表示该次请求资源的起始位置,从0开始计数。调用方选填,默认为0。offset为20,limit为100时,查询第21-120条数据 | |||
* @param limit 非0非负的整数,该次请求可返回的最大资源条数。示例值:200 | |||
* @return BankBranchesResult 城市列表信息 | |||
* @throws WxPayException . | |||
*/ | |||
BankBranchesResult bankBranches(String bankAliasCode, Integer cityCode, Integer offset, Integer limit) throws WxPayException; | |||
} |
@@ -0,0 +1,59 @@ | |||
package com.github.binarywang.wxpay.service; | |||
import com.github.binarywang.wxpay.bean.businesscircle.*; | |||
import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader; | |||
import com.github.binarywang.wxpay.exception.WxPayException; | |||
/** | |||
* <pre> | |||
* 微信支付智慧商圈API | |||
* </pre> | |||
* | |||
* @author thinsstar | |||
*/ | |||
public interface BusinessCircleService { | |||
/** | |||
* <pre> | |||
* 智慧商圈接口-商圈积分同步API | |||
* 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/businesscircle/chapter3_2.shtml | |||
* 接口链接:https://api.mch.weixin.qq.com/v3/businesscircle/points/notify | |||
* </pre> | |||
* | |||
* @param request 请求对象 | |||
* @throws WxPayException the wx pay exception | |||
*/ | |||
String notifyPoints(PointsNotifyRequest request) throws WxPayException; | |||
BusinessCircleNotifyData parseNotifyData(String data, SignatureHeader header) throws WxPayException; | |||
PaidResult decryptPaidNotifyDataResource(BusinessCircleNotifyData data) throws WxPayException; | |||
RefundResult decryptRefundNotifyDataResource(BusinessCircleNotifyData data) throws WxPayException; | |||
MemberCardAuthorizeNotifyResult decryptMemberCardAuthorizeNotifyDataResource(BusinessCircleNotifyData data) throws WxPayException; | |||
/** | |||
* 授权查询 | |||
* https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter8_6_4.shtml | |||
* @return | |||
* @throws WxPayException | |||
*/ | |||
MemberCardAuthorizeResult getAuthorizations(String openid) throws WxPayException; | |||
/** | |||
* 查询待积分状态 | |||
* @param brandid | |||
* @param openid | |||
* @return | |||
* @throws WxPayException | |||
*/ | |||
PointsCommitStatusResult getPointsCommitStatus(String brandid,String openid) throws WxPayException; | |||
/** | |||
* 停车状态同步 | |||
* https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter8_6_5.shtml | |||
* @param request | |||
* @throws WxPayException | |||
*/ | |||
void notifyParkings(ParkingNotifyRequest request) throws WxPayException; | |||
} |
@@ -0,0 +1,50 @@ | |||
package com.github.binarywang.wxpay.service; | |||
import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader; | |||
import com.github.binarywang.wxpay.bean.membercard.*; | |||
import com.github.binarywang.wxpay.exception.WxPayException; | |||
/** | |||
* <pre> | |||
* 会员卡相关接口 | |||
* </pre> | |||
* | |||
* @author thinsstar | |||
*/ | |||
public interface MemberCardService { | |||
MemberCardNotifyData parseNotifyData(String data, SignatureHeader header) throws WxPayException; | |||
MemberCardActivateResult decryptActivateNotifyDataResource(MemberCardNotifyData data) throws WxPayException; | |||
/** | |||
* 查询会员卡信息 | |||
* https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_9_6.shtml | |||
* @param card_id | |||
* @param code | |||
* @return | |||
* @throws WxPayException | |||
*/ | |||
MemberCardResult getMemberCard(String card_id,String code) throws WxPayException; | |||
/** | |||
* 修改用户会员卡信息API | |||
* https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_9_8.shtml | |||
* @param card_id | |||
* @param code | |||
* @param request | |||
* @throws WxPayException | |||
*/ | |||
void updMemberCard(String card_id, String code, MemberCardUpdRequest request) throws WxPayException; | |||
/** | |||
* 设置用户会员权益信息api | |||
* https://pay.weixin.qq.com/wiki/doc/apiv3_partner/Offline/apis/chapter5_9_23.shtml | |||
* @param card_id | |||
* @param code | |||
* @param request | |||
* @throws WxPayException | |||
*/ | |||
void setMemberCardRights(String card_id,String code,MemberCardRightsRequest request) throws WxPayException; | |||
} |
@@ -0,0 +1,46 @@ | |||
package com.github.binarywang.wxpay.service; | |||
import com.github.binarywang.wxpay.bean.media.ImageUploadResult; | |||
import com.github.binarywang.wxpay.exception.WxPayException; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
/** | |||
* <pre> | |||
* 微信支付通用媒体接口. | |||
* </pre> | |||
* | |||
* @author zhouyongshen | |||
*/ | |||
public interface MerchantMediaService { | |||
/** | |||
* <pre> | |||
* 通用接口-图片上传API | |||
* 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/tool/chapter3_1.shtml | |||
* 接口链接:https://api.mch.weixin.qq.com/v3/merchant/media/upload | |||
* </pre> | |||
* | |||
* @param imageFile 需要上传的图片文件 | |||
* @return ImageUploadResult 微信返回的媒体文件标识Id。示例值:6uqyGjGrCf2GtyXP8bxrbuH9-aAoTjH-rKeSl3Lf4_So6kdkQu4w8BYVP3bzLtvR38lxt4PjtCDXsQpzqge_hQEovHzOhsLleGFQVRF-U_0 | |||
* @throws WxPayException the wx pay exception | |||
*/ | |||
ImageUploadResult imageUploadV3(File imageFile) throws WxPayException, IOException; | |||
/** | |||
* <pre> | |||
* 通用接口-图片上传API | |||
* 文档详见: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/tool/chapter3_1.shtml | |||
* 接口链接:https://api.mch.weixin.qq.com/v3/merchant/media/upload | |||
* </pre> | |||
* | |||
* @param inputStream 需要上传的图片文件流 | |||
* @param fileName 需要上传的图片文件名 | |||
* @return ImageUploadResult 微信返回的媒体文件标识Id。示例值:6uqyGjGrCf2GtyXP8bxrbuH9-aAoTjH-rKeSl3Lf4_So6kdkQu4w8BYVP3bzLtvR38lxt4PjtCDXsQpzqge_hQEovHzOhsLleGFQVRF-U_0 | |||
* @throws WxPayException the wx pay exception | |||
*/ | |||
ImageUploadResult imageUploadV3(InputStream inputStream, String fileName) throws WxPayException, IOException; | |||
} |
@@ -9,8 +9,11 @@ import com.github.binarywang.wxpay.bean.request.*; | |||
import com.github.binarywang.wxpay.bean.result.*; | |||
import com.github.binarywang.wxpay.config.WxPayConfig; | |||
import com.github.binarywang.wxpay.exception.WxPayException; | |||
import org.apache.http.client.methods.HttpPost; | |||
import org.apache.http.client.methods.HttpRequestBase; | |||
import java.io.File; | |||
import java.io.InputStream; | |||
import java.util.Date; | |||
import java.util.Map; | |||
@@ -53,6 +56,87 @@ public interface WxPayService { | |||
*/ | |||
String post(String url, String requestStr, boolean useKey) throws WxPayException; | |||
/** | |||
* 发送post请求,得到响应字符串. | |||
* | |||
* @param url 请求地址 | |||
* @param requestStr 请求信息 | |||
* @return 返回请求结果字符串 string | |||
* @throws WxPayException the wx pay exception | |||
*/ | |||
String postV3(String url, String requestStr) throws WxPayException; | |||
/** | |||
* 发送patch请求,得到响应字符串. | |||
* | |||
* @param url 请求地址 | |||
* @param requestStr 请求信息 | |||
* @return 返回请求结果字符串 string | |||
* @throws WxPayException the wx pay exception | |||
*/ | |||
String patchV3(String url, String requestStr) throws WxPayException; | |||
/** | |||
* 发送post请求,得到响应字符串. | |||
* <p> | |||
* 部分字段会包含敏感信息,所以在提交前需要在请求头中会包含"Wechatpay-Serial"信息 | |||
* | |||
* @param url 请求地址 | |||
* @param requestStr 请求信息 | |||
* @return 返回请求结果字符串 string | |||
* @throws WxPayException the wx pay exception | |||
*/ | |||
String postV3WithWechatpaySerial(String url, String requestStr) throws WxPayException; | |||
/** | |||
* 发送post请求,得到响应字符串. | |||
* | |||
* @param url 请求地址 | |||
* @param httpPost 请求信息 | |||
* @return 返回请求结果字符串 string | |||
* @throws WxPayException the wx pay exception | |||
*/ | |||
String postV3(String url, HttpPost httpPost) throws WxPayException; | |||
/** | |||
* 发送http请求,得到响应字符串. | |||
* | |||
* @param url 请求地址 | |||
* @param httpRequest 请求信息,可以是put,post,get,delete等请求 | |||
* @return 返回请求结果字符串 string | |||
* @throws WxPayException the wx pay exception | |||
*/ | |||
String requestV3(String url, HttpRequestBase httpRequest) throws WxPayException; | |||
/** | |||
* 发送get V3请求,得到响应字符串. | |||
* | |||
* @param url 请求地址 | |||
* @return 返回请求结果字符串 string | |||
* @throws WxPayException the wx pay exception | |||
*/ | |||
String getV3(String url) throws WxPayException; | |||
/** | |||
* 发送get请求,得到响应字符串. | |||
* <p> | |||
* 部分字段会包含敏感信息,所以在提交前需要在请求头中会包含"Wechatpay-Serial"信息 | |||
* | |||
* @param url 请求地址 | |||
* @return 返回请求结果字符串 string | |||
* @throws WxPayException the wx pay exception | |||
*/ | |||
String getV3WithWechatPaySerial(String url) throws WxPayException; | |||
/** | |||
* 发送下载 V3请求,得到响应流. | |||
* | |||
* @param url 请求地址 | |||
* @return 返回请求响应流 input stream | |||
* @throws WxPayException the wx pay exception | |||
*/ | |||
InputStream downloadV3(String url) throws WxPayException; | |||
/** | |||
* 获取企业付款服务类. | |||
* | |||
@@ -74,6 +158,41 @@ public interface WxPayService { | |||
*/ | |||
ProfitSharingService getProfitSharingService(); | |||
/** | |||
* 获取微信支付智慧商圈服务类 | |||
* | |||
* @return the business circle service | |||
*/ | |||
BusinessCircleService getBusinessCircleService(); | |||
/** | |||
* 获取会员卡服务类 | |||
* | |||
* @return the business circle service | |||
*/ | |||
MemberCardService getMemberCardService(); | |||
/** | |||
* 特约商户进件服务 | |||
* | |||
* @return | |||
*/ | |||
Applyment4SubService getApplyment4SubService(); | |||
/** | |||
* 媒体上传服务 | |||
* | |||
* @return | |||
*/ | |||
MerchantMediaService getMerchantMediaService(); | |||
/** | |||
* 获取银行组件服务 | |||
* | |||
* @return 银行组件服务 | |||
*/ | |||
BankService getBankService(); | |||
/** | |||
* 设置企业付款服务类,允许开发者自定义实现类. | |||
* | |||
@@ -81,6 +200,7 @@ public interface WxPayService { | |||
*/ | |||
void setEntPayService(EntPayService entPayService); | |||
/** | |||
* <pre> | |||
* 查询订单. | |||
@@ -0,0 +1,66 @@ | |||
package com.github.binarywang.wxpay.service.impl; | |||
import com.github.binarywang.wxpay.bean.applyment.*; | |||
import com.github.binarywang.wxpay.exception.WxPayException; | |||
import com.github.binarywang.wxpay.service.Applyment4SubService; | |||
import com.github.binarywang.wxpay.service.WxPayService; | |||
import com.github.binarywang.wxpay.v3.util.RsaCryptoUtil; | |||
import com.google.gson.Gson; | |||
import com.google.gson.GsonBuilder; | |||
import lombok.RequiredArgsConstructor; | |||
import lombok.extern.slf4j.Slf4j; | |||
import java.security.cert.X509Certificate; | |||
@Slf4j | |||
@RequiredArgsConstructor | |||
public class Applyment4SubServiceImpl implements Applyment4SubService { | |||
private static final Gson GSON = new GsonBuilder().create(); | |||
private final WxPayService payService; | |||
private void encryptFiled(Object request) throws WxPayException { | |||
X509Certificate validCertificate = payService.getConfig().getVerifier().getValidCertificate(); | |||
RsaCryptoUtil.encryptFields(request, validCertificate); | |||
} | |||
@Override | |||
public WxPayApplymentCreateResult createApply(WxPayApplyment4SubCreateRequest request) throws WxPayException { | |||
String url = String.format("%s/v3/applyment4sub/applyment/", this.payService.getPayBaseUrl()); | |||
encryptFiled(request); | |||
String result = payService.postV3WithWechatpaySerial(url, GSON.toJson(request)); | |||
return GSON.fromJson(result, WxPayApplymentCreateResult.class); | |||
} | |||
@Override | |||
public ApplymentStateQueryResult queryApplyStatusByBusinessCode(String businessCode) throws WxPayException { | |||
String url = String.format("%s/v3/applyment4sub/applyment/business_code/%s", this.payService.getPayBaseUrl(), businessCode); | |||
String result = payService.getV3(url); | |||
return GSON.fromJson(result, ApplymentStateQueryResult.class); | |||
} | |||
@Override | |||
public ApplymentStateQueryResult queryApplyStatusByApplymentId(String applymentId) throws WxPayException { | |||
String url = String.format("%s/v3/applyment4sub/applyment/applyment_id/%s", this.payService.getPayBaseUrl(), applymentId); | |||
String result = payService.getV3(url); | |||
return GSON.fromJson(result, ApplymentStateQueryResult.class); | |||
} | |||
@Override | |||
public SettlementInfoResult querySettlementBySubMchid(String subMchid) throws WxPayException { | |||
String url = String.format("%s/v3/apply4sub/sub_merchants/%s/settlement", this.payService.getPayBaseUrl(), subMchid); | |||
String result = payService.getV3(url); | |||
return GSON.fromJson(result, SettlementInfoResult.class); | |||
} | |||
@Override | |||
public String modifySettlement(String subMchid, ModifySettlementRequest request) throws WxPayException { | |||
String url = String.format("%s/v3/apply4sub/sub_merchants/%s/modify-settlement", this.payService.getPayBaseUrl(), subMchid); | |||
encryptFiled(request); | |||
return payService.postV3WithWechatpaySerial(url, GSON.toJson(request)); | |||
} | |||
} |
@@ -0,0 +1,68 @@ | |||
package com.github.binarywang.wxpay.service.impl; | |||
import com.github.binarywang.wxpay.bean.bank.*; | |||
import com.github.binarywang.wxpay.exception.WxPayException; | |||
import com.github.binarywang.wxpay.service.BankService; | |||
import com.github.binarywang.wxpay.service.WxPayService; | |||
import com.google.gson.Gson; | |||
import com.google.gson.GsonBuilder; | |||
import lombok.RequiredArgsConstructor; | |||
/** | |||
* 微信支付-银行组件 | |||
* | |||
* @author zhongjun | |||
**/ | |||
@RequiredArgsConstructor | |||
public class BankServiceImpl implements BankService { | |||
private final WxPayService payService; | |||
private static final Gson GSON = new GsonBuilder().create(); | |||
@Override | |||
public BankAccountResult searchBanksByBankAccount(String accountNumber) throws WxPayException { | |||
String url = String.format("%s/v3/capital/capitallhh/banks/search-banks-by-bank-account?account_number=%s", this.payService.getPayBaseUrl(), accountNumber); | |||
String response = payService.getV3WithWechatPaySerial(url); | |||
return GSON.fromJson(response, BankAccountResult.class); | |||
} | |||
@Override | |||
public BankingResult personalBanking(Integer offset, Integer limit) throws WxPayException { | |||
offset = offset == null ? 0 : offset; | |||
limit = limit == null ? 200 : limit; | |||
String url = String.format("%s/v3/capital/capitallhh/banks/personal-banking?offset=%s&limit=%s", this.payService.getPayBaseUrl(), offset, limit); | |||
String response = payService.getV3(url); | |||
return GSON.fromJson(response, BankingResult.class); | |||
} | |||
@Override | |||
public BankingResult corporateBanking(Integer offset, Integer limit) throws WxPayException { | |||
offset = offset == null ? 0 : offset; | |||
limit = limit == null ? 200 : limit; | |||
String url = String.format("%s/v3/capital/capitallhh/banks/corporate-banking?offset=%s&limit=%s", this.payService.getPayBaseUrl(), offset, limit); | |||
String response = payService.getV3(url); | |||
return GSON.fromJson(response, BankingResult.class); | |||
} | |||
@Override | |||
public ProvincesResult areasProvinces() throws WxPayException { | |||
String url = String.format("%s/v3/capital/capitallhh/areas/provinces", this.payService.getPayBaseUrl()); | |||
String response = payService.getV3WithWechatPaySerial(url); | |||
return GSON.fromJson(response, ProvincesResult.class); | |||
} | |||
@Override | |||
public CitiesResult areasCities(Integer provinceCode) throws WxPayException { | |||
String url = String.format("%s/v3/capital/capitallhh/areas/provinces/%s/cities", this.payService.getPayBaseUrl(), provinceCode); | |||
String response = payService.getV3WithWechatPaySerial(url); | |||
return GSON.fromJson(response, CitiesResult.class); | |||
} | |||
@Override | |||
public BankBranchesResult bankBranches(String bankAliasCode, Integer cityCode, Integer offset, Integer limit) throws WxPayException { | |||
offset = offset == null ? 0 : offset; | |||
limit = limit == null ? 200 : limit; | |||
String url = String.format("%s/v3/capital/capitallhh/banks/%s/branches?city_code=%s&offset=%s&limit=%s", this.payService.getPayBaseUrl(), bankAliasCode, cityCode, offset, limit); | |||
String response = payService.getV3(url); | |||
return GSON.fromJson(response, BankBranchesResult.class); | |||
} | |||
} |
@@ -16,10 +16,7 @@ import com.github.binarywang.wxpay.config.WxPayConfig; | |||
import com.github.binarywang.wxpay.constant.WxPayConstants.SignType; | |||
import com.github.binarywang.wxpay.constant.WxPayConstants.TradeType; | |||
import com.github.binarywang.wxpay.exception.WxPayException; | |||
import com.github.binarywang.wxpay.service.EntPayService; | |||
import com.github.binarywang.wxpay.service.ProfitSharingService; | |||
import com.github.binarywang.wxpay.service.RedpackService; | |||
import com.github.binarywang.wxpay.service.WxPayService; | |||
import com.github.binarywang.wxpay.service.*; | |||
import com.github.binarywang.wxpay.util.SignUtils; | |||
import com.github.binarywang.wxpay.util.XmlConfig; | |||
import com.google.common.base.Joiner; | |||
@@ -63,6 +60,11 @@ public abstract class BaseWxPayServiceImpl implements WxPayService { | |||
private EntPayService entPayService = new EntPayServiceImpl(this); | |||
private ProfitSharingService profitSharingService = new ProfitSharingServiceImpl(this); | |||
private RedpackService redpackService = new RedpackServiceImpl(this); | |||
private BusinessCircleService businessCircleService = new BusinessCircleServiceImpl(this); | |||
private MemberCardService memberCardServiceService = new MemberCardServiceImpl(this); | |||
private Applyment4SubService applyment4SubService = new Applyment4SubServiceImpl(this); | |||
private MerchantMediaService merchantMediaService = new MerchantMediaServiceImpl(this); | |||
private BankService bankService = new BankServiceImpl(this); | |||
/** | |||
* The Config. | |||
@@ -79,11 +81,36 @@ public abstract class BaseWxPayServiceImpl implements WxPayService { | |||
return profitSharingService; | |||
} | |||
@Override | |||
public BusinessCircleService getBusinessCircleService() { | |||
return this.businessCircleService; | |||
} | |||
@Override | |||
public MemberCardService getMemberCardService(){ | |||
return this.memberCardServiceService; | |||
} | |||
@Override | |||
public RedpackService getRedpackService() { | |||
return this.redpackService; | |||
} | |||
@Override | |||
public Applyment4SubService getApplyment4SubService() { | |||
return applyment4SubService; | |||
} | |||
@Override | |||
public MerchantMediaService getMerchantMediaService() { | |||
return merchantMediaService; | |||
} | |||
@Override | |||
public BankService getBankService() { | |||
return bankService; | |||
} | |||
@Override | |||
public void setEntPayService(EntPayService entPayService) { | |||
this.entPayService = entPayService; | |||
@@ -0,0 +1,125 @@ | |||
package com.github.binarywang.wxpay.service.impl; | |||
import com.github.binarywang.wxpay.bean.businesscircle.*; | |||
import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader; | |||
import com.github.binarywang.wxpay.exception.WxPayException; | |||
import com.github.binarywang.wxpay.service.BusinessCircleService; | |||
import com.github.binarywang.wxpay.service.WxPayService; | |||
import com.github.binarywang.wxpay.v3.util.AesUtils; | |||
import com.github.binarywang.wxpay.v3.util.RsaCryptoUtil; | |||
import com.google.gson.Gson; | |||
import com.google.gson.GsonBuilder; | |||
import lombok.RequiredArgsConstructor; | |||
import lombok.extern.slf4j.Slf4j; | |||
import java.io.IOException; | |||
import java.nio.charset.StandardCharsets; | |||
import java.security.GeneralSecurityException; | |||
import java.util.Objects; | |||
/** | |||
* 微信支付-微信支付智慧商圈service | |||
* | |||
* @author thinsstar | |||
*/ | |||
@Slf4j | |||
@RequiredArgsConstructor | |||
public class BusinessCircleServiceImpl implements BusinessCircleService { | |||
private static final Gson GSON = new GsonBuilder().create(); | |||
private final WxPayService payService; | |||
@Override | |||
public String notifyPoints(PointsNotifyRequest request) throws WxPayException { | |||
String url = String.format("%s/v3/businesscircle/points/notify", this.payService.getPayBaseUrl()); | |||
RsaCryptoUtil.encryptFields(request, this.payService.getConfig().getVerifier().getValidCertificate()); | |||
return this.payService.postV3WithWechatpaySerial(url, GSON.toJson(request)); | |||
} | |||
/** | |||
* 校验通知签名 | |||
* | |||
* @param header 通知头信息 | |||
* @param data 通知数据 | |||
* @return true:校验通过 false:校验不通过 | |||
*/ | |||
private boolean verifyNotifySign(SignatureHeader header, String data) { | |||
String beforeSign = String.format("%s%n%s%n%s%n", header.getTimeStamp(), header.getNonce(), data); | |||
return payService.getConfig().getVerifier().verify(header.getSerialNo(), | |||
beforeSign.getBytes(StandardCharsets.UTF_8), header.getSigned()); | |||
} | |||
@Override | |||
public BusinessCircleNotifyData parseNotifyData(String data, SignatureHeader header) throws WxPayException { | |||
if (Objects.nonNull(header) && !this.verifyNotifySign(header, data)) { | |||
throw new WxPayException("非法请求,头部信息验证失败"); | |||
} | |||
return GSON.fromJson(data, BusinessCircleNotifyData.class); | |||
} | |||
@Override | |||
public PaidResult decryptPaidNotifyDataResource(BusinessCircleNotifyData data) throws WxPayException { | |||
BusinessCircleNotifyData.Resource resource = data.getResource(); | |||
String cipherText = resource.getCipherText(); | |||
String associatedData = resource.getAssociatedData(); | |||
String nonce = resource.getNonce(); | |||
String apiV3Key = this.payService.getConfig().getApiV3Key(); | |||
try { | |||
return GSON.fromJson(AesUtils.decryptToString(associatedData, nonce, cipherText, apiV3Key), PaidResult.class); | |||
} catch (GeneralSecurityException | IOException e) { | |||
throw new WxPayException("解析报文异常!", e); | |||
} | |||
} | |||
@Override | |||
public RefundResult decryptRefundNotifyDataResource(BusinessCircleNotifyData data) throws WxPayException { | |||
BusinessCircleNotifyData.Resource resource = data.getResource(); | |||
String cipherText = resource.getCipherText(); | |||
String associatedData = resource.getAssociatedData(); | |||
String nonce = resource.getNonce(); | |||
String apiV3Key = this.payService.getConfig().getApiV3Key(); | |||
try { | |||
return GSON.fromJson(AesUtils.decryptToString(associatedData, nonce, cipherText, apiV3Key), RefundResult.class); | |||
} catch (GeneralSecurityException | IOException e) { | |||
throw new WxPayException("解析报文异常!", e); | |||
} | |||
} | |||
@Override | |||
public MemberCardAuthorizeNotifyResult decryptMemberCardAuthorizeNotifyDataResource(BusinessCircleNotifyData data) throws WxPayException { | |||
BusinessCircleNotifyData.Resource resource = data.getResource(); | |||
String cipherText = resource.getCipherText(); | |||
String associatedData = resource.getAssociatedData(); | |||
String nonce = resource.getNonce(); | |||
String apiV3Key = this.payService.getConfig().getApiV3Key(); | |||
try { | |||
return GSON.fromJson(AesUtils.decryptToString(associatedData, nonce, cipherText, apiV3Key), MemberCardAuthorizeNotifyResult.class); | |||
} catch (GeneralSecurityException | IOException e) { | |||
throw new WxPayException("解析报文异常!", e); | |||
} | |||
} | |||
@Override | |||
public MemberCardAuthorizeResult getAuthorizations(String openid) throws WxPayException { | |||
String url = String.format("%s/v3/businesscircle/user-authorizations/%s?sub_mchid=%s&appid=%s", | |||
this.payService.getPayBaseUrl(),openid,this.payService.getConfig().getSubMchId(),this.payService.getConfig().getAppId()); | |||
String response = this.payService.getV3WithWechatPaySerial(url); | |||
return GSON.fromJson(response,MemberCardAuthorizeResult.class); | |||
} | |||
@Override | |||
public PointsCommitStatusResult getPointsCommitStatus(String brandid, String openid) throws WxPayException { | |||
String url = String.format("%s/v3/businesscircle/user/%s/points/commit_status?sub_mchid=%s&brandid=%s&appid=%s", | |||
this.payService.getPayBaseUrl(),openid,this.payService.getConfig().getSubMchId(),brandid,this.payService.getConfig().getAppId()); | |||
String response = this.payService.getV3WithWechatPaySerial(url); | |||
return GSON.fromJson(response,PointsCommitStatusResult.class); | |||
} | |||
@Override | |||
public void notifyParkings(ParkingNotifyRequest request) throws WxPayException { | |||
request.setAppid(this.payService.getConfig().getAppId()); | |||
request.setSubMchid(this.payService.getConfig().getSubMchId()); | |||
String url = String.format("%s/v3/businesscircle/parkings", this.payService.getPayBaseUrl()); | |||
RsaCryptoUtil.encryptFields(request, this.payService.getConfig().getVerifier().getValidCertificate()); | |||
this.payService.postV3WithWechatpaySerial(url, GSON.toJson(request)); | |||
} | |||
} |
@@ -0,0 +1,87 @@ | |||
package com.github.binarywang.wxpay.service.impl; | |||
import com.github.binarywang.wxpay.bean.ecommerce.SignatureHeader; | |||
import com.github.binarywang.wxpay.bean.membercard.*; | |||
import com.github.binarywang.wxpay.exception.WxPayException; | |||
import com.github.binarywang.wxpay.service.MemberCardService; | |||
import com.github.binarywang.wxpay.service.WxPayService; | |||
import com.github.binarywang.wxpay.v3.util.AesUtils; | |||
import com.github.binarywang.wxpay.v3.util.RsaCryptoUtil; | |||
import com.google.gson.Gson; | |||
import com.google.gson.GsonBuilder; | |||
import lombok.RequiredArgsConstructor; | |||
import lombok.extern.slf4j.Slf4j; | |||
import java.io.IOException; | |||
import java.nio.charset.StandardCharsets; | |||
import java.security.GeneralSecurityException; | |||
import java.util.Objects; | |||
/** | |||
* 会员卡相关 | |||
* | |||
* @author thinsstar | |||
*/ | |||
@Slf4j | |||
@RequiredArgsConstructor | |||
public class MemberCardServiceImpl implements MemberCardService { | |||
private static final Gson GSON = new GsonBuilder().create(); | |||
private final WxPayService payService; | |||
/** | |||
* 校验通知签名 | |||
* | |||
* @param header 通知头信息 | |||
* @param data 通知数据 | |||
* @return true:校验通过 false:校验不通过 | |||
*/ | |||
private boolean verifyNotifySign(SignatureHeader header, String data) { | |||
String beforeSign = String.format("%s%n%s%n%s%n", header.getTimeStamp(), header.getNonce(), data); | |||
return payService.getConfig().getVerifier().verify(header.getSerialNo(), | |||
beforeSign.getBytes(StandardCharsets.UTF_8), header.getSigned()); | |||
} | |||
@Override | |||
public MemberCardNotifyData parseNotifyData(String data, SignatureHeader header) throws WxPayException { | |||
if (Objects.nonNull(header) && !this.verifyNotifySign(header, data)) { | |||
throw new WxPayException("非法请求,头部信息验证失败"); | |||
} | |||
return GSON.fromJson(data, MemberCardNotifyData.class); | |||
} | |||
@Override | |||
public MemberCardActivateResult decryptActivateNotifyDataResource(MemberCardNotifyData data) throws WxPayException { | |||
MemberCardNotifyData.Resource resource = data.getResource(); | |||
String cipherText = resource.getCipherText(); | |||
String associatedData = resource.getAssociatedData(); | |||
String nonce = resource.getNonce(); | |||
String apiV3Key = this.payService.getConfig().getApiV3Key(); | |||
try { | |||
return GSON.fromJson(AesUtils.decryptToString(associatedData, nonce, cipherText, apiV3Key), MemberCardActivateResult.class); | |||
} catch (GeneralSecurityException | IOException e) { | |||
throw new WxPayException("解析报文异常!", e); | |||
} | |||
} | |||
@Override | |||
public MemberCardResult getMemberCard(String card_id, String code) throws WxPayException { | |||
String url = String.format("%s/v3/marketing/membercard-open/cards/%s/codes/%s", this.payService.getPayBaseUrl(),card_id,code); | |||
String response = this.payService.getV3WithWechatPaySerial(url); | |||
return GSON.fromJson(response,MemberCardResult.class); | |||
} | |||
@Override | |||
public void updMemberCard(String card_id, String code, MemberCardUpdRequest request) throws WxPayException { | |||
String url = String.format("%s/v3/marketing/membercard-open/cards/%s/codes/%s", this.payService.getPayBaseUrl(),card_id,code); | |||
RsaCryptoUtil.encryptFields(request, this.payService.getConfig().getVerifier().getValidCertificate()); | |||
this.payService.patchV3(url, GSON.toJson(request)); | |||
} | |||
@Override | |||
public void setMemberCardRights(String card_id, String code, MemberCardRightsRequest request) throws WxPayException { | |||
String url = String.format("%s/v3/marketing/membercard-open/cards/%s/codes/%s/rights", this.payService.getPayBaseUrl(),card_id,code); | |||
RsaCryptoUtil.encryptFields(request, this.payService.getConfig().getVerifier().getValidCertificate()); | |||
this.payService.patchV3(url, GSON.toJson(request)); | |||
} | |||
} |
@@ -0,0 +1,60 @@ | |||
package com.github.binarywang.wxpay.service.impl; | |||
import com.github.binarywang.wxpay.bean.media.ImageUploadResult; | |||
import com.github.binarywang.wxpay.exception.WxPayException; | |||
import com.github.binarywang.wxpay.service.MerchantMediaService; | |||
import com.github.binarywang.wxpay.service.WxPayService; | |||
import com.github.binarywang.wxpay.v3.WechatPayUploadHttpPost; | |||
import lombok.RequiredArgsConstructor; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.apache.commons.codec.digest.DigestUtils; | |||
import java.io.*; | |||
import java.net.URI; | |||
/** | |||
* 微信支付-媒体文件上传service | |||
* @author zhouyongshen | |||
*/ | |||
@Slf4j | |||
@RequiredArgsConstructor | |||
public class MerchantMediaServiceImpl implements MerchantMediaService { | |||
private final WxPayService payService; | |||
@Override | |||
public ImageUploadResult imageUploadV3(File imageFile) throws WxPayException,IOException { | |||
String url = String.format("%s/v3/merchant/media/upload", this.payService.getPayBaseUrl()); | |||
try (FileInputStream s1 = new FileInputStream(imageFile)) { | |||
String sha256 = DigestUtils.sha256Hex(s1); | |||
try (InputStream s2 = new FileInputStream(imageFile)) { | |||
WechatPayUploadHttpPost request = new WechatPayUploadHttpPost.Builder(URI.create(url)) | |||
.withImage(imageFile.getName(), sha256, s2) | |||
.build(); | |||
String result = this.payService.postV3(url, request); | |||
return ImageUploadResult.fromJson(result); | |||
} | |||
} | |||
} | |||
@Override | |||
public ImageUploadResult imageUploadV3(InputStream inputStream, String fileName) throws WxPayException, IOException { | |||
String url = String.format("%s/v3/merchant/media/upload", this.payService.getPayBaseUrl()); | |||
try(ByteArrayOutputStream bos = new ByteArrayOutputStream()) { | |||
byte[] buffer = new byte[2048]; | |||
int len; | |||
while ((len = inputStream.read(buffer)) > -1) { | |||
bos.write(buffer, 0, len); | |||
} | |||
bos.flush(); | |||
byte[] data = bos.toByteArray(); | |||
String sha256 = DigestUtils.sha256Hex(data); | |||
WechatPayUploadHttpPost request = new WechatPayUploadHttpPost.Builder(URI.create(url)) | |||
.withImage(fileName, sha256, new ByteArrayInputStream(data)) | |||
.build(); | |||
String result = this.payService.postV3(url, request); | |||
return ImageUploadResult.fromJson(result); | |||
} | |||
} | |||
} |