2016-09-04 22:17:55 weixin_36050378 阅读数 30902
所有微信开发的相关内容,都需要参考官方文档。

[微信公众平台|开发文档] http://mp.weixin.qq.com/wiki/home/

一、通过网页授权,可以获取用户微信的基本信息。

二、总共有5个步骤:

1 :用户同意授权,获取code

2 :通过code换取网页授权access_token

3 :刷新access_token(如果需要)

4 :拉取用户信息(需scope为 snsapi_userinfo)

5 附:检验授权凭证(access_token)是否有效

三、每一个步骤的实现。

1 :用户同意授权,获取code

/**
     * @explain
     * 获取code,用于获取openid和access_token
     * @remark
     * code只能使用一次,当获取到之后code失效,再次获取需要重新进入
     * 不会弹出授权页面,适用于关注公众号后自定义菜单跳转等,如果不关注,那么只能获取openid
     **/
    public function getCode()
    {
        if (isset($_GET["code"])) {
            return $_GET["code"];
        } else {
            $str = "location: https://open.weixin.qq.com/connect/oauth2/authorize?appid=" . $this->appid . "&redirect_uri=" . $this->index_url . "&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect";
            header($str);
            exit;
        }
    }

2 :通过code换取网页授权access_token

/**
     * @explain
     * 用于获取access_token,返回的<span style="font-family: Arial, Helvetica, sans-serif;">$access_token_array中也包含有用户的openid信息。</span>

     **/
    public function getOpenId()
    {
        $access_token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" . $this->appid . "&secret=" . $this->appsecret . "&code=" . $this->code . "&grant_type=authorization_code";
        $access_token_json = $this->https_request($access_token_url);
        $access_token_array = json_decode($access_token_json, TRUE);
        return $access_token_array;
    }

3 :刷新access_token(如果需要)

这一步直接略过。

4 :拉取用户信息(需scope为 snsapi_userinfo)

/**
     * @explain
     * 获取到用户的openid之后可以判断用户是否有数据,可以直接跳过获取access_token,也可以继续获取access_token
     **/
    public function getUserInfo()
    {
        
        $userinfo_url = "https://api.weixin.qq.com/sns/userinfo?access_token=".$this->access_token['access_token'] ."&openid=" . $this->access_token['openid']."&lang=zh_CN";
        $userinfo_json = $this->https_request($userinfo_url);
        $userinfo_array = json_decode($userinfo_json, TRUE);
        return $userinfo_array;
    }
至此四个步骤全部完成。


四、完整代码。实际项目使用TP3.2.3。

<?php

namespace Wechat\Controller;

use Think\Controller;

//微信接口基础类,其他微信类都继承这个基础类。可以自动判断用户状态,获取用户信息。
class WxbaseController extends Controller
{

    public $appid = 'wxba09d9f0fed4b84b';                   //微信APPID,公众平台获取
    public $appsecret = '332c2b1fc1eb282c0136b73723db4237'; //微信APPSECREC,公众平台获取
    public $index_url = "http://www.你的域名.cn/项目目录/index.php?m=分组&c=控制器&a=方法";  //微信回调地址,要跟公众平台的配置域名相同
    public $code;
    public $openid;

    /**
     *检测有无$_SESSION。<span style="font-family: Arial, Helvetica, sans-serif;">如果有,直接忽略。</span>
     *如果没有$<span style="font-family:Arial, Helvetica, sans-serif;">_SESSION</span>,就依次执行getCode、getOpenId、getUserInfo来获取用户信息。目的是解决CODE只能获取一次,刷新页面openid会丢失的问题。
     *再判断是否在数据库中,没有则写入数据库。最后将open_id写入session。
<span style="white-space:pre">	</span>*/
    public function _initialize()
    {
            if (!$_SESSION['openid']) {                             //如果$_SESSION中没有openid,说明用户刚刚登陆,就执行getCode、getOpenId、getUserInfo获取他的信息
                $this->code = $this->getCode();
                $this->access_token = $this->getOpenId();
                $userInfo = $this->getUserInfo();
                if ($userInfo) {
                    $ins = M('Wechat_user_info');<span style="white-space:pre">		</span>    //其他框架请自行调整方法。
                    $map['openid'] = $userInfo['openid'];
                    $result = $ins->where($map)->find();            //根据OPENID查找数据库中是否有这个用户,如果没有就写数据库。继承该类的其他类,用户都写入了数据库中。
                    if (!$result) {
                        $ins->add($userInfo);
                    }
                    session('openid', $userInfo['openid']);         //写到$_SESSION中。微信缓存很坑爹,调试时请及时清除缓存再试。
                }
            }

    }

