Skip to content

Commit

Permalink
#776 开放平台增加获取会员卡开卡插件参数和手机端预授权等接口
Browse files Browse the repository at this point in the history
1、增加卡券的api_ticket,区分jsapi_ticket,二者的获取逻辑不同;
2、增加小程序审核事件及审核事件推送消息SuccTime和Reason两个字段;
3、增加开放平台获取会员卡开卡插件参数接口。
4、增加开放平台手机端预授权接口实现;
  • Loading branch information
binarywang authored Sep 27, 2018
2 parents 9fcb433 + 34eb2f6 commit ec5cc69
Show file tree
Hide file tree
Showing 15 changed files with 353 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,15 @@ public static class EventType {
*/
public static final String CARD_PAY_ORDER = "card_pay_order";

/**
* 小程序审核事件:审核通过
*/
public static final String WEAPP_AUDIT_SUCCESS = "weapp_audit_success";

/**
* 小程序审核事件:审核不通过
*/
public static final String WEAPP_AUDIT_FAIL = "weapp_audit_fail";

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,26 @@ public interface WxMaJsapiService {
/**
* 获得jsapi_ticket的url
*/
String GET_JSAPI_TICKET_URL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi";
String GET_JSAPI_TICKET_URL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket";

/**
* 获得卡券api_ticket,不强制刷新api_ticket
*
* @see #getJsapiTicket(boolean)
*/
String getCardApiTicket() throws WxErrorException;

/**
* <pre>
* 获得卡券api_ticket
* 获得时会检查apiToken是否过期,如果过期了,那么就刷新一下,否则就什么都不干
*
* 详情请见:http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CN
* </pre>
*
* @param forceRefresh 强制刷新
*/
String getCardApiTicket(boolean forceRefresh) throws WxErrorException;

/**
* 获得jsapi_ticket,不强制刷新jsapi_ticket
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,32 @@ public WxMaJsapiServiceImpl(WxMaService wxMaService) {
this.wxMaService = wxMaService;
}

public String getCardApiTicket() throws WxErrorException {
return getCardApiTicket(false);
}

public String getCardApiTicket(boolean forceRefresh) throws WxErrorException {
Lock lock = this.wxMaService.getWxMaConfig().getCardApiTicketLock();
try {
lock.lock();
if (forceRefresh) {
this.wxMaService.getWxMaConfig().expireCardApiTicket();
}

if (this.wxMaService.getWxMaConfig().isCardApiTicketExpired()) {
String responseContent = this.wxMaService.get(GET_JSAPI_TICKET_URL + "?type=wx_card", 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().updateCardApiTicket(jsapiTicket, expiresInSeconds);
}
} finally {
lock.unlock();
}
return this.wxMaService.getWxMaConfig().getJsapiTicket();
}

@Override
public String getJsapiTicket() throws WxErrorException {
return getJsapiTicket(false);
Expand All @@ -43,7 +69,7 @@ public String getJsapiTicket(boolean forceRefresh) throws WxErrorException {
}

if (this.wxMaService.getWxMaConfig().isJsapiTicketExpired()) {
String responseContent = this.wxMaService.get(GET_JSAPI_TICKET_URL, null);
String responseContent = this.wxMaService.get(GET_JSAPI_TICKET_URL + "?type=jsapi", null);
JsonElement tmpJsonElement = JSON_PARSER.parse(responseContent);
JsonObject tmpJsonObject = tmpJsonElement.getAsJsonObject();
String jsapiTicket = tmpJsonObject.get("ticket").getAsString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,25 @@ public interface WxMaConfig {
*/
void updateJsapiTicket(String jsapiTicket, int expiresInSeconds);

String getCardApiTicket();

Lock getCardApiTicketLock();

boolean isCardApiTicketExpired();

/**
* 强制将卡券api ticket过期掉
*/
void expireCardApiTicket();

/**
* 应该是线程安全的
*
* @param 卡券apiTicket 新的卡券api ticket值
* @param expiresInSeconds 过期时间,以秒为单位
*/
void updateCardApiTicket(String apiTicket, int expiresInSeconds);

String getAppid();

String getSecret();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
package cn.binarywang.wx.miniapp.config;

import java.io.File;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.util.http.apache.ApacheHttpClientBuilder;
import java.io.File;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
* 基于内存的微信配置provider,在实际生产环境中应该将这些配置持久化
Expand All @@ -32,8 +31,14 @@ public class WxMaInMemoryConfig implements WxMaConfig {
protected volatile String jsapiTicket;
protected volatile long jsapiTicketExpiresTime;

//微信卡券的ticket单独缓存
protected volatile String cardApiTicket;
protected volatile long cardApiTicketExpiresTime;


protected Lock accessTokenLock = new ReentrantLock();
protected Lock jsapiTicketLock = new ReentrantLock();
protected Lock cardApiTicketLock = new ReentrantLock();

/**
* 临时文件目录
Expand Down Expand Up @@ -103,6 +108,34 @@ public void updateJsapiTicket(String jsapiTicket, int expiresInSeconds) {
this.jsapiTicketExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L;
}


@Override
public String getCardApiTicket() {
return this.cardApiTicket;
}

@Override
public Lock getCardApiTicketLock() {
return this.cardApiTicketLock;
}

@Override
public boolean isCardApiTicketExpired() {
return System.currentTimeMillis() > this.cardApiTicketExpiresTime;
}

@Override
public void expireCardApiTicket() {
this.cardApiTicketExpiresTime = 0;
}

@Override
public void updateCardApiTicket(String cardApiTicket, int expiresInSeconds) {
this.cardApiTicket = cardApiTicket;
// 预留200秒的时间
this.cardApiTicketExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L;
}

@Override
public void expireAccessToken() {
this.expiresTime = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ public interface WxMpMemberCardService {
*/
String MEMBER_CARD_ACTIVATEUSERFORM = "https://api.weixin.qq.com/card/membercard/activateuserform/set";

/**
* 获取会员卡开卡插件参数
*/
String MEMBER_CARD_ACTIVATE_URL = "https://api.weixin.qq.com/card/membercard/activate/geturl";

/**
* 得到WxMpService
*/
Expand Down Expand Up @@ -88,4 +93,13 @@ public interface WxMpMemberCardService {
*/
MemberCardActivateUserFormResult setActivateUserForm(MemberCardActivateUserFormRequest userFormRequest) throws WxErrorException;

/**
* 获取会员卡开卡插件参数(跳转型开卡组件需要参数)
*
* @param cardId
* @param outStr
* @return
* @throws WxErrorException
*/
ActivatePluginParam getActivatePluginParam(String cardId, String outStr) throws WxErrorException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;

/**
* 会员卡相关接口的实现类
*
Expand Down Expand Up @@ -237,7 +242,7 @@ public WxMpMemberCardUserInfoResult getUserInfo(String cardId, String code) thro
jsonObject.addProperty("code", code);

String responseContent = this.getWxMpService().post(MEMBER_CARD_USER_INFO_GET, jsonObject.toString());
log.debug("{}",responseContent);
log.debug("{}", responseContent);
JsonElement tmpJsonElement = new JsonParser().parse(responseContent);
return WxMpGsonBuilder.INSTANCE.create().fromJson(tmpJsonElement,
new TypeToken<WxMpMemberCardUserInfoResult>() {
Expand Down Expand Up @@ -280,4 +285,91 @@ public MemberCardActivateUserFormResult setActivateUserForm(MemberCardActivateUs
return MemberCardActivateUserFormResult.fromJson(responseContent);
}

/**
* 获取会员卡开卡插件参数(跳转型开卡组件需要参数)
*
* @param outStr
* @return
* @throws WxErrorException
*/
public ActivatePluginParam getActivatePluginParam(String cardId, String outStr) throws WxErrorException {
JsonObject params = new JsonObject();
params.addProperty("card_id", cardId);
params.addProperty("outer_str", outStr);
String response = this.wxMpService.post(MEMBER_CARD_ACTIVATE_URL, GSON.toJson(params));
ActivatePluginParamResult result = GSON.fromJson(response, ActivatePluginParamResult.class);
if (0 == result.getErrcode()) {
String url = result.getUrl();
try {
String decodedUrl = URLDecoder.decode(url, "UTF-8");
Map<String, String> resultMap = parseRequestUrl(decodedUrl);
ActivatePluginParam activatePluginParam = new ActivatePluginParam();
activatePluginParam.setEncryptCardId(resultMap.get("encrypt_card_id"));
activatePluginParam.setOuterStr(resultMap.get("outer_str"));
activatePluginParam.setBiz(resultMap.get("biz")+"==");
return activatePluginParam;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
return null;
}

/**
* 去掉url中的路径,留下请求参数部分
*
* @param strURL url地址
* @return url请求参数部分
*/
private static String truncateUrlPage(String strURL) {
String strAllParam = null;
String[] arrSplit = null;
arrSplit = strURL.split("[?]");
if (strURL.length() > 1) {
if (arrSplit.length > 1) {
if (arrSplit[1] != null) {
strAllParam = arrSplit[1];
}
}
}

return strAllParam;
}

/**
* 解析出url参数中的键值对
* 如 "index.jsp?Action=del&id=123",解析出Action:del,id:123存入map中
*
* @param URL url地址
* @return url请求参数部分
*/
public static Map<String, String> parseRequestUrl(String URL) {
Map<String, String> mapRequest = new HashMap<String, String>();

String[] arrSplit = null;

String strUrlParam = truncateUrlPage(URL);
if (strUrlParam == null) {
return mapRequest;
}
arrSplit = strUrlParam.split("[&]");
for (String strSplit : arrSplit) {
String[] arrSplitEqual = null;
arrSplitEqual = strSplit.split("[=]");

//解析出键值
if (arrSplitEqual.length > 1) {
//正确解析
mapRequest.put(arrSplitEqual[0], arrSplitEqual[1]);

} else {
if (arrSplitEqual[0] != "") {
//只有参数没有值,不加入
mapRequest.put(arrSplitEqual[0], "");
}
}
}
return mapRequest;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package me.chanjar.weixin.mp.bean.membercard;

import com.google.gson.annotations.SerializedName;
import lombok.Data;

/**
* @author yqx
* @date 2018/9/19
*/
@Data
public class ActivatePluginParam {

@SerializedName("encrypt_card_id")
String encryptCardId;

@SerializedName("outer_str")
String outerStr;

@SerializedName("biz")
String biz;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package me.chanjar.weixin.mp.bean.membercard;

import lombok.Data;

/**
* @author yqx
* @date 2018/9/19
*/
@Data
public class ActivatePluginParamResult {

private int errcode;

private String errmsg;

private String url;

}
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,21 @@ public class WxMpXmlMessage implements Serializable {
@XStreamAlias("DeviceStatus")
private Integer deviceStatus;

///////////////////////////////////////
// 小程序 审核事件
///////////////////////////////////////
/**
* 审核成功时的时间(整形),时间戳
*/
@XStreamAlias("SuccTime")
private Long succTime;

/**
* 审核失败的原因
*/
@XStreamAlias("Reason")
private String reason;

public static WxMpXmlMessage fromXml(String xml) {
//修改微信变态的消息内容格式,方便解析
xml = xml.replace("</PicList><PicList>", "");
Expand Down
Loading

0 comments on commit ec5cc69

Please sign in to comment.