当前位置: 首页 > news >正文

小程序开发之获取小程序二维码

生活就是问题叠着问题,一个一个的去解决!这句话应该我们这个行业再也合适不过了!

写业务逻辑代码之前,先捋一下思路:用户登录注册之后生成一个有个人标识的二维码,用户可以把这个二维码保存到自己的手机里面,然后分享到微信朋友圈,其他人可以扫面进入小程序,进入指定的小程序页面,进入授权注册,不然我发进入小程序,用户完成授权注册之后,分享出去的那个人下面就会多一个粉丝。

是不是感觉很复杂,才开始我没有仔细阅读小程序官方文档,我还以为前端就可以完成这个工作,做了很久之后,一直报错40001,后来我一看文档,我就不厚道的笑了,去找后台的小哥哥,小哥哥一看没问题,撸代码就是了。经过后台小哥哥不懈努力,终于写了出来!前端这一个只要调用api保存到手机就可以了!




先把后台的代码贴出来吧,虽然我看不懂,我还是后者脸皮要了过来!

package com.weixin.utils.manager;
public class WxConfigDTO {
    //小程序唯一标识   (在微信小程序管理后台获取)    public static final String wxspAppid = "你的小程序appid";    //小程序的 APP secret (在微信小程序管理后台获取)    public static final String wxspSecret = "你的小程序spSecret";    //小程序获取openId URL    public static final String getOpenIdUrl = "你的openIdURL";    //小程序获取openId 授权    public static final String grantType = "你的小程序openId授权";    //小程序获取access_token URL    public static final String getAccessToken = "你的小程序access_token URL";    //获取小程序码 URL    public static final String getImgCode = "你的小程序码 URL";    //阿里云地址    public static final String endpoint = "阿里云地址";    // 云账号AccessKeyID有所有API访问权限    public static final String accessKeyId = "云账号AccessKeyID有所有API访问权限";    //云账号accessKeySecret    public static final String accessKeySecret = "x59xf21ltmr6xrb0rwRfEufthCoOrP";    //阿里云访问图片路径    public static final String ossImg =  "云账号accessKeySecret";    //阿里云访问bucketName    public static final String bucketName =  "阿里云访问bucketName";    //小程序扫码跳转页    public static final String scanToPage =  "小程序扫码跳转页";    //是否支持小程序扫码跳转页    public static enum isToPage{        toPage("page","支持扫码跳转,但小程序要上线,否则生成小程序码失败"),        notToPage("path","不支持扫码跳转,即时小程序未上线,也可以成功生成小程序码");
        isToPage(String scanToPage,String message) {            this.scanToPage = scanToPage;            this.message = message;        }        private String scanToPage;        private String message;        public String getScanToPage() {            return scanToPage;        }        public void setScanToPage(String scanToPage) {            this.scanToPage = scanToPage;        }        public String getMessage() {            return message;        }        public void setMessage(String message) {            this.message = message;        }            }}