    /**
     * @explain
     * 获取code,用于获取openid和access_token
     * @remark
     * code只能使用一次,当获取到之后code失效,再次获取需要重新进入
     * 不会弹出授权页面,适用于关注公众号后自定义菜单跳转等,如果不关注,那么只能获取openid
     **/
    public function getCode()
    {
        if (isset($_GET["code"])) {
            return $_GET["code"];
        } else {
            $str = "location: https://open.weixin.qq.com/connect/oauth2/authorize?appid=" . $this->appid . "&redirect_uri=" . $this->index_url . "&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect";
            header($str);
            exit;
        }
    }

    /**
     * @explain
     * 用于获取用户openid
     **/
    public function getOpenId()
    {
        $access_token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" . $this->appid . "&secret=" . $this->appsecret . "&code=" . $this->code . "&grant_type=authorization_code";
        $access_token_json = $this->https_request($access_token_url);
        $access_token_array = json_decode($access_token_json, TRUE);
        return $access_token_array;
    }

    /**
     * @explain
     * 通过code获取用户openid以及用户的微信号信息
     * @return
     * @remark
     * 获取到用户的openid之后可以判断用户是否有数据,可以直接跳过获取access_token,也可以继续获取access_token
     * access_token每日获取次数是有限制的,access_token有时间限制,可以存储到数据库7200s. 7200s后access_token失效
     **/
    public function getUserInfo()
    {

        $userinfo_url = "https://api.weixin.qq.com/sns/userinfo?access_token=".$this->access_token['access_token'] ."&openid=" . $this->access_token['openid']."&lang=zh_CN";
        $userinfo_json = $this->https_request($userinfo_url);
        $userinfo_array = json_decode($userinfo_json, TRUE);
        return $userinfo_array;
    }


    /**
     * @explain
     * 发送http请求,并返回数据
     **/
    public function https_request($url, $data = null)
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        if (!empty($data)) {
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $output = curl_exec($curl);
        curl_close($curl);
        return $output;
    }
}



2014-03-14 15:55:17 u013802231 阅读数 2978

微信开发视频教程-深入浅出微信公众平台实战开发(微网站、LBS云、Api接口调用、服务号高级接口)

一、微信开发实例视频教程总目录:


微信开发实例视频教程

讲师介绍:

易伟,现广东合桓律师事务所专职律师。业余程序开发爱好者,2013年编著的《微信公众平台搭建与开发揭秘》一书出版后,市场引起极大的反响,短短几个月销量过万。

二、为什么需要微信开发实例视频教程这么套课程?

2.1、用户需要什么?

微信公众平台已经成为企业的标配,个人自媒体的发展也越来越重视微信公众平台。随着微信公众平台开发系统的报价水涨船高(微信支付20万起),一些企业希望企业内部人员能够学习开发微信公众平台,便于日后维护和节约成本。

2.2、微信开发实例视频教程学习目标(我们提供什么?)

目标一. 可以让学员快速上手掌握微信公众平台的特点。

目标二. 可以让学员迅速了解微信公众平台常用API的调用。

目标三. 可以让学员迅速掌握微信公众平台与html5的结合。

目标四. 可以让学员熟练使用微信公众平台的高级接口。

目标五. 了解ajax技术。

目标六. 了解LBS云开发。

目标七. 了解360全景图。

目标八. 通过微信开发实例视频教程的学习,可以制作出完整功能的订阅号和服务号微信平台。

2.3、微信开发实例视频教程课程特色

特点一、讲师为业余程序开发爱好者,短时间内通过自学掌握微信公众平台开发技术,可以提供快速学习的方法和介绍学习经验,特别适合零基础学员。

特点二、微信公众平台各功能都是在客户需求基础上开发,实用性强。

特点三、在微信官方示例代码上进行修改,适合基础学员学习,避免讲解过于复杂的类的封装和继承。

2.4、微信开发实例视频教程课程亮点

亮点一、紧跟最新微信公众平台接口更新内容,对各个接口讲解全面。

亮点二、云平台开发,兼顾主流的BAE和SAE云平台,降低学习成本。

亮点三、Dw6微网站开发,快速上手,所见所得,减少代码录入。

亮点四、单客服、多客服、手机留言客服系统,多种客服解决方案,解决企业需求。

亮点五、刮刮卡、会员卡、大转盘、一站到底微信流行游戏悉数介绍。

三、微信开发实例视频教程真心不错,我可以学吗?

微信开发实例视频教程针对零基础学员,如果具有一定的php和jquery基础将更快速的学习。

四、我该怎么学,如何才能学好微信开发实例视频教程这门课程,给些建议。

4.1、微信开发实例视频教程在时间上的安排建议

