开发好了小程序后,为了方便用户访问,可以把小程序码展示出来让用户扫码访问。本文将介绍如何生成小程序码。包括:“生成二维码的前端代码”、“请求后端接口的代码”、“生成二维码的后端代码”。
1、生成二维码的前端代码。
输入宽度来生成指定大小的二维码:
<div id="codeMain">
<div class="layui-form">
<input type="text" class="layui-input QRwidth" lay-verify="QRwidth" placeholder="请输入生成二维码图片的宽度"
title="请输入生成二维码图片的宽度" />
<button class="layui-btn" lay-submit lay-filter="createQRcode"><i class="layui-icon layui-icon-edit"></i>
生成二维码</button>
<a href="" download="商家二维码.jpg" class="downloadQRcode"><i class="layui-icon layui-icon-download-circle"></i>
下载二维码</a>
</div>
<div class="showQRcode">
<div class="theQRcode">
<img src="">
</div>
</div>
</div>
2、请求后端接口的代码。
//数据验证
form.on('submit(createQRcode)', function(obj){
var indexLoading = layer.load(1);
var QRwidth = $(".QRwidth").val();
$(".QRwidth").val("");
$.ajax({
url: generateQRCode_url,
type: method_post,
data: {
"width": QRwidth
},
cache: false,
async: true,
dataType: "json",
success: function(data){
console.log(data);
$('.theQRcode img').attr('src',data.qrCodeUrl ); //图片链接(base64)
$('.downloadQRcode').attr('href',data.qrCodeUrl );
console.log($('.downloadQRcode').attr('href'))
layer.close(indexLoading);
},
error: function(XMLHttpRequest, textStatus, errorThrown){
layer.msg(XMLHttpRequest.status + ":" + XMLHttpRequest.statusText);
layer.close(indexLoading);
}
});
return false;
});
数据格式检查代码:
//验证前端输入的宽度值
form.verify({
QRwidth: function(value, item){
if(value < 280 || value > 1280){
isToSend = true;
return "二维码的宽度值必须大于280并且小于1280";
}
},
});
$('.downloadQRcode').click(function(){
if($('.downloadQRcode').attr('href') == ''){
$('.downloadQRcode').attr('download','');
layer.msg("尚无二维码可下载");
}
});
3、生成二维码的后端代码。
检查宽度格式:
if (mpQrCode.getWidth() < 280 || mpQrCode.getWidth() > 1280) {
logger.info("小程序码的宽度最小 280px,最大 1280px");
params.put(BaseAction.JSON_ERROR_KEY, EnumErrorCode.EC_OtherError);
break;
}
请求微信accessToken:
WxAccessToken wxAccessToken = WxUtils.getAccessTokenFromWxServer(false, MP_APPID, MP_SECRET, accessTokenUrl);
if (wxAccessToken == null || StringUtils.isEmpty(wxAccessToken.getAccessToken())) {
logger.info("微信公众号向微信POST请求Token错误!!对应的appid为:" + MP_APPID);
params.put(BaseAction.JSON_ERROR_KEY, EnumErrorCode.EC_OtherError);
break;
}
getAccessTokenFromWxServer方法:
/** 获取微信服务器返回的AccessToken,有效期为两小时,需自己储存。
* 在缓存中保存AccessToken的有效期,如果超时,则重新申请一个,并刷新缓存。否则,继续重用上次申请的
* 由于测试场使用的公众号正是BX的公众号,测试代码频繁(其实不算太频繁)刷新token,将来可能会令微信服务器禁止这种行为 //... */
public static synchronized WxAccessToken getAccessTokenFromWxServer(boolean bDeleteOldToken, String appid, String secret, String url) {
if (StringUtils.isEmpty(appid) || StringUtils.isEmpty(secret)) {
logger.info("appid or secret is null");
return null;
}
if (bDeleteOldToken) {
mapAccessToken.clear();
}
// 判断缓存中有无AccessToken,如果有,直接返回
if (mapAccessToken.containsKey(appid)) {
Date expireDatetime = ((WxAccessToken) mapAccessToken.get(appid)).getDate1();
if (!DatetimeUtil.isAfterDate(new Date(), expireDatetime, 0)) {
return mapAccessToken.get(appid);
}
}
// 缓存中无AccessToken或过期
//
// 将发送请求的必要信息替换成已注册的开发者的信息
String newurl = String.format(url, appid, secret);
// 向微信端发送请求,并返回JSON数据
JSONObject jsonObject = getDataFromWxServer(newurl);
if (jsonObject == null) {
logger.info("获取AccessToken失败!!!"); // getDataFromWxServer()已经logger.error,这里不再需要报警
return null;
} else {
Object wxErrCode = jsonObject.get(BaseWxModel.WX_ERRCODE);
if (wxErrCode == null) {
WxAccessToken accessToken = null;
if (mapAccessToken.containsKey(appid)) {
accessToken = mapAccessToken.get(appid);
} else {
accessToken = new WxAccessToken();
}
accessToken.setAccessToken(jsonObject.getString(WxAccessToken.field.getFIELD_NAME_accessToken()));
accessToken.setExpiresin(jsonObject.getInt(WxAccessToken.field.getFIELD_NAME_expiresin()));
accessToken.setDate1(DatetimeUtil.getDate(new Date(), accessToken.getExpiresin()));
mapAccessToken.put(appid, accessToken);
return accessToken;
} else {
if (BaseAction.ENV != EnumEnv.DEV) {
logger.error("请求微信Token发生错误,错误码:" + wxErrCode);
}
return null;
}
}
}
根据accessToken创建POST请求:
HttpClient httpClient = HttpClientBuilder.create().build();
// 创建POST请求
HttpPost httpPost = new HttpPost(String.format(wxaCodeUnlimit, wxAccessToken.getAccessToken()));
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-Type", "application/json");
//
StringEntity entity = new StringEntity(json.toString(), "UTF-8");
httpPost.setEntity(entity);
执行POST请求:
HttpResponse response = httpClient.execute(httpPost);
StatusLine status = response.getStatusLine();
int state = status.getStatusCode();
logger.info("请求返回:" + state + "(" + wxaCodeUnlimit + ")");
if (state != HttpStatus.SC_OK) {
logger.info("微信公众号向微信POST请求小程序码错误!!对应的appid为:" + MP_APPID);
params.put(BaseAction.JSON_ERROR_KEY, EnumErrorCode.EC_OtherError);
break;
}
创建文件下和保存微信返回的小程序码,并返回给前端显示:
String path = PATH + "/" + company.getDbName() + "/mp";
if (!GeneralUtil.checkDiskSpaceAndCreateFolder(params, path)) {
break;
}
File qrCodePictureDestination = new File(PATH + "/" + company.getDbName() + "/mp/" + company.getDbName() + ".jpg");
OutputStream os = new FileOutputStream(qrCodePictureDestination);
HttpEntity reEntity = response.getEntity();
reEntity.writeTo(os);
//
StringBuilder filePath = new StringBuilder(qrCodePictureDestination.getPath().replaceAll("\\\\", "/"));
for (int i = 0; i < CommoditySyncAction.DIR.length(); i++) {
filePath.setCharAt(i, Character.toLowerCase(filePath.charAt(i)));// 确保下面的替换真正替换到东西
}
String qrCodePictureDir = filePath.toString().replaceAll(CommoditySyncAction.DIR, "/p");
params.put("qrCodeUrl", qrCodePictureDir);
params.put(BaseAction.JSON_ERROR_KEY, EnumErrorCode.EC_NoError);
params.put(KEY_HTMLTable_Parameter_msg, "");//
params.put(BaseAction.SP_OUT_PARAM_sErrorMsg, "");