package com.weixin.utils.manager;import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.io.UnsupportedEncodingException;import java.net.HttpURLConnection;import java.net.URL;import java.net.URLConnection;import java.security.AlgorithmParameters;import java.security.InvalidAlgorithmParameterException;import java.security.InvalidKeyException;import java.security.NoSuchAlgorithmException;import java.security.Security;import java.security.spec.InvalidParameterSpecException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.HashMap;import java.util.List;import java.util.Map;
import javax.crypto.BadPaddingException;import javax.crypto.Cipher;import javax.crypto.IllegalBlockSizeException;import javax.crypto.NoSuchPaddingException;import javax.crypto.spec.IvParameterSpec;import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;import org.bouncycastle.jce.provider.BouncyCastleProvider;import org.json.JSONObject;
import com.aliyun.oss.OSSClient;import com.aliyun.oss.common.auth.DefaultCredentialProvider;public class WxConfigManager {    public static Map<String, String> getOpenId(String iv,String codeId,String encryptedData ) throws Exception {            Map<String, String> map=new HashMap<String, String>();             1、向微信服务器 使用登录凭证 code 获取 session_key 和 openid             //请求参数            //授权(必填)grant_type=authorization_code            String params = "appid=" + WxConfigDTO.wxspAppid + "&secret=" + WxConfigDTO.wxspSecret + "&js_code=" + codeId + "&grant_type=" + WxConfigDTO.grantType;            //发送请求            String sr = sendGet(WxConfigDTO.getOpenIdUrl, params);            System.err.println(sr);            //解析相应内容(转换成JSON对象)            JSONObject jsonObject = new JSONObject(sr);            String sessionKey = jsonObject.getString("session_key");             2、对encryptedData加密数据进行AES解密             String result = decrypt(encryptedData, sessionKey, iv, "UTF-8");            if (null != result && result.length() > 0) {
                JSONObject userInfoJSON = new JSONObject(result);                map.put("openId",userInfoJSON.get("openId").toString());                map.put("nickName", userInfoJSON.get("nickName").toString());                map.put("gender", userInfoJSON.get("gender").toString());                map.put("city", userInfoJSON.get("city").toString());                map.put("province", userInfoJSON.get("province").toString());                map.put("country", userInfoJSON.get("country").toString());                map.put("avatarUrl", userInfoJSON.get("avatarUrl").toString());                map.put("unionId", userInfoJSON.get("unionId").toString());            }            return map;    }        /**     * 生成小程序邀请码并上传阿里云(三步)     * 1,获取access_token     * 2,获取微信小程序码图片流     * 3,上传阿里云     * @param inviteCode     */    public static void main(String[] args)  throws Exception {        createInviteCode("123456");    }        /**     * 1,获取access_token     * @param inviteCode     * @return     */    public static String createInviteCode(String inviteCode)  throws Exception {        //1,获取access_token        String object = WxConfigManager.sendGet(WxConfigDTO.getAccessToken, "grant_type=client_credential&appid="+WxConfigDTO.wxspAppid+"&secret="+WxConfigDTO.wxspSecret);        //2,获取微信小程序码图片流        return getImageCode(inviteCode,new JSONObject(object).get("access_token").toString());    }        /**     * 2,获取微信小程序码图片流     * @param inviteCode 邀请码,accessToken     * @return 小程序码二进制流     */    public static String getImageCode(String inviteCode,String accessToken)  throws Exception {        //2,获取微信小程序码图片流        //拼接参数,请求微信接口,获取小程序码        URL url = new URL(WxConfigDTO.getImgCode+accessToken);        HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();        // 提交模式        // conn.setConnectTimeout(10000);//连接超时 单位毫秒        // conn.setReadTimeout(2000);//读取超时 单位毫秒        // 发送POST请求必须设置如下两行        httpURLConnection.setDoOutput(true);        httpURLConnection.setDoInput(true);        // 获取URLConnection对象对应的输出流        PrintWriter printWriter = new PrintWriter(httpURLConnection.getOutputStream());        // 发送请求参数        JSONObject paramJson = new JSONObject();        paramJson.put("scene", inviteCode);        paramJson.put(WxConfigDTO.isToPage.notToPage.getScanToPage(), WxConfigDTO.scanToPage);        printWriter.write(paramJson.toString());        // flush输出流的缓冲        printWriter.flush();        //开始获取数据        BufferedInputStream inputStream = new BufferedInputStream(httpURLConnection.getInputStream());        //上传阿里云        return uploadOss(inviteCode,inputStream);    }        /**     * 3,上传阿里云     * @param inviteCode     * @return 图片地址     */    public static String uploadOss(String inviteCode,BufferedInputStream inputStream) {        //3,上传阿里云        // 创建OSSClient实例        OSSClient ossClient = new OSSClient(WxConfigDTO.endpoint, new DefaultCredentialProvider(WxConfigDTO.accessKeyId, WxConfigDTO.accessKeySecret),null);        // 上传文件到阿里云。        Date at = new Date();        String endPath = "MpInviteCode" + "/" + new SimpleDateFormat("yyyyMM").format(at) + "/"                + new SimpleDateFormat("dd").format(at) + "/" + inviteCode +".jpg";        String cipther = Env.isProduct != null && Env.isProduct ? endPath : "test/" + endPath;        ossClient.putObject(WxConfigDTO.bucketName, cipther, inputStream);        // 关闭OSSClient。        ossClient.shutdown();        //返回阿里云路径        System.err.println( WxConfigDTO.ossImg+cipther);        return WxConfigDTO.ossImg+cipther;    }        public static String sendGet(String url, String param) {        String result = "";        BufferedReader in = null;        try {            String urlNameString = url + "?" + param;            URL realUrl = new URL(urlNameString);            // 打开和URL之间的连接            URLConnection connection = realUrl.openConnection();            // 设置通用的请求属性            connection.setRequestProperty("accept", "*/*");            connection.setRequestProperty("connection", "Keep-Alive");            connection.setRequestProperty("user-agent",                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");            // 建立实际的连接            connection.connect();            // 获取所有响应头字段            Map<String, List<String>> map = connection.getHeaderFields();            // 遍历所有的响应头字段            for (String key : map.keySet()) {                System.out.println(key + "--->" + map.get(key));            }            // 定义 BufferedReader输入流来读取URL的响应            in = new BufferedReader(new InputStreamReader(                    connection.getInputStream()));            String line;            while ((line = in.readLine()) != null) {                result += line;            }        } catch (Exception e) {            System.out.println("发送GET请求出现异常!" + e);            e.printStackTrace();        }        // 使用finally块来关闭输入流        finally {            try {                if (in != null) {                    in.close();                }            } catch (Exception e2) {                e2.printStackTrace();            }        }        return result;    }
    /**     * 向指定 URL 发送POST方法的请求     *     * @param url     *            发送请求的 URL     * @param param     *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。     * @return 所代表远程资源的响应结果     */    public static String sendPost(String url, String param) {        PrintWriter out = null;        BufferedReader in = null;        String result = "";        try {            URL realUrl = new URL(url);            // 打开和URL之间的连接            URLConnection conn = realUrl.openConnection();            // 设置通用的请求属性            conn.setRequestProperty("accept", "*/*");            conn.setRequestProperty("connection", "Keep-Alive");            conn.setRequestProperty("user-agent",                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");            // 发送POST请求必须设置如下两行            conn.setDoOutput(true);            conn.setDoInput(true);            // 获取URLConnection对象对应的输出流            out = new PrintWriter(conn.getOutputStream());            // 发送请求参数            out.print(param);            // flush输出流的缓冲            out.flush();            // 定义BufferedReader输入流来读取URL的响应            in = new BufferedReader(                    new InputStreamReader(conn.getInputStream()));            String line;            while ((line = in.readLine()) != null) {                result += line;            }        } catch (Exception e) {            System.out.println("发送 POST 请求出现异常!"+e);            e.printStackTrace();        }        //使用finally块来关闭输出流、输入流        finally{            try{                if(out!=null){                    out.close();                }                if(in!=null){                    in.close();                }            }            catch(IOException ex){                ex.printStackTrace();            }        }        return result;    }        static {        //BouncyCastle是一个开源的加解密解决方案,主页在http://www.bouncycastle.org/        Security.addProvider(new BouncyCastleProvider());    }        /**     * AES解密     *     * @param data           //密文,被加密的数据     * @param key            //秘钥     * @param iv             //偏移量     * @param encodingFormat //解密后的结果需要进行的编码     * @return     * @throws Exception     */    public static String decrypt(String data, String key, String iv, String encodingFormat) throws Exception {//        initialize();
        //被加密的数据        byte[] dataByte = Base64.decodeBase64(data.getBytes());        //加密秘钥        byte[] keyByte = Base64.decodeBase64(key.getBytes());        //偏移量        byte[] ivByte = Base64.decodeBase64(iv.getBytes());

        try {            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");            parameters.init(new IvParameterSpec(ivByte));
            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
            byte[] resultByte = cipher.doFinal(dataByte);            if (null != resultByte && resultByte.length > 0) {                String result = new String(resultByte, encodingFormat);                return result;            }            return null;        } catch (NoSuchAlgorithmException e) {            e.printStackTrace();        } catch (NoSuchPaddingException e) {            e.printStackTrace();        } catch (InvalidParameterSpecException e) {            e.printStackTrace();        } catch (InvalidKeyException e) {            e.printStackTrace();        } catch (InvalidAlgorithmParameterException e) {            e.printStackTrace();        } catch (IllegalBlockSizeException e) {            e.printStackTrace();        } catch (BadPaddingException e) {            e.printStackTrace();        } catch (UnsupportedEncodingException e) {            e.printStackTrace();        }
        return null;    }}复制代码

实现逻辑:扫码进来的会进入指定的授权注册页面,完成注册任务,后台会返给我一张带有用户个人标识的小程序二维码,然后我把它放在缓存里面,需要用的时候展示给用户!用户可以把二维码图片保存到手机里,通过朋友圈分享出去!

前端代码逻辑

方法一:

    keepPhone: function () {    var that = this;    var mpInvitePic = that.data.mpInvitePic;    var switchs = that.data.switchs;    // 检查用户是否授权    wx.getSetting({      success: function (res) {        if (!res.authSetting['scope.writePhotosAlbum']) {          // 用户授权保存到手机相册          wx.authorize({            scope: 'scope.writePhotosAlbum',            success: function (res) {              // api不支持网络图片,所以你需要下载一下,把你的网络图片下载下来,微信那边给你生成一个临时路径!              wx.downloadFile({                url: mpInvitePic,                success: function (res) {                  //保存到手机相册api                  wx.saveImageToPhotosAlbum({                    filePath: res.tempFilePath,                    success: function (res) {                      wx.showToast({ title: '保存成功', })                    }                  })                }              })            },            fail(res) {              wx.showToast({                title: '影响您使用小程序的某些功能',                icon: 'none'              })            }          })        }      },      fail(res) {
      }    })  },
