소스 검색

issue #74;

git commit -m issue
master
Daniel Qian 10 년 전
부모
커밋
cef8ac01e8
5개의 변경된 파일133개의 추가작업 그리고 14개의 파일을 삭제
  1. +28
    -6
      weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/SHA1.java
  2. +22
    -2
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java
  3. +22
    -2
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java
  4. +28
    -3
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java
  5. +33
    -1
      weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java

+ 28
- 6
weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/SHA1.java 파일 보기

@@ -10,27 +10,49 @@ import java.util.Arrays;
public class SHA1 {

/**
* 生成SHA1签名
* 串接arr参数,生成sha1 digest
*
* @param arr
* @return
*/
public static String gen(String... arr) throws NoSuchAlgorithmException {
Arrays.sort(arr);
StringBuilder sb = new StringBuilder();
for(String a : arr) {
for (String a : arr) {
sb.append(a);
}
return genStr(sb.toString());
}

/**
* 用&串接arr参数,生成sha1 digest
*
* @param arr
* @return
*/
public static String genWithAmple(String... arr) throws NoSuchAlgorithmException {
Arrays.sort(arr);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < arr.length; i++) {
String a = arr[i];
sb.append(a);
if (i != arr.length - 1) {
sb.append('&');
}
}
return genStr(sb.toString());
}

public static String genStr(String str) throws NoSuchAlgorithmException {
MessageDigest sha1 = MessageDigest.getInstance("SHA1");
sha1.update(sb.toString().getBytes());
sha1.update(str.getBytes());
byte[] output = sha1.digest();
return bytesToHex(output);
}


protected static String bytesToHex(byte[] b) {
char hexDigit[] = {'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
char hexDigit[] = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
StringBuffer buf = new StringBuffer();
for (int j = 0; j < b.length; j++) {
buf.append(hexDigit[(b[j] >> 4) & 0x0f]);


+ 22
- 2
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpConfigStorage.java 파일 보기

@@ -9,10 +9,19 @@ import me.chanjar.weixin.common.bean.WxAccessToken;
*/
public interface WxMpConfigStorage {

/**
* 应该是线程安全的
* @param accessToken
*/
public void updateAccessToken(WxAccessToken accessToken);

/**
* 应该是线程安全的
* @param accessToken
* @param expiresIn
*/
public void updateAccessToken(String accessToken, int expiresIn);
public String getAccessToken();
public String getAppId();
@@ -35,4 +44,15 @@ public interface WxMpConfigStorage {

public String getHttp_proxy_password();


public String getJsapiTicket();

public boolean isJsapiTokenExpired();

/**
* 应该是线程安全的
* @param jsapiTicket
*/
public void updateJsapiTicket(String jsapiTicket, int expiresInSeconds);

}

+ 22
- 2
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpInMemoryConfigStorage.java 파일 보기

@@ -9,6 +9,8 @@ import me.chanjar.weixin.common.bean.WxAccessToken;
*/
public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {

private static final long l = 7000 * 1000l;

protected String appId;
protected String secret;
protected String token;
@@ -23,11 +25,14 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
protected String http_proxy_username;
protected String http_proxy_password;

public void updateAccessToken(WxAccessToken accessToken) {
protected String jsapiTicket;
protected long jsapiTicketExpiresTime;

public synchronized void updateAccessToken(WxAccessToken accessToken) {
updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn());
}
public void updateAccessToken(String accessToken, int expiresIn) {
public synchronized void updateAccessToken(String accessToken, int expiresIn) {
this.accessToken = accessToken;
this.expiresIn = expiresIn;
}
@@ -121,6 +126,21 @@ public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
this.http_proxy_password = http_proxy_password;
}


public String getJsapiTicket() {
return jsapiTicket;
}

public boolean isJsapiTokenExpired() {
return System.currentTimeMillis() > this.jsapiTicketExpiresTime;
}

public synchronized void updateJsapiTicket(String jsapiTicket, int expiresInSeconds) {
this.jsapiTicket = jsapiTicket;
// 预留200秒的时间
this.jsapiTicketExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000l;
}

@Override
public String toString() {
return "WxMpInMemoryConfigStorage{" +


+ 28
- 3
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpService.java 파일 보기

@@ -43,17 +43,42 @@ public interface WxMpService {
* @throws me.chanjar.weixin.common.exception.WxErrorException
*/
public void accessTokenRefresh() throws WxErrorException;

/**
* <pre>
* 获得jsapi_ticket
* 获得时会检查jsapiToken是否过期,如果过期了,那么就刷新一下,否则就什么都不干
*
* 详情请见:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E9.99.84.E5.BD.951-JS-SDK.E4.BD.BF.E7.94.A8.E6.9D.83.E9.99.90.E7.AD.BE.E5.90.8D.E7.AE.97.E6.B3.95
* </pre>
* @return
* @throws WxErrorException
*/
public String getJsapiTicket() throws WxErrorException;

/**
* <pre>
* 创建调用jsapi时所需要的签名
*
* 详情请见:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E9.99.84.E5.BD.951-JS-SDK.E4.BD.BF.E7.94.A8.E6.9D.83.E9.99.90.E7.AD.BE.E5.90.8D.E7.AE.97.E6.B3.95
* </pre>
* @param timestamp 时间戳
* @param noncestr 用户自己生成的随机字符串
* @param url url
* @return
*/
public String createJsapiSignature(String timestamp, String noncestr, String url) throws WxErrorException;

/**
* <pre>
* 上传多媒体文件
*
*
* 上传的多媒体文件有格式和大小限制,如下:
* 图片(image): 1M,支持JPG格式
* 语音(voice):2M,播放长度不超过60s,支持AMR\MP3格式
* 视频(video):10MB,支持MP4格式
* 缩略图(thumb):64KB,支持JPG格式
*
*
* 详情请见: http://mp.weixin.qq.com/wiki/index.php?title=上传下载多媒体文件
* </pre>
* @param mediaType 媒体类型, 请看{@link me.chanjar.weixin.common.api.WxConsts}


+ 33
- 1
weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpServiceImpl.java 파일 보기

@@ -36,6 +36,7 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -106,7 +107,38 @@ public class WxMpServiceImpl implements WxMpService {
// 刷新完毕了,就没他什么事儿了
}
}

public String getJsapiTicket() throws WxErrorException {
if (wxMpConfigStorage.isJsapiTokenExpired()) {
synchronized (wxMpConfigStorage) {
if (wxMpConfigStorage.isJsapiTokenExpired()) {
String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi";
String responseContent = execute(new SimpleGetRequestExecutor(), url, null);
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent)));
JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject();
String jsapiTicket = tmpJsonObject.get("ticket").getAsString();
int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt();
wxMpConfigStorage.updateJsapiTicket(jsapiTicket, expiresInSeconds);
}
}
}
return wxMpConfigStorage.getJsapiTicket();
}

public String createJsapiSignature(String timestamp, String noncestr, String url) throws WxErrorException {
String jsapiTicket = getJsapiTicket();
try {
return SHA1.genWithAmple(
"jsapi_ticket=" + jsapiTicket,
"timestamp=" + timestamp,
"noncestr=" + noncestr,
"url=" + url
);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}

public void customMessageSend(WxMpCustomMessage message) throws WxErrorException {
String url = "https://api.weixin.qq.com/cgi-bin/message/custom/send";
execute(new SimplePostRequestExecutor(), url, message.toJson());


불러오는 중...
취소
저장