国产男女精品_免费黄网在线观看_av综合在线观看_在线v片_欧美一区二区三区激情视频_99视频只有精品

18577034138
微信小程序如何開發卡卷功能

概述:

最近做了個領取微信卡券的小程序,看了很多文檔資料以及花了很多時間才算搞定的,不過也算是好事多磨,這邊記錄分享一下,也算給一點提升。一、開發前準備1:申請微信公眾號 和 微信小程序,這是兩個不同的東西,都需要單獨申請、不同的帳號;2:微信公眾號需要開通微信

最近做了個領取微信卡券的小程序,看了很多文檔資料以及花了很多時間才算搞定的,不過也算是好事多磨,這邊記錄分享一下,也算給一點提升。

一、開發前準備

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,代碼直接如下:

    private static String grantType = "client_credential";
        public static String appId = "";            //微信公眾號appid
            public static String secret = "";            //微信公眾號密鑰
        public static AccessToken token = null;            //微信公眾號的accessToken對象,由于請求次數有限制,這里使用全局靜態變量保存起來
        public static AccessToken getToken() throws WeixinException, JsonParseException, JsonMappingException, IOException{
            if(token == null || token.getExpires_in() < System.currentTimeMillis()){
                //拼接參數
                String param = "?grant_type=" + grantType + "&appid=" + appId + "&secret=" + secret;
                //創建請求對象
                    HttpsClient http = new HttpsClient();
                    //調用獲取access_token接口
                    Response res = http.get("https://api.weixin.qq.com/cgi-bin/token" + param);
                    System.out.println(res.asString());
                    ObjectMapper mapper = new ObjectMapper();
                    token = mapper.readValue(res.asString(),AccessToken.class);
            }
                return token;
        }