复制代码

方法二:

  keepPhone:function(){    var that = this;    var mpInvitePic = that.data.mpInvitePic;    var switchs = that.data.switchs;    wx.downloadFile({      url:mpInvitePic,      success: function (res) {        if (res.statusCode == 200) {          wx.saveImageToPhotosAlbum({            filePath: res.tempFilePath,            success: function (res) {              wx.showToast({ title: '保存成功'});            }          })        }      }    })  },复制代码


转载于:https://juejin.im/post/5c061d9051882516fa63adac

相关文章:

  • Android Contextual Menus之二:contextual action mode
  • 基本类型和引用类型的值 动态的属性
  • JVM启动参数小结
  • java B2B2C源码电子商务平台 -----客户端负载均衡策略
  • 八年技术加持,性能提升10倍,阿里云HBase 2.0首发商用
  • 构建基于WCF Restful Service的服务
  • Python基础10_动态传参,名称空间和作用域,函数嵌套,关键字global和nonlocal
  • Log4j.properties配置详解
  • Linux环境搭建 | 使用WinSCP远程连接虚拟机
  • Spring boot JPA 用自定义主键策略 生成自定义主键ID
  • java 环境 eclipse 配置
  • 福大软工 · 第十次作业 - 项目测评(团队) [已完成]
  • Html页面插入flash代码
  • 关于自定义 Alert
  • C#练习4
  • #Java异常处理
  • C++回声服务器_9-epoll边缘触发模式版本服务器
  • C学习-枚举(九)
  • Elasticsearch 参考指南(升级前重新索引)
  • Java-详解HashMap
  • js中的正则表达式入门
  • OSS Web直传 (文件图片)
  • Phpstorm怎样批量删除空行?
  • Python语法速览与机器学习开发环境搭建
  • SOFAMosn配置模型
  • TypeScript实现数据结构(一)栈,队列,链表
  • Web标准制定过程
  • 基于遗传算法的优化问题求解
  • 技术攻略】php设计模式(一):简介及创建型模式
  • 理解IaaS, PaaS, SaaS等云模型 (Cloud Models)
  • 前端面试之闭包
  • 我的面试准备过程--容器(更新中)
  • 学习笔记DL002:AI、机器学习、表示学习、深度学习,第一次大衰退
  • 一些关于Rust在2019年的思考
  • 用Python写一份独特的元宵节祝福
  • 在electron中实现跨域请求,无需更改服务器端设置
  • ionic异常记录
  • ​LeetCode解法汇总2182. 构造限制重复的字符串
  • # centos7下FFmpeg环境部署记录
  • #【QT 5 调试软件后,发布相关:软件生成exe文件 + 文件打包】
  • #include<初见C语言之指针(5)>
  • (初研) Sentence-embedding fine-tune notebook
  • (每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理第3章 信息系统治理(一)
  • (三)c52学习之旅-点亮LED灯
  • (十八)三元表达式和列表解析
  • (学习日记)2024.01.09
  • (转)Groupon前传:从10个月的失败作品修改,1个月找到成功
  • (转载)在C#用WM_COPYDATA消息来实现两个进程之间传递数据
  • .locked1、locked勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .NET CF命令行调试器MDbg入门(三) 进程控制
  • .net 按比例显示图片的缩略图
  • .Net 访问电子邮箱-LumiSoft.Net,好用
  • .NET 分布式技术比较
  • .NET/C# 中你可以在代码中写多个 Main 函数,然后按需要随时切换
  • .netcore 如何获取系统中所有session_如何把百度推广中获取的线索(基木鱼,电话,百度商桥等)同步到企业微信或者企业CRM等企业营销系统中...