微信小程序> 微信卡券,微信小程序领取卡券java

微信卡券,微信小程序领取卡券java

浏览量:558 时间: 来源:zhourenfei17
最近做了个领取微信卡券的小程序,看了很多文档资料以及花了很多时间才算搞定的,不过也算是好事多磨,这边记录分享一下,也算给一点提升。
一、开发前准备
1:申请微信公众号和微信小程序,这是两个不同的东西,都需要单独申请、不同的帐号;
2:微信公众号需要开通微信卡券的功能;
3:在微信公众号里面去绑定小程序;
4:申请微信开放平台,并将微信公众号和微信小程序绑定到该开放平台。(注:绑定到开发平台下的作用只是为了获取unionid,因为同一用户在公众号和小程序下获得的openid是不一样的,如果公众号和小程序都需要领取卡券,则最好通过unionid来跟踪用户;如果你只是开发微信小程序的领取卡券,则完全可以忽略第4点,博主本人也没有去绑定到微信开放平台,感觉步骤好多,特别麻烦!)
二、开始开发
1:获取微信卡券
https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1451025272
这边可以直接通过微信公众号提供的接口获取或者创建微信的卡券,此处不过多介绍,只是提一下这边要获取的access_token,网址如下https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140183,代码直接如下:
privatestaticStringgrantType="client_credential";publicstaticStringappId="";//微信公众号appidpublicstaticStringsecret="";//微信公众号密钥publicstaticAccessTokentoken=null;//微信公众号的accessToken对象,由于请求次数有限制,这里使用全局静态变量保存起来publicstaticAccessTokengetToken()throwsWeixinException,JsonParseException,JsonMappingException,IOException{if(token==null||token.getExpires_in()System.currentTimeMillis()){//拼接参数Stringparam="?grant_type="+grantType+"&appid="+appId+"&secret="+secret;//创建请求对象HttpsClienthttp=newHttpsClient();//调用获取access_token接口Responseres=http.get("https://api.weixin.qq.com/cgi-bin/token"+param);System.out.println(res.asString());ObjectMappermapper=newObjectMapper();token=mapper.readValue(res.asString(),AccessToken.class);}returntoken;}
其中需要jackson和weixin4j的jar包,比较普遍,请自行下载;而AccessToken对象也比较简单,就errcode、errmsg、access_token、expires_in这四个参数,比较简单,在文章结尾贴代码
2:升级微信卡券
其实这个步骤也可以省略,升级微信卡券的目的是可以直接从微信卡券跳转到对应的小程序,博主就偷懒了,直接跳过了这个步骤;
不过升级卡券也比较简单,就是调用调用微信公众号的更改微信卡券接口(URL:https://api.weixin.qq.com/card/update?access_token=TOKEN),添加几个字段,可以参考微信官方文档3.1,链接如下:https://mp.weixin.qq.com/cgi-bin/announce?action=getannouncement&key=1490190158&version=1&lang=zh_CN&platform=2
3:领取卡券
3.1:先获取openId
小程序端代码,通过调用wx.login获取code,再调用https://api.weixin.qq.com/sns/jscode2session接口获取openid,博主看到很多例子是直接从小程序端调用这个接口,但我事实中发现是行不通的,因为这个域名无法添加到小程序的request合法域名中,微信给的说明是不要在前端调用这个接口,需要通过后台,那没办法喽
wx.login({success:function(res){varservice_url='https://???/???/weixin/api/login?code='+res.code;//需要将服务器域名添加到小程序的request合法域名中,而且必须是https开头wx.request({url:l,data:{},method:'GET',success:function(res){console.log(res);if(res.data!=null&&res.data!=undefined&&res.data!=''){wx.setStorageSync("openid",res.data.openid);//将获取的openid存到缓存中}}});}});
后端java代码
/小程序后台登录,向微信平台发送获取access_token请求,并返回openId@paramcode@return用户凭证@throwsWeixinException@throwsIOException@throwsJsonMappingException@throwsJsonParseException/@RequestMapping("login")@ResponseBodypublicMapString,Objectlogin(Stringcode,HttpServletRequestrequest)throwsWeixinException,JsonParseException,JsonMappingException,IOException{if(code==null||code.equals("")){thrownewWeixinException("invalidnull,codeisnull.");}MapString,Objectret=newHashMapString,Object();//拼接参数Stringparam="?grant_type="+grant_type+"&appid="+appid+"&secret="+secret+"&js_code="+code;System.out.println("https://api.weixin.qq.com/sns/jscode2session"+param);//创建请求对象HttpsClienthttp=newHttpsClient();//调用获取access_token接口Responseres=http.get("https://api.weixin.qq.com/sns/jscode2session"+param);//根据请求结果判定,是否验证成功JSONObjectjsonObj=res.asJSONObject();if(jsonObj!=null){Objecterrcode=jsonObj.get("errcode");if(errcode!=null){//返回异常信息thrownewWeixinException(getCause(Integer.parseInt(errcode.toString())));}ObjectMappermapper=newObjectMapper();OAuthJsTokenoauthJsToken=mapper.readValue(jsonObj.toJSONString(),OAuthJsToken.class);ret.put("openid",oauthJsToken.getOpenid());}returnret;}
其中OAuthJsToken对象的字段为:openid、expires_in、session_key(会话密钥),在文章结尾贴代码;
3.2:生成领取卡券的签名,并调用wx.addCard方法领取卡券
这边写贴java后端代码
publicstaticApiTicketticket=null;//使用全局静态变量存储ApiTicket对象,当然如果使用缓存框架保存当然更好,这边只是做一个简单示例/@Description:获取领取卡券获取签名等参数@paramcardId:需要领取的卡券的cardId@return@throwsWeixinException@throwsJsonParseException@throwsJsonMappingException@throwsIOException/@RequestMapping("getCardSign")@ResponseBodypublicMapString,StringgetCardSign(StringcardId)throwsWeixinException,JsonParseException,JsonMappingException,IOException{MapString,Stringret=newHashMapString,String();//先要获取api_ticket,由于请求api_ticket的接口访问有次数限制,所以最好将获得到的api_ticket保存到缓存中,这边做法比较简单,直接使用的静态变量if(ticket==null||ticket.getExpires_in()System.currentTimeMillis()){//创建请求对象HttpsClienthttp=newHttpsClient();ObjectMappermapper=newObjectMapper();AccessTokentoken=OpenApi.getToken();//这里获取的token就是最上方代码保存的微信公众号全局静态变量token//通过access_token调用获取api_ticket接口Responseres=http.get("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+token.getAccess_token()+"&type=wx_card");System.out.println(res.asString());ticket=mapper.readValue(res.asString(),ApiTicket.class);}ret=sign(ticket.getTicket(),cardId);//生成领取卡券需要的签名,并返回相关的参数for(Map.Entryentry:ret.entrySet()){System.out.println(entry.getKey()+","+entry.getValue());}returnret;}/@Description:生成卡券需要的签名并返回参数@paramapi_ticket:@paramcardId:需要领取的卡券的cardId@return/publicstaticMapString,Stringsign(Stringapi_ticket,StringcardId){MapString,Stringret=newHashMapString,String();Stringnonce_str=create_nonce_str();Stringtimestamp=create_timestamp();Stringsignature="";Stringparam[]=newString[4];param[0]=nonce_str;param[1]=timestamp;param[2]=api_ticket;param[3]=cardId;Arrays.sort(param);//对参数的value值进行字符串的字典序排序StringBuildersb=newStringBuilder();for(Stringb:param){sb.append(b);}System.out.println(sb);//对上面拼接的字符串进行sha1加密,得到signaturetry{MessageDigestcrypt=MessageDigest.getInstance("SHA-1");crypt.reset();crypt.update(sb.toString().getBytes("UTF-8"));signature=byteToHex(crypt.digest());}catch(NoSuchAlgorithmExceptione){e.printStackTrace();}catch(UnsupportedEncodingExceptione){e.printStackTrace();}//返回领取卡券需要的参数,其中nonceStr和timestamp必须和签名中的保持一致ret.put("card_id",cardId);ret.put("api_ticket",api_ticket);ret.put("nonceStr",nonce_str);ret.put("timestamp",timestamp);ret.put("signature",signature);returnret;}
其中ApiTicket对象的属性有:errcode、errmsg、ticket、expires_in,在文章结尾贴出该代码再贴小程序端代码
varthat=this;varservice_url='https://???/???/weixin/api/getCardSign?cardId='+cardId;//需要将服务器域名添加到小程序的request合法域名中,而且必须是https开头wx.request({url:service_url,data:{},method:'GET',success:function(res){console.log(res);wx.addCard({cardList:[{cardId:that.data.cardId,cardExt:'{"code":"","openid":"","timestamp":'+res.data.timestamp+',"nonce_str":"'+res.data.nonceStr+'","signature":"'+res.data.signature+'"}'}],//这里需要注意的是cardExt参数的value值是String类型,不要使用对象发送;另外openid如果在创建优惠券的时候没有指定,则这边为空,千万不要填写当前用户的openidsuccess:function(result){console.log(res);wx.showToast({title:'领取成功',icon:'success',duration:2000});},fail:function(res){console.log('领取失败');console.log(res);}})}});
ok,如果领取成功,可以直接到微信卡包里面查看。下面贴出AccessToken、ApiTicket、OAuthJsToken的java模型代码
publicclassBaseResponse{privateinterrcode;privateStringerrmsg;publicintgetErrcode(){returnerrcode;}publicvoidsetErrcode(interrcode){this.errcode=errcode;}publicStringgetErrmsg(){returnerrmsg;}publicvoidsetErrmsg(Stringerrmsg){this.errmsg=errmsg;}}publicclassAccessTokenextendsBaseResponse{privateStringaccess_token;privatelongexpires_in;publicStringgetAccess_token(){returnaccess_token;}publicvoidsetAccess_token(Stringaccess_token){this.access_token=access_token;}publiclonggetExpires_in(){returnexpires_in;}publicvoidsetExpires_in(longexpires_in){this.expires_in=System.currentTimeMillis()+(expires_in-100)1000;//原expires_in是有效时长,比如:7200,现改为过期的时间戳}}publicclassApiTicketextendsBaseResponse{privateStringticket;privatelongexpires_in;publicStringgetTicket(){returnticket;}publicvoidsetTicket(Stringticket){this.ticket=ticket;}publiclonggetExpires_in(){returnexpires_in;}publicvoidsetExpires_in(longexpires_in){this.expires_in=System.currentTimeMillis()+(expires_in-100)1000;//原expires_in是有效时长,比如:7200,现改为过期的时间戳}}publicclassOAuthJsToken{privateStringopenid;//用户唯一标识privateintexpires_in=7200;//凭证有效时间,单位:秒privateStringsession_key;//会话密匙privatelongexprexpiredTime;//过期时间publicStringgetOpenid(){returnopenid;}publicvoidsetOpenid(Stringopenid){this.openid=openid;}publicintgetExpires_in(){returnexpires_in;}publicvoidsetExpires_in(intexpires_in){this.expires_in=expires_in;this.exprexpiredTime=System.currentTimeMillis()+expires_in1000;}publicStringgetSession_key(){returnsession_key;}publicvoidsetSession_key(Stringsession_key){this.session_key=session_key;}publiclonggetExprexpiredTime(){returnexprexpiredTime;}publicvoidsetExprexpiredTime(longexprexpiredTime){this.exprexpiredTime=exprexpiredTime;}/判断用户凭证是否过期@return过期返回true,否则返回false/publicbooleanisExprexpired(){returnSystem.currentTimeMillis()=this.exprexpiredTime;}}

版权声明

即速应用倡导尊重与保护知识产权。如发现本站文章存在版权问题,烦请提供版权疑问、身份证明、版权证明、联系方式等发邮件至197452366@qq.com ,我们将及时处理。本站文章仅作分享交流用途,作者观点不等同于即速应用观点。用户与作者的任何交易与本站无关,请知悉。

产品经理

手机 : 13312967497

擅长 : 小程序流量变现

扫码领取礼包

热门模板

  • 头条
  • 搜狐
  • 微博
  • 百家
  • 一点资讯
  • 知乎