微信开发实例视频教程共100讲,如果您时间上充分,可以按照课程顺序逐一学习。

如果您是上班族或您已经有一定的基础了,可以挑选有兴趣的课程直接学习,每小节课程4-10分钟,特别适合碎片化学习。

4.2、微信开发实例视频教程学习要求

如果您没有基础,建议还是中规中矩的按照课程进度一点一点仔细观看学习,并一定要把看完的视频中的代码自己手敲一遍,以加深理解和记忆

如果您有基础,可不必按步就搬进行,可以拿你感兴趣的部分去学习,但一定要注意实践,并学会举一反三

4.3、微信开发实例视频教程讲师建议

1.最好看完视频之后,抛开视频,独立自己去把上课中的示例写一遍,看自己是否理解,如果不正确,可以回过头看再看下视频,如果反复,达到真正理解和熟练掌握的目的。

2. 一定不要过于依赖视频,要学会看API和使用百度,学会思考,学会举一反三。

3.先把功能实现,再去简化代码,不要拘泥于一两个封装好的代码。

五、学完微信开发实例视频教程这门课程后能做什么?

学会微信开发实例视频教程后,您可以结合用户微信公众平台建立成熟的运营方案,可以从事微信公众平台技术维护相关工作。

六、学习微信开发实例视频教程常见问题:

常见问题一:学习该教程使用什么软件?

讲师回答:php的IDE都可以,建议使用Dreamweaver6,方便微网站开发。至少要做到代码错误提示

常见问题二:学这个课程需要什么基础?

讲师回答:不需要基础。

常见问题三:自己的服务器是否可以?BAE收费怎么办?

讲师回答:可以使用php服务器或其他云服务,BAE收费后可使用SAE,有免费的云豆。

微信开发实例视频教程-深入浅出微信公众平台实战开发(微网站、LBS云、Api接口调用、服务号高级接口)地址:http://www.ibeifeng.com/goods-383.html


2016-11-15 11:38:46 qq_24091555 阅读数 20062

           由于项目需要,需要接触微信开发,并要调用微信的JS-SDK里面的接口。

       因为经验缺乏,我百度一下关于微信开发的资料,但收集的资料都不尽人意。网上的主流的微信开发是采用PHP开发的,而本人学的Java。所以对PHP微信开发只能看懂思路。更有的是,网上一些微信开发视频,也是和PHP有关的,关于用Java开发的甚少。

       无奈之下,我只好苦啃微信开发文档。大家都知道,微信官方给的开发文档真的有点那个啥,一个功能实现非要分几个地方来说,看完这块,又得点击另一个页面看完另一块,甚是麻烦。这样的设定也让我走了好多坑。

但功夫不负有心,在研究透了微信开发文档之后,我顺利在在项目中完成微信开发。现在我将微信开发的经验分享一下,希望对大家有所帮助。

       微信JS-SDK是微信公众号平台面向网页开发这提供基于微信内的网页开发工具包。接口大类分为:基础接口、分享接口、图像接口、音频接口、智能接口、设备信息、地址位置、摇一摇周边、界面操作、微信扫一扫、微信小店、微信卡劵和微信支付。一般使用频率高的就是分享接口、地理微信、微信扫一扫和微信支付。

接下来,我将主要讲解如何调用微信分享接口。

第一步,准备内网映射工具,ngrok。不清楚这个的同学可以去百度一下。https://ngrok.com为ngrok官网。要进行微信开发,内网映射工具是不可少。毕竟,我们程序员进行开发,要测试开发的产品是否能用,都先在自己的电脑跑一下。但由于ngrok的服务器在外国的,鉴于天朝的墙太高,访问可能不稳定。所以我推荐的是国内的natapp,免费和收费的都有,服务毕竟稳定可靠,只不过要想自定义二级域名就得交费成为VIP咯。

第二步,配置JS接口安全域名。登录要进行开发的公众号,点击公众设置--->功能设置。设置JS接口安全域名,要注意三点:①填写域名前面不需加上http://,例如你的域名是http://test.com,直接填写test.com即可;②域名默认80端口,只支持80和443端口,所以域名后面不能添加端口号。③该域名为你调用微信JS-SDK接口域名。

第三步,引用JS文件。在需要调用JS接口的页面引入http://res.wx.qq.com/open/js/jweixin-1.0.0.js 。


第四步,通过config接口注入权限验证配置 。具体参数有什么用处,在截图都有注释讲解。其中jsApiList为我们要使用的接口,我在下面共引用了五个接口,分别为微信好友分享、QQ好友分享、腾讯微博分享、QQ空间分享和朋友圈分享。调用的都是分享的接口。至于其他接口列表,可以去微信开发文档那浏览一下。这里就不详说。

        第五步,在服务器生成相关参数传到调用JS-SDK页面,完成授权。这是最重要的一步。如上图所示,appId,timestamp,nonceStr,signature都为必填参数。下面我将会详细说说如何生成这些参数并传回页面。

