#672 小程序增加jssdk相关接口实现

This commit is contained in:
Binary Wang 2018-08-05 19:51:41 +08:00
parent 93db3237a6
commit 214e7e58fa
9 changed files with 243 additions and 9 deletions

View File

@ -1,13 +1,21 @@
package me.chanjar.weixin.common.bean; package me.chanjar.weixin.common.bean;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable; import java.io.Serializable;
/** /**
* jspai signature. * jspai signature.
*
* @author chanjarster
*/ */
@Data @Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WxJsapiSignature implements Serializable { public class WxJsapiSignature implements Serializable {
private static final long serialVersionUID = -1116808193154384804L; private static final long serialVersionUID = -1116808193154384804L;

View File

@ -0,0 +1,48 @@
package cn.binarywang.wx.miniapp.api;
import me.chanjar.weixin.common.bean.WxJsapiSignature;
import me.chanjar.weixin.common.error.WxErrorException;
/**
* <pre>
* jsapi相关接口
* Created by BinaryWang on 2018/8/5.
* </pre>
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
public interface WxMaJsapiService {
/**
* 获得jsapi_ticket的url
*/
String GET_JSAPI_TICKET_URL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi";
/**
* 获得jsapi_ticket,不强制刷新jsapi_ticket
*
* @see #getJsapiTicket(boolean)
*/
String getJsapiTicket() throws WxErrorException;
/**
* <pre>
* 获得jsapi_ticket
* 获得时会检查jsapiToken是否过期如果过期了那么就刷新一下否则就什么都不干
*
* 详情请见http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CN
* </pre>
*
* @param forceRefresh 强制刷新
*/
String getJsapiTicket(boolean forceRefresh) throws WxErrorException;
/**
* <pre>
* 创建调用jsapi时所需要的签名
*
* 详情请见http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CN
* </pre>
*/
WxJsapiSignature createJsapiSignature(String url) throws WxErrorException;
}

View File

@ -2,6 +2,7 @@ package cn.binarywang.wx.miniapp.api;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.config.WxMaConfig; import cn.binarywang.wx.miniapp.config.WxMaConfig;
import me.chanjar.weixin.common.bean.WxJsapiSignature;
import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor; import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor;
import me.chanjar.weixin.common.util.http.RequestExecutor; import me.chanjar.weixin.common.util.http.RequestExecutor;
@ -17,6 +18,7 @@ public interface WxMaService {
String GET_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s"; String GET_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
String JSCODE_TO_SESSION_URL = "https://api.weixin.qq.com/sns/jscode2session"; String JSCODE_TO_SESSION_URL = "https://api.weixin.qq.com/sns/jscode2session";
/** /**
* 获取登录后的session信息 * 获取登录后的session信息
* *
@ -149,6 +151,13 @@ public interface WxMaService {
*/ */
WxMaCodeService getCodeService(); WxMaCodeService getCodeService();
/**
* 返回jsapi操作相关的 API服务类对象
*
* @return WxMaJsapiService
*/
WxMaJsapiService getJsapiService();
/** /**
* 小程序修改服务器地址成员管理 API * 小程序修改服务器地址成员管理 API
* *

View File

@ -0,0 +1,75 @@
package cn.binarywang.wx.miniapp.api.impl;
import cn.binarywang.wx.miniapp.api.WxMaJsapiService;
import cn.binarywang.wx.miniapp.api.WxMaService;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import me.chanjar.weixin.common.bean.WxJsapiSignature;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.RandomUtils;
import me.chanjar.weixin.common.util.crypto.SHA1;
import java.util.concurrent.locks.Lock;
/**
* <pre>
* Created by BinaryWang on 2018/8/5.
* </pre>
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
public class WxMaJsapiServiceImpl implements WxMaJsapiService {
private static final JsonParser JSON_PARSER = new JsonParser();
private WxMaService wxMaService;
public WxMaJsapiServiceImpl(WxMaService wxMaService) {
this.wxMaService = wxMaService;
}
@Override
public String getJsapiTicket() throws WxErrorException {
return getJsapiTicket(false);
}
@Override
public String getJsapiTicket(boolean forceRefresh) throws WxErrorException {
Lock lock = this.wxMaService.getWxMaConfig().getJsapiTicketLock();
try {
lock.lock();
if (forceRefresh) {
this.wxMaService.getWxMaConfig().expireJsapiTicket();
}
if (this.wxMaService.getWxMaConfig().isJsapiTicketExpired()) {
String responseContent = this.wxMaService.get(GET_JSAPI_TICKET_URL, null);
JsonElement tmpJsonElement = JSON_PARSER.parse(responseContent);
JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject();
String jsapiTicket = tmpJsonObject.get("ticket").getAsString();
int expiresInSeconds = tmpJsonObject.get("expires_in").getAsInt();
this.wxMaService.getWxMaConfig().updateJsapiTicket(jsapiTicket, expiresInSeconds);
}
} finally {
lock.unlock();
}
return this.wxMaService.getWxMaConfig().getJsapiTicket();
}
@Override
public WxJsapiSignature createJsapiSignature(String url) throws WxErrorException {
long timestamp = System.currentTimeMillis() / 1000;
String randomStr = RandomUtils.getRandomStr();
String jsapiTicket = getJsapiTicket(false);
String signature = SHA1.genWithAmple("jsapi_ticket=" + jsapiTicket,
"noncestr=" + randomStr, "timestamp=" + timestamp, "url=" + url);
return WxJsapiSignature
.builder()
.appId(this.wxMaService.getWxMaConfig().getAppid())
.timestamp(timestamp)
.nonceStr(randomStr)
.url(url)
.signature(signature)
.build();
}
}

View File

@ -1,14 +1,6 @@
package cn.binarywang.wx.miniapp.api.impl; package cn.binarywang.wx.miniapp.api.impl;
import cn.binarywang.wx.miniapp.api.WxMaAnalysisService; import cn.binarywang.wx.miniapp.api.*;
import cn.binarywang.wx.miniapp.api.WxMaCodeService;
import cn.binarywang.wx.miniapp.api.WxMaMediaService;
import cn.binarywang.wx.miniapp.api.WxMaMsgService;
import cn.binarywang.wx.miniapp.api.WxMaQrcodeService;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.WxMaSettingService;
import cn.binarywang.wx.miniapp.api.WxMaTemplateService;
import cn.binarywang.wx.miniapp.api.WxMaUserService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.config.WxMaConfig; import cn.binarywang.wx.miniapp.config.WxMaConfig;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
@ -58,6 +50,7 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl
private WxMaAnalysisService analysisService = new WxMaAnalysisServiceImpl(this); private WxMaAnalysisService analysisService = new WxMaAnalysisServiceImpl(this);
private WxMaCodeService codeService = new WxMaCodeServiceImpl(this); private WxMaCodeService codeService = new WxMaCodeServiceImpl(this);
private WxMaSettingService settingService = new WxMaSettingServiceImpl(this); private WxMaSettingService settingService = new WxMaSettingServiceImpl(this);
private WxMaJsapiService jsapiService = new WxMaJsapiServiceImpl(this);
private int retrySleepMillis = 1000; private int retrySleepMillis = 1000;
private int maxRetryTimes = 5; private int maxRetryTimes = 5;
@ -310,6 +303,11 @@ public class WxMaServiceImpl implements WxMaService, RequestHttp<CloseableHttpCl
return this.codeService; return this.codeService;
} }
@Override
public WxMaJsapiService getJsapiService() {
return this.jsapiService;
}
@Override @Override
public WxMaSettingService getSettingService() { public WxMaSettingService getSettingService() {
return this.settingService; return this.settingService;

View File

@ -38,6 +38,25 @@ public interface WxMaConfig {
*/ */
void updateAccessToken(String accessToken, int expiresInSeconds); void updateAccessToken(String accessToken, int expiresInSeconds);
String getJsapiTicket();
Lock getJsapiTicketLock();
boolean isJsapiTicketExpired();
/**
* 强制将jsapi ticket过期掉
*/
void expireJsapiTicket();
/**
* 应该是线程安全的
*
* @param jsapiTicket 新的jsapi ticket值
* @param expiresInSeconds 过期时间以秒为单位
*/
void updateJsapiTicket(String jsapiTicket, int expiresInSeconds);
String getAppid(); String getAppid();
String getSecret(); String getSecret();

View File

@ -27,7 +27,11 @@ public class WxMaInMemoryConfig implements WxMaConfig {
protected volatile String httpProxyUsername; protected volatile String httpProxyUsername;
protected volatile String httpProxyPassword; protected volatile String httpProxyPassword;
protected volatile String jsapiTicket;
protected volatile long jsapiTicketExpiresTime;
protected Lock accessTokenLock = new ReentrantLock(); protected Lock accessTokenLock = new ReentrantLock();
protected Lock jsapiTicketLock = new ReentrantLock();
/** /**
* 临时文件目录 * 临时文件目录
@ -70,6 +74,33 @@ public class WxMaInMemoryConfig implements WxMaConfig {
this.expiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L; this.expiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L;
} }
@Override
public String getJsapiTicket() {
return this.jsapiTicket;
}
@Override
public Lock getJsapiTicketLock() {
return this.jsapiTicketLock;
}
@Override
public boolean isJsapiTicketExpired() {
return System.currentTimeMillis() > this.jsapiTicketExpiresTime;
}
@Override
public void expireJsapiTicket() {
this.jsapiTicketExpiresTime = 0;
}
@Override
public void updateJsapiTicket(String jsapiTicket, int expiresInSeconds) {
this.jsapiTicket = jsapiTicket;
// 预留200秒的时间
this.jsapiTicketExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L;
}
@Override @Override
public void expireAccessToken() { public void expireAccessToken() {
this.expiresTime = 0; this.expiresTime = 0;

View File

@ -0,0 +1,45 @@
package cn.binarywang.wx.miniapp.api.impl;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.config.WxMaConfig;
import cn.binarywang.wx.miniapp.test.ApiTestModule;
import com.google.inject.Inject;
import me.chanjar.weixin.common.bean.WxJsapiSignature;
import me.chanjar.weixin.common.error.WxErrorException;
import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import static org.assertj.core.api.Assertions.assertThat;
/**
* <pre>
* Created by BinaryWang on 2018/8/5.
* </pre>
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Test
@Guice(modules = ApiTestModule.class)
public class WxMaJsapiServiceImplTest {
@Inject
private WxMaService wxService;
@Inject
private WxMaConfig wxMaConfig;
@Test
public void testGetJsapiTicket() throws WxErrorException {
assertThat(this.wxService.getJsapiService().getJsapiTicket()).isNotBlank();
}
@Test
public void testGetJsapiTicket1() throws WxErrorException {
assertThat(this.wxService.getJsapiService().getJsapiTicket(true)).isNotBlank();
}
@Test
public void testCreateJsapiSignature() throws WxErrorException {
final WxJsapiSignature jsapiSignature = this.wxService.getJsapiService().createJsapiSignature("http://www.qq.com");
System.out.println(jsapiSignature);
assertThat(jsapiSignature).isNotNull();
}
}

View File

@ -54,6 +54,7 @@ public class TestConfig extends WxMaInMemoryConfig {
this.templateId = templateId; this.templateId = templateId;
} }
@Override
public void setAccessTokenLock(Lock lock) { public void setAccessTokenLock(Lock lock) {
super.accessTokenLock = lock; super.accessTokenLock = lock;
} }