其中需要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) {
                var service_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
         * @param code
         * @return 用戶憑證
         * @throws WeixinException
         * @throws IOException
         * @throws JsonMappingException
         * @throws JsonParseException
         */
        @RequestMapping("login")
        @ResponseBody
        public Map<String, Object> login(String code, HttpServletRequest request) throws WeixinException, JsonParseException, JsonMappingException, IOException {
            if (code == null || code.equals("")) {
                throw new WeixinException("invalid null, code is null.");
            }
            
            Map<String, Object> ret = new HashMap<String, Object>();
            //拼接參數
            String param = "?grant_type=" + grant_type + "&appid=" + appid + "&secret=" + secret + "&js_code=" + code;
            
            System.out.println("https://api.weixin.qq.com/sns/jscode2session" + param);
            
            //創建請求對象
            HttpsClient http = new HttpsClient();
            //調用獲取access_token接口
            Response res = http.get("https://api.weixin.qq.com/sns/jscode2session" + param);
            //根據請求結果判定,是否驗證成功
            JSONObject jsonObj = res.asJSONObject();
            if (jsonObj != null) {
                Object errcode = jsonObj.get("errcode");
                if (errcode != null) {
                    //返回異常信息
                    throw new WeixinException(getCause(Integer.parseInt(errcode.toString())));
                }
                
                ObjectMapper mapper = new ObjectMapper();
                OAuthJsToken oauthJsToken = mapper.readValue(jsonObj.toJSONString(),OAuthJsToken.class);
                ret.put("openid", oauthJsToken.getOpenid());
            }
            return ret;
        }



其中OAuthJsToken對象的字段為:openid、expires_in、session_key(會話密鑰) ,在文章結尾貼代碼;

3.2:生成領取卡券的簽名,并調用wx.addCard方法領取卡券

這邊寫貼java后端代碼

            public static ApiTicket ticket = null;//使用全局靜態變量存儲ApiTicket對象,當然如果使用緩存框架保存當然更好,這邊只是做一個簡單示例
        /??
         * @Description: 獲取領取卡券獲取簽名等參數
         * @param cardId:需要領取的卡券的cardId
         * @return
         * @throws WeixinException
         * @throws JsonParseException
         * @throws JsonMappingException
         * @throws IOException
         */
        @RequestMapping("getCardSign")
        @ResponseBody
        public Map<String, String> getCardSign(String cardId) throws WeixinException, JsonParseException, JsonMappingException, IOException{
            Map<String, String> ret = new HashMap<String, String>();
            //先要獲取api_ticket,由于請求api_ticket的接口訪問有次數限制,所以最好將獲得到的api_ticket保存到緩存中,這邊做法比較簡單,直接使用的靜態變量
            if(ticket == null || ticket.getExpires_in() < System.currentTimeMillis()){
                //創建請求對象
                    HttpsClient http = new HttpsClient();
                
                    ObjectMapper mapper = new ObjectMapper();
                
                    AccessToken token = OpenApi.getToken();//這里獲取的token就是最上方代碼保存的微信公眾號全局靜態變量token
                        
                        //通過access_token調用獲取api_ticket接口
                    Response res = 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.Entry entry : ret.entrySet()) {
                       System.out.println(entry.getKey() + ", " + entry.getValue());
                   }
                   return ret;
        }
        /??
         * @Description: 生成卡券需要的簽名并返回參數
         * @param api_ticket:
         * @param cardId:需要領取的卡券的cardId
         * @return
         */
        public static Map<String, String> sign(String api_ticket, String cardId) {
            Map<String, String> ret = new HashMap<String, String>();
            String nonce_str = create_nonce_str();
            String timestamp = create_timestamp();
            String signature = "";
            
            String param[] = new String[4];
            
            param[0] = nonce_str;
            param[1] = timestamp;
            param[2] = api_ticket;
            param[3] = cardId;
            
            Arrays.sort(param);//對參數的value值進行字符串的字典序排序
            
            StringBuilder sb = new StringBuilder();
            for(String b : param){
                sb.append(b);
            }
            System.out.println(sb);
            //對上面拼接的字符串進行sha1加密,得到signature
            try{
                MessageDigest crypt = MessageDigest.getInstance("SHA-1");
                crypt.reset();
                crypt.update(sb.toString().getBytes("UTF-8"));
                signature = byteToHex(crypt.digest());
            }catch (NoSuchAlgorithmException e){
                e.printStackTrace();
            }catch (UnsupportedEncodingException e){
                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);
     
            return ret;
        }



其中ApiTicket對象的屬性有:errcode、errmsg、ticket、expires_in,在文章結尾貼出該代碼

再貼小程序端代碼

        var that = this;
        var service_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如果在創建優惠券的時候沒有指定,則這邊為空,千萬不要填寫當前用戶的openid
                success: 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模型代碼

    public class BaseResponse {
        private int errcode;
        private String errmsg;
        
        public int getErrcode() {
            return errcode;
        }
        public void setErrcode(int errcode) {
            this.errcode = errcode;
        }
        public String getErrmsg() {
            return errmsg;
        }
        public void setErrmsg(String errmsg) {
            this.errmsg = errmsg;
        }
    }
    public class AccessToken extends BaseResponse{
        private String access_token;
        private long expires_in;
        
        public String getAccess_token() {
            return access_token;
        }
        public void setAccess_token(String access_token) {
            this.access_token = access_token;
        }
        public long getExpires_in() {
            return expires_in;
        }
        public void setExpires_in(long expires_in) {
            this.expires_in = System.currentTimeMillis() + (expires_in - 100) * 1000;//原expires_in是有效時長,比如:7200,現改為過期的時間戳
        }
    }
    public class ApiTicket extends BaseResponse{
        private String ticket;
        private long expires_in;
        
        public String getTicket() {
            return ticket;
        }
        public void setTicket(String ticket) {
            this.ticket = ticket;
        }
        public long getExpires_in() {
            return expires_in;
        }
        public void setExpires_in(long expires_in) {
            this.expires_in = System.currentTimeMillis() + (expires_in - 100) * 1000;//原expires_in是有效時長,比如:7200,現改為過期的時間戳
        }
    }
    public class OAuthJsToken {
        private String openid;                //用戶唯一標識
        private int expires_in = 7200;        //憑證有效時間,單位:秒
        private String session_key;            //會話密匙
        private long exprexpiredTime;            //過期時間
        
        public String getOpenid() {
            return openid;
        }
        public void setOpenid(String openid) {
            this.openid = openid;
        }
        public int getExpires_in() {
            return expires_in;
        }
        public void setExpires_in(int expires_in) {
            this.expires_in = expires_in;
            this.exprexpiredTime = System.currentTimeMillis() + expires_in * 1000;
        }
        public String getSession_key() {
            return session_key;
        }
        public void setSession_key(String session_key) {
            this.session_key = session_key;
        }
        
        public long getExprexpiredTime() {
            return exprexpiredTime;
        }
        public void setExprexpiredTime(long exprexpiredTime) {
            this.exprexpiredTime = exprexpiredTime;
        }
        /??
         * 判斷用戶憑證是否過期
         *
         * @return 過期返回 true,否則返回false
         */
        public boolean isExprexpired() {
            return System.currentTimeMillis() >= this.exprexpiredTime;
        }
    }


---------------------

主站蜘蛛池模板: 不卡的毛片| 国产福利片在线| 天天操天天草| 在线国产小视频| 国产91免费| 国产成人aa| 国产精品mm| 欧美三级视频在线| 免费一级淫片| 国产精品乱码久久久久久| 午夜久久视频| 成人免费看片| 97成人精品| 91社在线观看| 美女午夜视频| 国产又色又爽又黄的| 欧美日韩在线视频免费播放| 中出中文字幕| av网在线播放| 久草成人网| 日韩久久视频| 在线观看日韩欧美| 午夜tv影院| 免费日韩一级片| 毛片com| 欧美日韩一区二区不卡| 亚洲色图国产| 一区二区欧美日韩| 香蕉视频911| 九月色婷婷| 在线网站你懂的| 黄色三级av| 亚洲一级黄色| 国产激情片| 亚洲激情四射| 欧美精品二区| 国产欧美小视频| 国产91精品在线观看| 久久精品视频一区二区| 日韩视频专区| 久久综合久|