appId为开发的微信公众号的AppID(应用ID),我们可以在登录微信公众号,在开发选项中点击基本配置来查看。

timestamp为系统生成的时间戳。


nonceStr为服务器随机生成的字符串。



signature为微信JS-SDK使用权限算法。在生成signature之前,我们要拿到jsapi_ticket。官方文档是这样解释的:


我们要注意三个地方。jsapi_ticket要缓存两个小时,每过两个小时,向微信那边请求一次。获取jsapi_ticket要通过access_token。那么我们该如何获取access_token呢?


从文档可以看出,access_token需要AppID和AppSercet两个参数。而且access_token和jsapi_ticket一样,有效期皆为两小时。这就要求我们服务器要缓存access_token和jsapi_ticket,当有效期一过,就重新请求。有的人采用是用数据库来存取这两个参数,而我采用的是用Quartz定时器。关于Quartz定时器的使用,可浏览我上篇博客《SSH与Quartz集成》,里面有关于Quartz的使用方法。

AppSercet可在与APPID同一页面获取。接下来,调用接口,获取access_token。



接下来,我们用access_token去获取jsapi_ticket。


获取jsapi_ticket,就可以进行生成签名。在此之前,先看一下官方文档的签名算法。



用代码实现。


第六步,传生成的参数给网页。



第七步,调用已授权的JS接口。


第八步,利用微信Web开发者工具调试,看看是否授权成功。(微信web开发者工具可在微信开发下载)。



2019-10-25 23:18:59 wxwsfl 阅读数 46

今天编写一个网页授权接口开发的实例,希望对大家的工作有所帮助

微信公众号开发文档地址:https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Overview.html

网页授权文档地址:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html

准备工作:

 微信平台测试号配置:

找到网页服务 --  网页账号 -- 授权接口的配置

点击修改, 添加内网映射的域名

注意, 前方有坑,请注意躲避----------此处的填写的是域名,不是URL,无需添加 http:// 协议

 

公众号配置完成后,开始上代码:

1.创建实体类

/**
 * @author:         diego
 * @date:           2019/2/20 15:57
 * @description:    微信常用属性定义
 * @version:        1.0
 */
public class WeChat {

    //自定义Token
    private String token = "token";

    //微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
    private String signature;

    //时间戳
    private String timestamp;

    //随机数
    private String nonce;

    //随机字符串
    private String echostr;

    //用户同意授权返回code
    private String code;

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }

    public String getSignature() {
        return signature;
    }

    public void setSignature(String signature) {
        this.signature = signature;
    }

    public String getTimestamp() {
        return timestamp;
    }

    public void setTimestamp(String timestamp) {
        this.timestamp = timestamp;
    }

    public String getNonce() {
        return nonce;
    }

    public void setNonce(String nonce) {
        this.nonce = nonce;
    }

    public String getEchostr() {
        return echostr;
    }

    public void setEchostr(String echostr) {
        this.echostr = echostr;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }
}

2.常量定义


public class WeChatConstDefine {

    /*------------------------------------------- 常量 -------------------------------------------*/

    public static final Boolean TRUE = true;

    public static final Boolean FALSE = false;

    public static final String GET = "GET";

    public static final String POST = "POST";

    public static final String ENCODE_UTF_8 = "UTF-8";

    public static final String ENCODE_GBK = "GBK";


    /*---------------------------------------- 微信请求地址 ----------------------------------------*/

    //用户同意授权,获取code
    public static final String authorize = "https://open.weixin.qq.com/connect/oauth2/authorize";

    //通过code换取网页授权access_token
    public static final String access_token = "https://api.weixin.qq.com/sns/oauth2/access_token";

    //刷新access_token(如果需要)
    public static final String refresh_token = "https://api.weixin.qq.com/sns/oauth2/refresh_token";

    //拉取用户信息(需scope为 snsapi_userinfo)
    public static final String userInfo = "https://api.weixin.qq.com/sns/userinfo";

    //检验授权凭证(access_token)是否有效
    public static final String auth = "https://api.weixin.qq.com/sns/auth";

    //重定向后缀参数
    public static final String weChat_redirect = "#wechat_redirect";

}

