精简WeixinAccount类及其配置文件
This commit is contained in:
parent
0cca9d6d02
commit
954ee2175c
11
CHANGE.md
11
CHANGE.md
@ -381,4 +381,13 @@
|
||||
|
||||
+ 精简函数上的@link注释
|
||||
|
||||
+ 新增媒体文件上传、下载结果类([MediaUploadResult.java](./weixin4j-base/src/main/java/com/foxinmy/weixin4j/model/MediaUploadResult.java),[MediaDownloadResult.java](./weixin4j-base/src/main/java/com/foxinmy/weixin4j/model/MediaDownloadResult.java))
|
||||
+ 新增媒体文件上传、下载结果类([MediaUploadResult.java](./weixin4j-base/src/main/java/com/foxinmy/weixin4j/model/MediaUploadResult.java),[MediaDownloadResult.java](./weixin4j-base/src/main/java/com/foxinmy/weixin4j/model/MediaDownloadResult.java))
|
||||
|
||||
* 2015-07-29
|
||||
|
||||
+ 精简WeixinAccount类及其配置文件
|
||||
|
||||
+ **weixin4j-mp**: 新增二维码结果类[QRResult.java](./weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/QRResult.java)并将二维码接口[QRApi.java](./weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/QrApi.java)名称变更为createQR和createQRFile
|
||||
|
||||
+ **weixin4j-mp**: [Oauth授权](./weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/OauthApi.java)跳转的uri在配置文件的属性名改为`oauth_redirect_uri`
|
||||
|
||||
@ -34,7 +34,7 @@ public class Button implements Serializable {
|
||||
*
|
||||
* @see com.foxinmy.weixin4j.type.ButtonType
|
||||
*/
|
||||
private String type;
|
||||
private ButtonType type;
|
||||
/**
|
||||
* 菜单KEY值,根据type的类型而定,用于消息接口推送,不超过128字节.
|
||||
* <p>
|
||||
@ -43,7 +43,9 @@ public class Button implements Serializable {
|
||||
* <p>
|
||||
* 使用API设置的自定义菜单:</br>
|
||||
* click、scancode_push、scancode_waitmsg、pic_sysphoto、pic_photo_or_album
|
||||
* 、</br> pic_weixin、location_select:保存为key;view:保存为url;media_id、view_limited:保存为media_id
|
||||
* 、</br>
|
||||
* pic_weixin、location_select:保存为key;view:保存为url;media_id、view_limited
|
||||
* :保存为media_id
|
||||
* </p>
|
||||
* </p>
|
||||
*/
|
||||
@ -64,13 +66,13 @@ public class Button implements Serializable {
|
||||
* 菜单显示的名称
|
||||
* @param content
|
||||
* 当buttonType为view时content设置为url,否则为key.
|
||||
* @param buttonType
|
||||
* @param type
|
||||
* 按钮类型
|
||||
*/
|
||||
public Button(String name, String content, ButtonType buttonType) {
|
||||
public Button(String name, String content, ButtonType type) {
|
||||
this.name = name;
|
||||
this.content = content;
|
||||
this.type = buttonType.name();
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
@ -81,16 +83,11 @@ public class Button implements Serializable {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
public ButtonType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false, deserialize = false)
|
||||
public ButtonType getFormatType() {
|
||||
return ButtonType.valueOf(type);
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
public void setType(ButtonType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
|
||||
@ -2,6 +2,9 @@ package com.foxinmy.weixin4j.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONCreator;
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
|
||||
/**
|
||||
* 微信账号信息
|
||||
*
|
||||
@ -12,6 +15,7 @@ import java.io.Serializable;
|
||||
* @see
|
||||
*/
|
||||
public class WeixinAccount implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -6001008896414323534L;
|
||||
|
||||
/**
|
||||
@ -22,17 +26,10 @@ public class WeixinAccount implements Serializable {
|
||||
* 调用接口的密钥
|
||||
*/
|
||||
private String secret;
|
||||
private String token;
|
||||
/**
|
||||
* 安全模式下的加密密钥
|
||||
*/
|
||||
private String encodingAesKey;
|
||||
|
||||
public WeixinAccount() {
|
||||
|
||||
}
|
||||
|
||||
public WeixinAccount(String id, String secret) {
|
||||
@JSONCreator
|
||||
public WeixinAccount(@JSONField(name = "id") String id,
|
||||
@JSONField(name = "secret") String secret) {
|
||||
this.id = id;
|
||||
this.secret = secret;
|
||||
}
|
||||
@ -45,33 +42,8 @@ public class WeixinAccount implements Serializable {
|
||||
return secret;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setSecret(String secret) {
|
||||
this.secret = secret;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public void setToken(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public String getEncodingAesKey() {
|
||||
return encodingAesKey;
|
||||
}
|
||||
|
||||
public void setEncodingAesKey(String encodingAesKey) {
|
||||
this.encodingAesKey = encodingAesKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "id=" + id + ", secret=" + secret + ", token=" + token
|
||||
+ ", encodingAesKey=" + encodingAesKey;
|
||||
return "id=" + id + ", secret=" + secret;
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,42 +53,28 @@ public class WeixinPayAccount extends WeixinAccount {
|
||||
* @param appSecret
|
||||
* 调用接口的凭证
|
||||
* @param paySignKey
|
||||
* 支付密钥字符串
|
||||
* 支付密钥字符串(必填)
|
||||
* @param mchId
|
||||
* 微信支付分配的商户号
|
||||
* 微信支付分配的商户号(V3版本必填)
|
||||
* @param partnerId 财付通的商户号(V2版本必填)
|
||||
* @param partnerKey 财付通商户权限密钥Key(V2版本必填)
|
||||
* @param subMchId 微信支付分配的子商户号,受理模式下必填(商户平台版)
|
||||
* @param deviceInfo 微信支付分配的设备号(商户平台版)
|
||||
*/
|
||||
@JSONCreator
|
||||
public WeixinPayAccount(@JSONField(name = "appId") String appId,
|
||||
@JSONField(name = "appSecret") String appSecret,
|
||||
@JSONField(name = "paySignKey") String paySignKey,
|
||||
@JSONField(name = "mchId") String mchId) {
|
||||
super(appId, appSecret);
|
||||
this.paySignKey = paySignKey;
|
||||
this.mchId = mchId;
|
||||
}
|
||||
|
||||
/**
|
||||
* V2版本字段
|
||||
*
|
||||
* @param appId
|
||||
* 公众号唯一的身份ID
|
||||
* @param appSecret
|
||||
* 调用接口的凭证
|
||||
* @param paySignKey
|
||||
* 支付密钥字符串
|
||||
* @param partnerId
|
||||
* 财付通账号的ID
|
||||
* @param partnerKey
|
||||
* 财付通账号的key
|
||||
*/
|
||||
@JSONCreator
|
||||
public WeixinPayAccount(@JSONField(name = "appId") String appId,
|
||||
@JSONField(name = "appSecret") String appSecret,
|
||||
public WeixinPayAccount(@JSONField(name = "id") String appId,
|
||||
@JSONField(name = "secret") String appSecret,
|
||||
@JSONField(name = "paySignKey") String paySignKey,
|
||||
@JSONField(name = "mchId") String mchId,
|
||||
@JSONField(name = "subMchId") String subMchId,
|
||||
@JSONField(name = "deviceInfo") String deviceInfo,
|
||||
@JSONField(name = "partnerId") String partnerId,
|
||||
@JSONField(name = "partnerKey") String partnerKey) {
|
||||
super(appId, appSecret);
|
||||
this.paySignKey = paySignKey;
|
||||
this.mchId = mchId;
|
||||
this.subMchId = subMchId;
|
||||
this.deviceInfo = deviceInfo;
|
||||
this.partnerId = partnerId;
|
||||
this.partnerKey = partnerKey;
|
||||
}
|
||||
@ -126,9 +112,10 @@ public class WeixinPayAccount extends WeixinAccount {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WeixinPayAccount [paySignKey=" + paySignKey + ", partnerId="
|
||||
+ partnerId + ", partnerKey=" + partnerKey + ", mchId=" + mchId
|
||||
+ ", subMchId=" + subMchId + ", deviceInfo=" + deviceInfo
|
||||
+ ", version=" + version + "]";
|
||||
return "WeixinPayAccount [" + super.toString() + ", paySignKey="
|
||||
+ paySignKey + ", partnerId=" + partnerId + ", partnerKey="
|
||||
+ partnerKey + ", mchId=" + mchId + ", subMchId=" + subMchId
|
||||
+ ", deviceInfo=" + deviceInfo + ", version=" + getVersion()
|
||||
+ "]";
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,7 +67,7 @@ public class Video implements NotifyTuple {
|
||||
}
|
||||
|
||||
/**
|
||||
* 企业号
|
||||
* 企业号 & 公众号群发
|
||||
*
|
||||
* @param mediaId
|
||||
* @param title
|
||||
|
||||
@ -120,4 +120,10 @@
|
||||
|
||||
* 2015-07-04
|
||||
|
||||
+ released 1.5.1
|
||||
+ released 1.5.1
|
||||
|
||||
* 2015-07-29
|
||||
|
||||
+ 新增二维码结果类[QRResult.java](./src/main/java/com/foxinmy/weixin4j/mp/model/QRResult.java)并将二维码接口[QRApi.java](./weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/QrApi.java)名称变更为createQR和createQRFile
|
||||
|
||||
+ [Oauth授权](./src/main/java/com/foxinmy/weixin4j/mp/api/OauthApi.java)跳转的uri在配置文件的属性名改为`oauth_redirect_uri`
|
||||
@ -62,17 +62,14 @@ weixin4j.properties说明
|
||||
| media_path | 调用媒体接口时保存媒体文件的物理路径 |
|
||||
| bill_path | 调用下载对账单接口保存excel文件的物理路径 |
|
||||
| ca_file | 调用某些接口(支付相关)强制需要auth的ca授权文件 |
|
||||
| redirect_uri | 调用OauthApi接口时需要填写的重定向路径 |
|
||||
| oauth_redirect_uri | 调用OauthApi接口时需要填写的重定向路径 |
|
||||
|
||||
示例(properties中换行用右斜杆\\)
|
||||
|
||||
account={"id":"appId","secret":"appSecret",\
|
||||
"token":"开放者的token",\
|
||||
"encodingAesKey":"公众号设置了加密方式且为「安全模式」时需要填入",\
|
||||
"mchId":"V3.x版本下的微信商户号",\
|
||||
"partnerId":"V2版本下的财付通的商户号",\
|
||||
"partnerKey":"V2版本下的财付通商户权限密钥Key",\
|
||||
"version":"针对微信支付的版本号(2,3),如果不填则按照mchId非空与否来判断",\
|
||||
"paySignKey":"微信支付中调用API的密钥"}
|
||||
|
||||
token_path=/tmp/weixin4j/token
|
||||
@ -84,7 +81,7 @@ weixin4j.properties说明
|
||||
#classpath路径下:ca_file=classpath:xxxxx.p12
|
||||
|
||||
#公众号登陆授权的重定向路径(使用OauthApi时需要填写)
|
||||
redirect_uri=http://xxx
|
||||
oauth_redirect_uri=http://xxx
|
||||
|
||||
2.实例化微信企业号接口实现对象,调用具体的API方法
|
||||
|
||||
|
||||
@ -36,6 +36,7 @@ import com.foxinmy.weixin4j.mp.model.KfAccount;
|
||||
import com.foxinmy.weixin4j.mp.model.KfSession;
|
||||
import com.foxinmy.weixin4j.mp.model.MenuSetting;
|
||||
import com.foxinmy.weixin4j.mp.model.QRParameter;
|
||||
import com.foxinmy.weixin4j.mp.model.QRResult;
|
||||
import com.foxinmy.weixin4j.mp.model.SemQuery;
|
||||
import com.foxinmy.weixin4j.mp.model.SemResult;
|
||||
import com.foxinmy.weixin4j.mp.model.User;
|
||||
@ -641,22 +642,6 @@ public class WeixinProxy {
|
||||
return massApi.uploadVideo(video);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分组群发
|
||||
*
|
||||
* @param tuple
|
||||
* 消息元件
|
||||
* @param groupId
|
||||
* 分组ID
|
||||
* @return 群发后的消息ID
|
||||
* @see {@link #massMessage(MassTuple,boolean,int)}
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public String massByGroupId(MassTuple tuple, int groupId)
|
||||
throws WeixinException {
|
||||
return massApi.massByGroupId(tuple, groupId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 群发消息
|
||||
* <p>
|
||||
@ -685,9 +670,9 @@ public class WeixinProxy {
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/15/5380a4e6f02f2ffdc7981a8ed7a40753.html#.E6.A0.B9.E6.8D.AE.E5.88.86.E7.BB.84.E8.BF.9B.E8.A1.8C.E7.BE.A4.E5.8F.91.E3.80.90.E8.AE.A2.E9.98.85.E5.8F.B7.E4.B8.8E.E6.9C.8D.E5.8A.A1.E5.8F.B7.E8.AE.A4.E8.AF.81.E5.90.8E.E5.9D.87.E5.8F.AF.E7.94.A8.E3.80.91">根据分组群发</a>
|
||||
*/
|
||||
public String massMessage(MassTuple tuple, boolean isToAll, int groupId)
|
||||
public String massByGroupId(MassTuple tuple, boolean isToAll, int groupId)
|
||||
throws WeixinException {
|
||||
return massApi.massMessage(tuple, isToAll, groupId);
|
||||
return massApi.massByGroupId(tuple, isToAll, groupId);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1072,26 +1057,16 @@ public class WeixinProxy {
|
||||
*
|
||||
* @param parameter
|
||||
* 二维码参数
|
||||
* @return byte数据包
|
||||
* @return 二维码结果对象
|
||||
* @throws WeixinException
|
||||
* @see com.foxinmy.weixin4j.mp.model.QRResult
|
||||
* @see com.foxinmy.weixin4j.mp.model.QRParameter
|
||||
* @see com.foxinmy.weixin4j.mp.api.QrApi
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/18/28fc21e7ed87bec960651f0ce873ef8a.html">生成二维码</a>
|
||||
*/
|
||||
public byte[] getQRData(QRParameter parameter) throws WeixinException {
|
||||
return qrApi.getQRData(parameter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成带参数的二维码
|
||||
*
|
||||
* @return 二维码图片解析后的地址 开发者可根据该地址自行生成需要的二维码图片
|
||||
* @throws WeixinException
|
||||
* @see {@link #getQRData(QRParameter)}
|
||||
*/
|
||||
public String getQRUrl(QRParameter parameter) throws WeixinException {
|
||||
return qrApi.getQRUrl(parameter);
|
||||
public QRResult createQR(QRParameter parameter) throws WeixinException {
|
||||
return qrApi.createQR(parameter);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1099,10 +1074,10 @@ public class WeixinProxy {
|
||||
*
|
||||
* @return 硬盘存储的文件对象
|
||||
* @throws WeixinException
|
||||
* @see {@link #getQRData(QRParameter)}
|
||||
* @see {@link #createQR(QRParameter)}
|
||||
*/
|
||||
public File getQRFile(QRParameter parameter) throws WeixinException {
|
||||
return qrApi.getQRFile(parameter);
|
||||
public File createQRFile(QRParameter parameter) throws WeixinException {
|
||||
return qrApi.createQRFile(parameter);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -85,22 +85,6 @@ public class MassApi extends MpApi {
|
||||
|
||||
/**
|
||||
* 分组群发
|
||||
*
|
||||
* @param tuple
|
||||
* 消息元件
|
||||
* @param groupId
|
||||
* 分组ID
|
||||
* @return 群发后的消息ID
|
||||
* @see {@link com.foxinmy.weixin4j.mp.api.MassApi#massMessage(MassTuple,boolean,int)}
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public String massByGroupId(MassTuple tuple, int groupId)
|
||||
throws WeixinException {
|
||||
return massMessage(tuple, false, groupId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 群发消息
|
||||
* <p>
|
||||
* 在返回成功时,意味着群发任务提交成功,并不意味着此时群发已经结束,所以,仍有可能在后续的发送过程中出现异常情况导致用户未收到消息,
|
||||
* 如消息有时会进行审核、服务器不稳定等,此外,群发任务一般需要较长的时间才能全部发送完毕
|
||||
@ -126,7 +110,7 @@ public class MassApi extends MpApi {
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/15/5380a4e6f02f2ffdc7981a8ed7a40753.html#.E6.A0.B9.E6.8D.AE.E5.88.86.E7.BB.84.E8.BF.9B.E8.A1.8C.E7.BE.A4.E5.8F.91.E3.80.90.E8.AE.A2.E9.98.85.E5.8F.B7.E4.B8.8E.E6.9C.8D.E5.8A.A1.E5.8F.B7.E8.AE.A4.E8.AF.81.E5.90.8E.E5.9D.87.E5.8F.AF.E7.94.A8.E3.80.91">根据分组群发</a>
|
||||
*/
|
||||
public String massMessage(MassTuple tuple, boolean isToAll, int groupId)
|
||||
public String massByGroupId(MassTuple tuple, boolean isToAll, int groupId)
|
||||
throws WeixinException {
|
||||
if (tuple instanceof MpNews) {
|
||||
MpNews _news = (MpNews) tuple;
|
||||
@ -175,7 +159,7 @@ public class MassApi extends MpApi {
|
||||
public String massArticleByGroupId(List<MpArticle> articles, int groupId)
|
||||
throws WeixinException {
|
||||
String mediaId = uploadArticle(articles);
|
||||
return massByGroupId(new MpNews(mediaId), groupId);
|
||||
return massByGroupId(new MpNews(mediaId), false, groupId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -57,15 +57,16 @@ public class MenuApi extends MpApi {
|
||||
public String process(Object object, String name,
|
||||
Object value) {
|
||||
if (object instanceof Button && name.equals("content")) {
|
||||
ButtonType buttonType = ((Button) object)
|
||||
.getFormatType();
|
||||
if (buttonType == ButtonType.view) {
|
||||
return "url";
|
||||
} else if (buttonType == ButtonType.media_id
|
||||
|| buttonType == ButtonType.view_limited) {
|
||||
return "media_id";
|
||||
} else {
|
||||
return "key";
|
||||
ButtonType buttonType = ((Button) object).getType();
|
||||
if (buttonType != null) {
|
||||
if (ButtonType.view == buttonType) {
|
||||
return "url";
|
||||
} else if (ButtonType.media_id == buttonType
|
||||
|| ButtonType.view_limited == buttonType) {
|
||||
return "media_id";
|
||||
} else {
|
||||
return "key";
|
||||
}
|
||||
}
|
||||
}
|
||||
return name;
|
||||
@ -117,8 +118,8 @@ public class MenuApi extends MpApi {
|
||||
public JsonResult deleteMenu() throws WeixinException {
|
||||
String menu_delete_uri = getRequestUri("menu_delete_uri");
|
||||
Token token = tokenHolder.getToken();
|
||||
WeixinResponse response = weixinClient.get(String.format(menu_delete_uri,
|
||||
token.getAccessToken()));
|
||||
WeixinResponse response = weixinClient.get(String.format(
|
||||
menu_delete_uri, token.getAccessToken()));
|
||||
|
||||
return response.getAsJsonResult();
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ public class OauthApi extends MpApi {
|
||||
*/
|
||||
public String getAuthorizeURL() {
|
||||
String appId = DEFAULT_WEIXIN_ACCOUNT.getId();
|
||||
String redirectUri = ConfigUtil.getValue("redirect_uri");
|
||||
String redirectUri = ConfigUtil.getValue("oauth_redirect_uri");
|
||||
return getAuthorizeURL(appId, redirectUri, "state", "snsapi_login");
|
||||
}
|
||||
|
||||
|
||||
@ -5,11 +5,12 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
|
||||
import com.foxinmy.weixin4j.model.Token;
|
||||
import com.foxinmy.weixin4j.mp.model.QRParameter;
|
||||
import com.foxinmy.weixin4j.mp.model.QRResult;
|
||||
import com.foxinmy.weixin4j.token.TokenHolder;
|
||||
import com.foxinmy.weixin4j.util.ConfigUtil;
|
||||
import com.foxinmy.weixin4j.util.Weixin4jConst;
|
||||
@ -37,42 +38,25 @@ public class QrApi extends MpApi {
|
||||
*
|
||||
* @param parameter
|
||||
* 二维码参数
|
||||
* @return 二维码图片解析后的地址 开发者可根据该地址自行生成需要的二维码图片
|
||||
* @return 二维码结果对象
|
||||
* @throws WeixinException
|
||||
* @see com.foxinmy.weixin4j.mp.model.QRResult
|
||||
* @see com.foxinmy.weixin4j.mp.model.QRParameter
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/18/28fc21e7ed87bec960651f0ce873ef8a.html">生成二维码</a>
|
||||
*/
|
||||
public String getQRUrl(QRParameter parameter) throws WeixinException {
|
||||
return doQR(parameter).getString("url");
|
||||
}
|
||||
|
||||
private JSONObject doQR(QRParameter parameter) throws WeixinException {
|
||||
public QRResult createQR(QRParameter parameter) throws WeixinException {
|
||||
Token token = tokenHolder.getToken();
|
||||
String qr_uri = getRequestUri("qr_ticket_uri");
|
||||
WeixinResponse response = weixinClient.post(
|
||||
String.format(qr_uri, token.getAccessToken()),
|
||||
parameter.getContent());
|
||||
return response.getAsJson();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成带参数的二维码
|
||||
*
|
||||
* @param parameter
|
||||
* 二维码参数
|
||||
* @return byte数据包
|
||||
* @throws WeixinException
|
||||
* @see com.foxinmy.weixin4j.mp.model.QRParameter
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/18/28fc21e7ed87bec960651f0ce873ef8a.html">生成二维码</a>
|
||||
*/
|
||||
public byte[] getQRData(QRParameter parameter) throws WeixinException {
|
||||
String ticket = doQR(parameter).getString("ticket");
|
||||
String qr_uri = getRequestUri("qr_image_uri");
|
||||
WeixinResponse response = weixinClient.get(String
|
||||
.format(qr_uri, ticket));
|
||||
|
||||
return response.getContent();
|
||||
QRResult result = response.getAsObject(new TypeReference<QRResult>() {
|
||||
});
|
||||
qr_uri = getRequestUri("qr_image_uri");
|
||||
response = weixinClient.get(String.format(qr_uri, result.getTicket()));
|
||||
result.setContent(response.getContent());
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -87,9 +71,10 @@ public class QrApi extends MpApi {
|
||||
* @throws WeixinException
|
||||
* @see <a
|
||||
* href="mp.weixin.qq.com/wiki/18/28fc21e7ed87bec960651f0ce873ef8a.html">二维码</a>
|
||||
* @see #createQR(QRParameter)
|
||||
* @see com.foxinmy.weixin4j.mp.model.QRParameter
|
||||
*/
|
||||
public File getQRFile(QRParameter parameter) throws WeixinException {
|
||||
public File createQRFile(QRParameter parameter) throws WeixinException {
|
||||
String qr_path = ConfigUtil.getValue("qr_path",
|
||||
Weixin4jConst.DEFAULT_QRCODE_PATH);
|
||||
String filename = String.format("%s_%s_%d.jpg", parameter.getQrType()
|
||||
@ -99,11 +84,11 @@ public class QrApi extends MpApi {
|
||||
if (parameter.getQrType().ordinal() > 0 && file.exists()) {
|
||||
return file;
|
||||
}
|
||||
byte[] datas = getQRData(parameter);
|
||||
QRResult qrResult = createQR(parameter);
|
||||
OutputStream os = null;
|
||||
try {
|
||||
os = new FileOutputStream(file);
|
||||
os.write(datas);
|
||||
os.write(qrResult.getContent());
|
||||
} catch (IOException e) {
|
||||
throw new WeixinException(e.getMessage());
|
||||
} finally {
|
||||
@ -111,7 +96,7 @@ public class QrApi extends MpApi {
|
||||
if (os != null) {
|
||||
os.close();
|
||||
}
|
||||
} catch (IOException ignore) {
|
||||
} catch (IOException e) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,65 @@
|
||||
package com.foxinmy.weixin4j.mp.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
|
||||
/**
|
||||
* 二维码
|
||||
*
|
||||
* @className QRResult
|
||||
* @author jy
|
||||
* @date 2015年7月29日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class QRResult implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 7730781702153258151L;
|
||||
|
||||
private String ticket;
|
||||
private String url;
|
||||
@JSONField(name = "expire_seconds")
|
||||
private int expireSeconds;
|
||||
private byte[] content;
|
||||
|
||||
public String getTicket() {
|
||||
return ticket;
|
||||
}
|
||||
|
||||
public void setTicket(String ticket) {
|
||||
this.ticket = ticket;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public int getExpireSeconds() {
|
||||
return expireSeconds;
|
||||
}
|
||||
|
||||
public void setExpireSeconds(int expireSeconds) {
|
||||
this.expireSeconds = expireSeconds;
|
||||
}
|
||||
|
||||
public byte[] getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(byte[] content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "QRResult [ticket=" + ticket + ", url=" + url
|
||||
+ ", expireSeconds=" + expireSeconds + ", content="
|
||||
+ Arrays.toString(content) + "]";
|
||||
}
|
||||
}
|
||||
@ -1,10 +1,7 @@
|
||||
# \u6d4b\u8bd5\u4e4b\u7528 \u6b63\u5f0f\u73af\u5883\u4e0bcopy\u4e00\u4efd\u5230classpath
|
||||
# \u516c\u4f17\u53f7\u4fe1\u606f
|
||||
account={"id":"wx4ab8f8de58159a57","secret":"1d4eb0f4bf556aaed539f30ed05ca795",\
|
||||
"token":"\u5f00\u653e\u8005\u7684token",\
|
||||
"encodingAesKey":"\u516c\u4f17\u53f7\u8bbe\u7f6e\u4e86\u52a0\u5bc6\u65b9\u5f0f\u4e14\u4e3a\u300c\u5b89\u5168\u6a21\u5f0f\u300d\u65f6\u9700\u8981\u586b\u5165",\
|
||||
"mchId":"V3.x\u7248\u672c\u4e0b\u7684\u5fae\u4fe1\u5546\u6237\u53f7 \u670d\u52a1\u53f7\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165",\
|
||||
"version":2,\
|
||||
"partnerId":"V2\u7248\u672c\u4e0b\u7684\u8d22\u4ed8\u901a\u7684\u5546\u6237\u53f7 \u670d\u52a1\u53f7\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165",\
|
||||
"partnerKey":"V2\u7248\u672c\u4e0b\u7684\u8d22\u4ed8\u901a\u5546\u6237\u6743\u9650\u5bc6\u94a5Key \u670d\u52a1\u53f7\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165",\
|
||||
"paySignKey":"\u5fae\u4fe1\u652f\u4ed8\u4e2d\u8c03\u7528API\u7684\u5bc6\u94a5 \u670d\u52a1\u53f7\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165"}
|
||||
@ -23,4 +20,4 @@ ca_file=/tmp/weixin4j/xxxxx.p12
|
||||
# ca_file=classpath:xxxxx.pfx
|
||||
|
||||
# oauth\u6388\u6743\u540e\u91cd\u5b9a\u5411\u7684url
|
||||
redirect_uri=
|
||||
oauth_redirect_uri=
|
||||
@ -30,7 +30,8 @@ public class CouponTest {
|
||||
protected final static WeixinPayProxy WEIXINPAY;
|
||||
protected final static WeixinPayAccount ACCOUNT;
|
||||
static {
|
||||
ACCOUNT = new WeixinPayAccount("appid", "appsecret", "paysign", "mchid");
|
||||
ACCOUNT = new WeixinPayAccount("appid", "appsecret", "paysign",
|
||||
"mchid", null, null, null, null);
|
||||
WEIXINPAY = new WeixinPayProxy(ACCOUNT);
|
||||
}
|
||||
protected final File caFile = new File("证书文件路径(*.p12)");
|
||||
|
||||
@ -58,7 +58,7 @@ public class MassTest extends TokenTest {
|
||||
|
||||
@Test
|
||||
public void massByGroupId() throws WeixinException {
|
||||
String msgId = massApi.massByGroupId(new Image("mediaId"), 0);
|
||||
String msgId = massApi.massByGroupId(new Image("mediaId"), true, 0);
|
||||
Assert.assertTrue(msgId != null);
|
||||
}
|
||||
|
||||
|
||||
@ -33,11 +33,12 @@ public class PayTest {
|
||||
private final static WeixinPayAccount ACCOUNT3;
|
||||
static {
|
||||
ACCOUNT2 = new WeixinPayAccount("请填入v2版本的appid", "请填入v2版本的appSecret",
|
||||
"请填入v3版本的paysignkey", "请填入v2版本的partnerId", "请填入v2版本的partnerKey");
|
||||
"请填入v2版本的paysignkey", null, null, null, "请填入v2版本的partnerId",
|
||||
"请填入v2版本的partnerKey");
|
||||
PAY2 = new Pay2Api(ACCOUNT2, new FileTokenStorager(ConfigUtil.getValue(
|
||||
"token_path", "/tmp/weixin4j/token")));
|
||||
ACCOUNT3 = new WeixinPayAccount("请填入v3版本的appid", "请填入v3版本的appSecret",
|
||||
"请填入v3版本的paysignkey", "请填入v3版本的mchid");
|
||||
"请填入v3版本的paysignkey", "请填入v3版本的mchid", null, null, null, null);
|
||||
PAY3 = new WeixinPayProxy(ACCOUNT3);
|
||||
}
|
||||
|
||||
|
||||
@ -29,19 +29,19 @@ public class QRTest extends TokenTest {
|
||||
|
||||
@Test
|
||||
public void temp_qr() throws WeixinException, IOException {
|
||||
File file = qrApi.getQRFile(QRParameter.createTemporary(1200, 1200));
|
||||
File file = qrApi.createQRFile(QRParameter.createTemporary(1200, 1200));
|
||||
Assert.assertTrue(file.exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void forever_qr_int() throws WeixinException, IOException {
|
||||
File file = qrApi.getQRFile(QRParameter.createPermanenceInt(1200));
|
||||
File file = qrApi.createQRFile(QRParameter.createPermanenceInt(1200));
|
||||
Assert.assertTrue(file.exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void forever_qr_str() throws WeixinException, IOException {
|
||||
File file = qrApi.getQRFile(QRParameter.createPermanenceStr("1200中文"));
|
||||
File file = qrApi.createQRFile(QRParameter.createPermanenceStr("1200中文"));
|
||||
Assert.assertTrue(file.exists());
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,9 +2,15 @@ package com.foxinmy.weixin4j.mp.test;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.select.Elements;
|
||||
|
||||
import com.foxinmy.weixin4j.model.Token;
|
||||
import com.foxinmy.weixin4j.mp.payment.v2.RefundRecordV2;
|
||||
import com.foxinmy.weixin4j.payment.mch.Order;
|
||||
@ -99,6 +105,26 @@ public class XmlstreamTest {
|
||||
com.foxinmy.weixin4j.payment.mch.RefundRecord.class));
|
||||
}
|
||||
|
||||
public static String errorXml() {
|
||||
StringBuffer xml = new StringBuffer();
|
||||
String url = "http://qydev.weixin.qq.com/wiki/index.php?title=%E5%85%A8%E5%B1%80%E8%BF%94%E5%9B%9E%E7%A0%81%E8%AF%B4%E6%98%8E";
|
||||
try {
|
||||
Document doc = Jsoup.parse(new URL(url), 5000);
|
||||
Elements eles = doc.getElementsByTag("tr");
|
||||
for (Element ele : eles) {
|
||||
xml.append("<error>");
|
||||
xml.append("<code>").append(ele.child(0).text())
|
||||
.append("</code>");
|
||||
xml.append("<text>").append(ele.child(1).text())
|
||||
.append("</text>");
|
||||
xml.append("</error>");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return xml.toString();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// map2xml();
|
||||
// xml2map();
|
||||
@ -106,13 +132,15 @@ public class XmlstreamTest {
|
||||
// System.err.println(xml2refundRecordV2());
|
||||
// xml2refundRecordV3();
|
||||
// object2xmlWithoutRootElement();
|
||||
/*RefundRecord refundRecord = xml2refundRecordV2();
|
||||
System.err.println(refundRecord);
|
||||
String sign = refundRecord.getSign();
|
||||
refundRecord.setSign(null);
|
||||
String validSign = PayUtil.paysignMd5(refundRecord, "paysignkey");
|
||||
System.err.println("sign=" + sign + ",validSign=" + validSign);
|
||||
System.err.println(ListsuffixResultSerializer
|
||||
.serializeToXML(refundRecord));*/
|
||||
/*
|
||||
* RefundRecord refundRecord = xml2refundRecordV2();
|
||||
* System.err.println(refundRecord); String sign =
|
||||
* refundRecord.getSign(); refundRecord.setSign(null); String validSign
|
||||
* = PayUtil.paysignMd5(refundRecord, "paysignkey");
|
||||
* System.err.println("sign=" + sign + ",validSign=" + validSign);
|
||||
* System.err.println(ListsuffixResultSerializer
|
||||
* .serializeToXML(refundRecord));
|
||||
*/
|
||||
// System.out.println(errorXml());
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,8 +59,8 @@ weixin4j.properties说明
|
||||
|
||||
account={"id":"corpid","secret":"corpsecret",\
|
||||
"token":"企业号中应用在回调模式下的token",\
|
||||
"encodingAesKey":"企业号中应用在回调模式下AES加密密钥",\
|
||||
"providerSecret:"提供商的secret"}
|
||||
"providerSecret:"第三方提供商secret(企业号登陆)",\
|
||||
"chatSecret":"消息服务secret(企业号聊天)"}
|
||||
|
||||
token_path=/tmp/weixin4j/token
|
||||
media_path=/tmp/weixin4j/media
|
||||
|
||||
@ -60,15 +60,16 @@ public class MenuApi extends QyApi {
|
||||
public String process(Object object, String name,
|
||||
Object value) {
|
||||
if (object instanceof Button && name.equals("content")) {
|
||||
ButtonType buttonType = ((Button) object)
|
||||
.getFormatType();
|
||||
if (buttonType == ButtonType.view) {
|
||||
return "url";
|
||||
} else if (buttonType == ButtonType.media_id
|
||||
|| buttonType == ButtonType.view_limited) {
|
||||
return "media_id";
|
||||
} else {
|
||||
return "key";
|
||||
ButtonType buttonType = ((Button) object).getType();
|
||||
if (buttonType != null) {
|
||||
if (ButtonType.view == buttonType) {
|
||||
return "url";
|
||||
} else if (ButtonType.media_id == buttonType
|
||||
|| ButtonType.view_limited == buttonType) {
|
||||
return "media_id";
|
||||
} else {
|
||||
return "key";
|
||||
}
|
||||
}
|
||||
}
|
||||
return name;
|
||||
@ -124,8 +125,8 @@ public class MenuApi extends QyApi {
|
||||
public JsonResult deleteMenu(int agentid) throws WeixinException {
|
||||
String menu_delete_uri = getRequestUri("menu_delete_uri");
|
||||
Token token = tokenHolder.getToken();
|
||||
WeixinResponse response = weixinClient.get(String.format(menu_delete_uri,
|
||||
token.getAccessToken(), agentid));
|
||||
WeixinResponse response = weixinClient.get(String.format(
|
||||
menu_delete_uri, token.getAccessToken(), agentid));
|
||||
|
||||
return response.getAsJsonResult();
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
package com.foxinmy.weixin4j.qy.model;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONCreator;
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
|
||||
/**
|
||||
@ -14,22 +16,36 @@ import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
* >企业号设置</a>
|
||||
*/
|
||||
public class WeixinQyAccount extends WeixinAccount {
|
||||
|
||||
|
||||
private static final long serialVersionUID = 3689999353867189585L;
|
||||
|
||||
public WeixinQyAccount(){
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param corpid
|
||||
* 企业ID
|
||||
* @param corpsecret
|
||||
* 管理组的凭证密钥
|
||||
* @param suiteId
|
||||
* 应用套件的id
|
||||
* @param suiteSecret
|
||||
* 应用套件的secret
|
||||
* @param providerSecret
|
||||
* 第三方提供商secret(企业号登陆)
|
||||
* @param chatSecret
|
||||
* 消息服务secret(企业号聊天)
|
||||
*/
|
||||
public WeixinQyAccount(String corpid, String corpsecret) {
|
||||
@JSONCreator
|
||||
public WeixinQyAccount(@JSONField(name = "id") String corpid,
|
||||
@JSONField(name = "secret") String corpsecret,
|
||||
@JSONField(name = "suiteId") String suiteId,
|
||||
@JSONField(name = "suiteSecret") String suiteSecret,
|
||||
@JSONField(name = "providerSecret") String providerSecret,
|
||||
@JSONField(name = "chatSecret") String chatSecret) {
|
||||
super(corpid, corpsecret);
|
||||
this.suiteId = suiteId;
|
||||
this.suiteSecret = suiteSecret;
|
||||
this.providerSecret = providerSecret;
|
||||
this.chatSecret = chatSecret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -41,65 +57,34 @@ public class WeixinQyAccount extends WeixinAccount {
|
||||
*/
|
||||
private String suiteSecret;
|
||||
/**
|
||||
* 应用套件token,用于生成签名,校验回调请求的合法性。后续所有托管的企业产生的回调消息都使用该值来解密。
|
||||
*/
|
||||
private String suiteToken;
|
||||
/**
|
||||
* 应用套件encodingAesKey,回调消息加解密参数,是AES密钥的Base64编码,用于解密回调消息内容对应的密文。
|
||||
* 后续所有托管的企业产生的回调消息都使用该值来解密。
|
||||
*/
|
||||
private String suiteEncodingAesKey;
|
||||
|
||||
/**
|
||||
* 提供商的secret
|
||||
* 第三方提供商secret(企业号登陆)
|
||||
*/
|
||||
private String providerSecret;
|
||||
/**
|
||||
* 消息服务secret(企业号聊天)
|
||||
*/
|
||||
private String chatSecret;
|
||||
|
||||
public String getSuiteId() {
|
||||
return suiteId;
|
||||
}
|
||||
|
||||
public void setSuiteId(String suiteId) {
|
||||
this.suiteId = suiteId;
|
||||
}
|
||||
|
||||
public String getSuiteSecret() {
|
||||
return suiteSecret;
|
||||
}
|
||||
|
||||
public void setSuiteSecret(String suiteSecret) {
|
||||
this.suiteSecret = suiteSecret;
|
||||
}
|
||||
|
||||
public String getSuiteToken() {
|
||||
return suiteToken;
|
||||
}
|
||||
|
||||
public void setSuiteToken(String suiteToken) {
|
||||
this.suiteToken = suiteToken;
|
||||
}
|
||||
|
||||
public String getSuiteEncodingAesKey() {
|
||||
return suiteEncodingAesKey;
|
||||
}
|
||||
|
||||
public void setSuiteEncodingAesKey(String suiteEncodingAesKey) {
|
||||
this.suiteEncodingAesKey = suiteEncodingAesKey;
|
||||
}
|
||||
|
||||
public String getProviderSecret() {
|
||||
return providerSecret;
|
||||
}
|
||||
|
||||
public void setProviderSecret(String providerSecret) {
|
||||
this.providerSecret = providerSecret;
|
||||
public String getChatSecret() {
|
||||
return chatSecret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WeixinQyAccount [" + super.toString() + ", suiteId=" + suiteId
|
||||
+ ", suiteSecret=" + suiteSecret + ", suiteToken=" + suiteToken
|
||||
+ ", suiteEncodingAesKey=" + suiteEncodingAesKey
|
||||
+ ", providerSecret=" + providerSecret + "]";
|
||||
+ ", suiteSecret=" + suiteSecret + ", providerSecret="
|
||||
+ providerSecret + ", chatSecret=" + chatSecret + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,9 @@
|
||||
# \u6d4b\u8bd5\u4e4b\u7528 \u6b63\u5f0f\u73af\u5883\u4e0bcopy\u4e00\u4efd\u5230classpath
|
||||
# \u4f01\u4e1a\u53f7\u4fe1\u606f
|
||||
account={"id":"wx6d13cc18002bb2e5","secret":"vcCOTIb-cOzWWhL5r_qKVlfzdpInEEKPRz3K-5ezn-Xt48-tOkxPqEE5XbKLXXFn",\
|
||||
"token":"gp2eGT5mIpngr",\
|
||||
"encodingAesKey":"BRYfV4zPFUJb3v3MySNBg1ERKE3vyyMRoScu76vFySv",\
|
||||
"suiteId":"\u5e94\u7528\u5957\u4ef6\u7684id","suiteSecret":"\u5e94\u7528\u5957\u4ef6\u7684secret",\
|
||||
"suiteToken":"\u5e94\u7528\u5957\u4ef6\u7684token",\
|
||||
"suiteEncodingAesKey":"\u5e94\u7528\u5957\u4ef6\u7684encodingAesKey",\
|
||||
"providerSecret":"\u63d0\u4f9b\u5546\u7684secret"}
|
||||
"providerSecret":"\u7b2c\u4e09\u65b9\u63d0\u4f9b\u5546secret(\u4f01\u4e1a\u53f7\u767b\u9646)",\
|
||||
"chatSecret":"\u6d88\u606f\u670d\u52a1secret(\u4f01\u4e1a\u53f7\u804a\u5929)"}
|
||||
|
||||
# \u4f7f\u7528FileTokenStorager\u65f6token\u7684\u5b58\u653e\u8def\u5f84
|
||||
token_path=/tmp/weixin4j/token
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user