3.自定义异常类

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class MyException extends RuntimeException {


    public MyException(String message) {
        super(message);
        log.info("/************************My Exception************************/");
        log.info("");
        log.info("");
        log.info(message);
        log.info("");
        log.info("");
        log.info("/************************My Exception************************/");
    }

    public MyException(Exception e) {
        super(e);
        log.info("/************************My Exception************************/");
        log.info("");
        log.info("");
        log.info(e.getMessage());
        log.info("");
        log.info("");
        log.info("/************************My Exception************************/");
    }

    public MyException(String message, Exception e) {
        super(message, e);
        log.info("/************************My Exception************************/");
        log.info("");
        log.info("");
        log.info("My Message:" + message);
        log.info("System Message:" + e.getMessage());
        log.info("");
        log.info("");
        log.info("/************************My Exception************************/");
    }
}

4.编码-解码工具类

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;

/**
 * @author:         diego
 * @date:           2019/1/29 10:39
 * @description:    编码-解码工具类
 * @version:        1.0
 */
public class EncodeUtils {

	/**
	 * URL 编码
	 */
	public static String urlEncode(String url,String encode) {
		if(null == url || "".equals(url) || null == encode && "".equals(encode)){
			throw new MyException("The url or encode is not null.");
		}else{
			try {
				return URLEncoder.encode(url, WeChatConstDefine.ENCODE_UTF_8);
			} catch (UnsupportedEncodingException e) {
				throw new MyException(e);
			}
		}
	}

	/**
	 * URL 解码
	 */
	public static String urlDecode(String url,String encode) {
		if(null == url || "".equals(url) || null == encode && "".equals(encode)){
			throw new MyException("The url or encode is not null.");
		}else{
			try {
				return URLDecoder.decode(url, WeChatConstDefine.ENCODE_UTF_8);
			} catch (UnsupportedEncodingException e) {
				throw new MyException(e);
			}
		}
	}
}

5.http工具类

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Iterator;
import java.util.Map;

/**
 * @author:         diego
 * @date:           2019/1/29 10:39
 * @description:    Http请求工具类
 * @version:        1.0
 */
public class HttpConnectionUtils {

    public static HttpConnectionUtils getHttp() {
        return new HttpConnectionUtils();
    }


    // url发送请求
    public String sendRequest(String url, String method, Map<String, Object> map,String suffix) throws MyException{
        String result = "";
        if (null == url || url.equals("")) {
            throw new MyException("The url is null.");
        }else if (null == method || method.equals("")) {
            method = WeChatConstDefine.GET;
        }else{
            if(!WeChatConstDefine.GET.equals(method) && !WeChatConstDefine.POST.equals(method)){
                throw new MyException("request method is error. you only use 'POST' or 'GET'.");
            }else{
                if(WeChatConstDefine.GET.equals(method)){
                    return sendByGetMethod(url, map,suffix);
                }else if(WeChatConstDefine.POST.equals(method)){
                    HttpURLConnection connection = getConnection(url, WeChatConstDefine.POST);
                    return sendByPostMethod(url,connection, map,suffix);
                }
            }
        }
        return result;
    }


    // url 拼接 参数
    public String analyticParams(String url,Map<String,Object> map,String suffix) throws MyException{
        StringBuffer params = new StringBuffer(url+"?");
        if(map != null && map.size() > 0){
            Iterator<String> it = map.keySet().iterator();
            do{
                String param = it.next();
                if(it.hasNext()){
                    params.append(param + "=" + map.get(param) + "&");
                }else{
                    params.append(param + "=" + map.get(param));
                }
            }while (it.hasNext());
        }else{
            throw new MyException("url parameter resolution failed.");
        }

        String httpUrl = "";
        if(null != suffix){
            httpUrl = params.toString() + suffix;
        }else{
            httpUrl = params.toString();
        }
        return httpUrl;
    }


    // get HttpURLConnection
    private HttpURLConnection getConnection(String urlString, String method) throws MyException {
        URL url = null;
        HttpURLConnection result = null;
        try {
            url = new URL(urlString);
            result = (HttpURLConnection) url.openConnection();
            result.setRequestMethod(method);
        } catch (Exception e) {
            throw new MyException(e);
        }

        if (null == result) {
            throw new MyException("HttpURLConnection is null.");
        }
        return result;
    }


    // get request method
    private String sendByGetMethod(String url, Map<String, Object> params,String suffix) throws MyException {
        // 拼接url
        String urlParams = this.analyticParams(url,params,suffix);

        HttpURLConnection connection = this.getConnection(urlParams, WeChatConstDefine.GET);
        try {
            connection.connect();
        } catch (IOException e) {
            throw new MyException(e);
        }

        return  getResponseResult(connection);
    }


    // post request method
    private String sendByPostMethod(String url,HttpURLConnection connection, Map<String, Object> params,String suffix) throws MyException {
        // 初始化post请求属性
        this.initPostProperties(connection);
        // 发送参数
        this.sendParams(url,connection, params,suffix);

        return  getResponseResult(connection);
    }


    // 初始化post请求属性
    private void initPostProperties(HttpURLConnection connection) {
        connection.setUseCaches(false);
        connection.setInstanceFollowRedirects(true);
        connection.setDoOutput(true);
        connection.setDoInput(true);
        connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
    }


    // 发送参数
    private void sendParams(String url,HttpURLConnection connection, Map<String, Object> params,String suffix) throws MyException {
        DataOutputStream out = null;
        try {
            connection.connect();
            out = new DataOutputStream(connection.getOutputStream());
            String stringParam = this.analyticParams(url,params,suffix);
            out.writeBytes(stringParam);
            out.flush();
        } catch (IOException e) {
            throw new MyException("Send param error : " + e);
        } finally {
            close(out);
        }
    }


    // 获取服务器返回结果
    private String getResponseResult(HttpURLConnection connection) throws MyException {
        StringBuilder result = new StringBuilder();
        InputStream in = null;
        try {
            in = connection.getInputStream();
            byte[] buff = new byte[1024];
            int flag = -1;

            while ((flag = in.read(buff)) != -1) {
                result.append(new String(buff, 0, flag, WeChatConstDefine.ENCODE_UTF_8));
            }
            in.close();
        } catch (IOException e) {
            throw new MyException(e);
        } finally {
            close(in);
        }
        return result.toString();
    }


    // close input stream
    private void close(InputStream in) {
        if (null != in) {
            try {
                in.close();
            } catch (IOException e) {
                throw new MyException(e);
            }
        }
    }


    // close output stream
    private void close(OutputStream out) {
        if (null != out) {
            try {
                out.close();
            } catch (IOException e) {
                throw new MyException(e);
            }
        }
    }

}

6.QR码工具类

import com.google.zxing.*;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Hashtable;


/**
 * @author:         diego
 * @date:           2019/1/29 10:42
 * @description:    二维码工具类
 * @version:        1.0
 */
public class QRCodeUtils {

    private static final String CHARSET = "utf-8";
    private static final String FORMAT_NAME = "JPG";
    // 二维码尺寸
    private static final int QRCODE_SIZE = 300;
    // LOGO宽度
    private static final int WIDTH = 60;
    // LOGO高度
    private static final int HEIGHT = 60;

    /** 生成二维码 */
    private static BufferedImage createImage(String content,InputStream logo)throws Exception {
        Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
        hints.put(EncodeHintType.MARGIN, 1);
        BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE,QRCODE_SIZE, QRCODE_SIZE, hints);
        int width = bitMatrix.getWidth();
        int height = bitMatrix.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
            }
        }
        // 插入图片
        QRCodeUtils.insertImage(image, logo, true);
        return image;
    }


    /** 在二维码中间插入logo图片 */
    private static void insertImage(BufferedImage source, InputStream logo, boolean needCompress)throws Exception {
        if(logo==null)return;
        Image src = ImageIO.read(logo);
        int width = src.getWidth(null);
        int height = src.getHeight(null);
        if (needCompress) { // 压缩LOGO
            if (width > WIDTH) {
                width = WIDTH;
            }
            if (height > HEIGHT) {
                height = HEIGHT;
            }
            Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH);
            BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics g = tag.getGraphics();
            g.drawImage(image, 0, 0, null); // 绘制缩小后的图
            g.dispose();
            src = image;
        }
        // 插入LOGO
        Graphics2D graph = source.createGraphics();
        int x = (QRCODE_SIZE - width) / 2;
        int y = (QRCODE_SIZE - height) / 2;
        graph.drawImage(src, x, y, width, height, null);
        Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
        graph.setStroke(new BasicStroke(3f));
        graph.draw(shape);
        graph.dispose();
    }


    /**
     * 生成二维码
     * @param content 文本内容
     * @param logo 内嵌图标
     * @param output 输出流
     * @throws Exception
     */
    public static void encode(String content, InputStream logo, OutputStream output) throws Exception {
        BufferedImage image = QRCodeUtils.createImage(content, logo);
        ImageIO.write(image, FORMAT_NAME, output);
    }
    public static void encode(String content, InputStream logo, File out)throws Exception {
        if(!out.getParentFile().exists()){
            out.getParentFile().mkdirs();
        }
        out.createNewFile();
        QRCodeUtils.encode(content, logo, new FileOutputStream(out));
    }
    public static void encode(String content, File logo, OutputStream out)throws Exception {
        if(logo.exists()){
            QRCodeUtils.encode(content, new FileInputStream(logo), out);
        }else{
            QRCodeUtils.encode(content,(InputStream)null, out);
        }
    }
    public static void encode(String content, File logo, File out)throws Exception {
        if(!out.getParentFile().exists()){
            out.getParentFile().mkdirs();
        }
        out.createNewFile();
        if(logo.exists()){
            QRCodeUtils.encode(content, new FileInputStream(logo), out);
        }else{
            QRCodeUtils.encode(content,(InputStream)null, out);
        }
    }
    public static void encode(String content, InputStream logo, String out)throws Exception {
        QRCodeUtils.encode(content, logo, new File(out));
    }
    public static void encode(String content, String logo, String out) throws Exception {
        QRCodeUtils.encode(content, new File(logo), new File(out));
    }
    public static void encode(String content, OutputStream out) throws Exception {
        QRCodeUtils.encode(content, (InputStream)null, out);
    }
    public static void encode(String content, String out)throws Exception {
        QRCodeUtils.encode(content,(InputStream)null, new File(out));
    }




    /**
     * 解析二维码,input是二维码图片流
     */
    public static String decode(InputStream input) throws Exception {
        BufferedImage image = ImageIO.read(input);
        if (image == null) {
            return null;
        }
        BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
        Result result;
        Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
        hints.put(DecodeHintType.CHARACTER_SET, CHARSET);
        result = new MultiFormatReader().decode(bitmap, hints);
        String resultStr = result.getText();
        return resultStr;
    }
    /**
     * 解析二维码,file是二维码图片
     */
    public static String decode(File file) throws Exception{
        return decode(new FileInputStream(file));
    }
    /**
     * 解析二维码,path是二维码图片路径
     */
    public static String decode(String path) throws Exception {
        return QRCodeUtils.decode(new File(path));
    }

    private static class BufferedImageLuminanceSource extends LuminanceSource {
        private final BufferedImage image;
        private final int left;
        private final int top;

        public BufferedImageLuminanceSource(BufferedImage image) {
            this(image, 0, 0, image.getWidth(), image.getHeight());
        }

        public BufferedImageLuminanceSource(BufferedImage image, int left, int top, int width,
                                            int height) {
            super(width, height);

            int sourceWidth = image.getWidth();
            int sourceHeight = image.getHeight();
            if (left + width > sourceWidth || top + height > sourceHeight) {
                throw new IllegalArgumentException("Crop rectangle does not fit within image data.");
            }

            for (int y = top; y < top + height; y++) {
                for (int x = left; x < left + width; x++) {
                    if ((image.getRGB(x, y) & 0xFF000000) == 0) {
                        image.setRGB(x, y, 0xFFFFFFFF); // = white
                    }
                }
            }

            this.image = new BufferedImage(sourceWidth, sourceHeight, BufferedImage.TYPE_BYTE_GRAY);
            this.image.getGraphics().drawImage(image, 0, 0, null);
            this.left = left;
            this.top = top;
        }

        public byte[] getRow(int y, byte[] row) {
            if (y < 0 || y >= getHeight()) {
                throw new IllegalArgumentException("Requested row is outside the image: " + y);
            }
            int width = getWidth();
            if (row == null || row.length < width) {
                row = new byte[width];
            }
            image.getRaster().getDataElements(left, top + y, width, 1, row);
            return row;
        }

        public byte[] getMatrix() {
            int width = getWidth();
            int height = getHeight();
            int area = width * height;
            byte[] matrix = new byte[area];
            image.getRaster().getDataElements(left, top, width, height, matrix);
            return matrix;
        }

        public boolean isCropSupported() {
            return true;
        }

        public LuminanceSource crop(int left, int top, int width, int height) {
            return new BufferedImageLuminanceSource(image, this.left + left, this.top + top, width,
                    height);
        }

        public boolean isRotateSupported() {
            return true;
        }

        public LuminanceSource rotateCounterClockwise() {
            int sourceWidth = image.getWidth();
            int sourceHeight = image.getHeight();
            AffineTransform transform = new AffineTransform(0.0, -1.0, 1.0, 0.0, 0.0, sourceWidth);
            BufferedImage rotatedImage = new BufferedImage(sourceHeight, sourceWidth,
                    BufferedImage.TYPE_BYTE_GRAY);
            Graphics2D g = rotatedImage.createGraphics();
            g.drawImage(image, transform, null);
            g.dispose();
            int width = getWidth();
            return new BufferedImageLuminanceSource(rotatedImage, top,
                    sourceWidth - (left + width), getHeight(), width);
        }
    }


    public static void main(String[] args) throws Exception {
        QRCodeUtils.encode("https://baike.xsoftlab.net","", "D:/abc/qr/1.jpg");
        String data = QRCodeUtils.decode("D:/abc/qr/1.jpg");
        System.out.println(data);
    }
}

7.请求接口

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class WeChatController {

    /**
     * 授权后重定向的回调链接地址
     */
    @RequestMapping("/index")
    @ResponseBody
    public String getCode(WeChat weChat){

        /* 根据需求编写逻辑代码 */

        return weChat.getCode();
    }
}

打死都不会遗漏的pom:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>


        <!-- QRCode二维码工具包 -->
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>core</artifactId>
            <version>3.3.3</version>
        </dependency>

        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>javase</artifactId>
            <version>3.3.3</version>
        </dependency>

        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>

测试:

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 *
 * @author: lsg
 * @create: 2019/10/25 13:33
 */
public class WeChatTest {

    public static void main(String[] args) {
        //参数详情请查看接口文档
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("appid", "测试账号中的appID");
        map.put("response_type", "code");
        map.put("scope", "snsapi_userinfo");
        map.put("state", "ABC");
        map.put("redirect_uri", EncodeUtils.urlEncode("http://内网穿透的域名/index", WeChatConstDefine.ENCODE_UTF_8));

        //用户通过扫码获取授权信息
        String url = HttpConnectionUtils.getHttp().analyticParams(WeChatConstDefine.authorize, map, WeChatConstDefine.weChat_redirect);
        try {
            System.out.println(url);
            //二维码
            QRCodeUtils.encode(url, "D:/WeChat.jpg");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

执行main方法,控制台输出URL,在微信中访问此URL或者找到D盘下 WeChat.jpg 文件进行扫码
 

 

点击允许,微信会调用redirect_uri定义的URL,访问了Controller中的 index 接口,页面输出用户授权 code。

 

此处预留一下 个人logo 位置,以后填充................

 

2015-06-03 11:30:42 wyx100 阅读数 1651

持续更新中

BAE java开发mysql数据库 图文教程

BAE java语言开发mysql源代码下载:


目前微信开发、BAE开发、java开发、mysql开发的教程很多,但是没有一个详细的介绍基于BAE平台、java语言和mysql数据库的微信开发教程。所以写了该教程,希望能给大家一点启发。

教程分为:

1.申请BAE账户;

2.在BAE平台建立web服务器应用;

3.在BAE平台建立mysql数据库服务器应用;

4.使用eclipse开发基于BAE平台的处理微信消息的web服务器系统;

5.web系统调用mysql数据库。


一.申请BAE账户

申请账户:http://bce.baidu.com/product/bae.html

 

本文档基于BAE3.0,

BAE2.0已下线;

为什么要迁移到3.0说明http://godbae.duapp.com/?p=691#more-691

 

二.添加应用部署

http://console.bce.baidu.com/bae/#/bae/app/list

1.      建立一个应用服务,本文档使用tomcat。基于java语言开发。

 

注意:

1.      有些服务需要给BAE充值,充值需要储蓄卡,信用卡暂不支持;

2.      部署应用收费需要0.4元/天;

3.      Mysql服务器,BAE提供一个免费的;

4.      BAE中的数据库不能远程连接,只能是BAE中的应用调用。

 

 

 

 

 

2.      建立BAE的mysql数据库

 

二.               BAE文档

开发前,仔细研究BAE提供的文档。

目前网上很多资料是基于BAE2.0的,根据该资料在BAE3.0上开发,会遇到很多问题,如果想开发顺利,需要仔细研究BAE3.0官方文档。

BAE3.0是BAE2.0的升级版,很多流程做了改动和优化,升级较大,比BAE2.0好用很多。

注意:开发项目前,请仔细研究项目文档。例如,开发java,开发前请先阅读官方提供的开发文档,事半功倍!这是程序猿/媛的好习惯。

 

产品文档

http://bce.baidu.com/doc/index.html

 

 

SDK工具

http://bce.baidu.com/doc/SDKTool/index.html

 

 

三.               搭建开发环境

1.jdk

推荐Jdk1.7及以上版本

Jdk1.6也可以正常使用

 

Jdk配置图文教程:

http://jingyan.baidu.com/article/6dad5075d1dc40a123e36ea3.html

 

jdk下载地址

http://pan.baidu.com/s/1jGpGRcU

 

 

 

3.      eclipse

 

基于BAE开发Eclipse(已经完成各种BAE和SVN配置)下载地址

http://pan.baidu.com/s/1bnlR0bP

 

 

四.               开发流程

1.      建立工程

2.      添加代码

3.      添加jar包

4.      生成war

5.      更新BAE的svn

6.      提交BAE的svn服务器

7.      在BAE 部署项目

8.      测试

输入网址

图示测试效果

 

 

五.               关键代码


没有更多推荐了,返回首页