Implementation of JS SDK Based on Vue Wechat Public Number

Keywords: Vue SDK PHP curl

Get ready

First of all, we should see clearly the authorization of Wechat Web pages. Official documents Every step, then my demo is a small project based on vue, backstage is the Slim framework of php. Since the official documents are so complete that I can hardly read them at the time of development, I will try to say as little as possible in this article and only record the important steps.

In fact, it doesn't matter much if v is not vue. It's just attracting traffic. )

As for the public number configuration, the configuration of the domain name of the page authorization callback is ignored here.

Then it will be divided into two parts. First, the realization of Web authorization is used to obtain user information, and then the integration of JS SDK and PHP on Vue is realized. The intermediate link between the two parts is access_token obtained in the former part, which is needed in the latter part.

JS SDK Web Page Authorization

Step 1: Implement user authorization page and get code

The purpose of the first step is to get the code, and what is the use of code?

As shown above is a simple authorization flow chart, for users, the entry action is our application home page, the main function is to jump to the authorization page of forgiveness color, while the actual application is to bring redirect_uri when authorization request. The following code: Server:

$app->get('/',function($req,$res,$args){
	$url = urlencode('http://your.url/app'; // This is the destination I want to jump to and need URL coding.
	return $res->withStatus(302)->withHeader('Location', "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APP_ID&redirect_uri=$url&response_type=code&scope=snsapi_userinfo&state=done#wechat_redirect");
});

Among them, APP_ID and redirect_uri need to be changed. Then it can be tested with the Wechat Developer Tool.

Eh? The adaptation of official tools. ] After confirming the authorization, you can jump to the redirect_uri page we set up.

Step 2: Exchange code for web authorization access_token

Code is actually equivalent to a queuing chip, and access_token really opens the door to the relevant interface. So in the application page action, we have to exchange code for access_token first.

$app->get('/app',function($req,$res,$args){
	//1. Determine whether token expires
	if ( time() > $_SESSION['expires_time'] ){
		//2. Get access_token
		$code = $req->getParam('code');
		$tokendata = getToken($code);
		//3. Save in session
		$_SESSION['access_token'] = $tokendata['access_token'];
		$_SESSION['expires_time'] = $tokendata['expires_in'] + time();
		$_SESSION['openid'] = $tokendata['openid'];
	}

	//4. Getting User Information
	$userdata = getUserInfo();

	if (isset($userdata['openid'])){
		//Save or update user information
		saveUser($userdata);
	}

	return $this->renderer->render($res, 'index.html', $args);
});

//Get token
function getToken($code){
	$url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APP_ID&secret=APP_SECRET&code=$code&grant_type=authorization_code";

	return json_decode(get($url),true);
}

//Getting User Information
function getUserInfo(){
	//get userdata
	$token = $_SESSION['access_token'];
	$openid = $_SESSION['openid'];
	$url = "https://api.weixin.qq.com/sns/userinfo?access_token=$token&openid=$openid&lang=zh_CH";

	return json_decode(get($url),true);
}

Because frequent requests for access_token will be rejected by the wechat side, it is important to keep access_token on the server side when saving sensitive information. To avoid frequent requests for access_token, record the current timeout expires_in+time() as a check item (usually 7200 seconds) the next time you enter the page. Then Wechat also provides a refresh_token to refresh access_token when it expires. The expiration time of refresh_token is 30 days, but I haven't done any applications that users want to use for 30 days. So the refresh_token mechanism is ignored here. For access_token, it shouldn't be too frequent for every user to request once every two hours (of course, the scenario of a moderate number of users).

And then it's getting the user's information. There's nothing to say, that's it.

Integration of JS SDK and PHP on Vue.js

Step 1: The server generates configuration information to be injected into the front end

If you want to understand the meaning of each place, you can go to the document, where you can directly drop the code and use it.

//Generate configuration information needed to be injected using Wechat JS-SDK, parameter $url (url of the current address)
function getConfig($url){
    $array = [];
    $array['debug'] = true;
    $array['appId'] = APP_ID; //Remember to change APP_ID
    //Time stamp for signature generation
    $time = time();
    $array['timestamp'] = $time;
    //Random strings for signature
    $nonceStr = nonceStr();
    $array['nonceStr'] = $nonceStr;
    $array['signature'] = signature($time,$url,$nonceStr);
    //Set up the js interface you need to use
    $array['jsApiList'] = ['checkJsApi','onMenuShareTimeline',
                    'onMenuShareAppMessage',
                    'chooseImage']; //The interface here refers to the article
    //Return configuration information
    return json_encode($array);
 }

 //Generate signature function, parameter $time (time of signature generation), $url (url of web page), $nonceStr (random string)
//Because when we inject configuration information into a web page, the time to generate signatures and random strings must be the same as when injected.
//So when I generate signatures, I pass a parameter to achieve the same timestamp, and random strings.
function signature($time,$url,$nonceStr){
    //Stitching strings
    $string = 'jsapi_ticket='.getJsApiTicket().'&noncestr='.$nonceStr.'&timestamp='.$time.'&url='.$url;
    //Generate signature
    $string = sha1($string);
    return $string;
}

//Generate random strings
function nonceStr(){
    //Define a string
    $chars='ABCDFFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz';
    //Current timestamp
    $time = time();
    //Get random strings from this string
    $chars = $chars.$time;
    //Disturbing strings
    $chars = str_shuffle($chars);
    return substr($chars,0,16);
}

//Get JSapi ticket
function getJsApiTicket(){
	if ( time() > $_SESSION['ticket_expires_time'] ){
		$access_token = $_SESSION['access_token'];
		$url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=$access_token&type=jsapi";
		$ticketData = json_decode(get($url),ture);
		$_SESSION['ticket_expires_time'] = time() + $ticketData['expires_in'];
		$_SESSION['js_ticket'] = $ticketData['ticket'];
	}

	return $_SESSION['js_ticket'];
}

Then prepare an action to return config json.

$app->get('/config',function($req,$res,$args){
	return getConfig('http://your.url');
});

Step 2: Introducing wechat-js-sdk library into the front end

A direct command:

npm install -S weixin-js-sdk

Then introduce the *. vue page to use

import wx from 'wexin-js-sdk'

Step 2: Front-end Vue requests injection of configuration information

First, the framework is Vue.js, and then the request library is axios.

	...
	created(){
		//Get configuration
	    var url = 'http://your.url/config'
	    var _this = this;
	    //Request injection configuration
	    axios.post(url, {})
	      .then(response => {
	          var data = response.data;
	          	//Injection into wx
	            wx.config({
		                appId: data.wechat_appid,
		                // debug: true,
		                timestamp: data.timestamp,
		                nonceStr: data.nonceStr,
		                signature: data.signature,
		                jsApiList: data.jsApiList
	            });
	            wx.ready(function(){
	            	//Configuration Sharing Interface
		              var shareData = {
		                title: 'title',
		                link:'http://your.link',
		                imgUrl:'',
		                success:function(){

		                },
		                cancel:function(){

		                }
		              }
		              wx.onMenuShareTimeline(sdata);
		              wx.onMenuShareAppMessage(sdata);
	            });
	      })
	      .catch(e => {
	        console.log(e);
	      })
	  },
  ...

So far, the whole journey has been completed, the specific code can be used out of the box.

appendix

Packaging Method of Post and Get curl

 /**
 * @param $url
 * @param array  $post_data
 *
 * @return string
 */
function post($url,$post_data = array()){
    try {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        // post data
        curl_setopt($ch, CURLOPT_POST, 1);
        // The variable of post
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data));
        $output = curl_exec($ch);
        $curl_errno = curl_errno($ch);

        curl_close($ch);

        if ($curl_errno > 0) {
            return json_encode(array(
                'ResultCode' => 0,
                'Msg' => 'Curl error: error code ('.$curl_errno.')'
                ));
        }

        return $output;

    }catch(Exception $e){
        print 'Error:'.$e->getMessage();   
        exit();
    }
}

/**
 * @param $url
 *
 * @return string
 */
function get($url){
    try {

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        $output = curl_exec($ch);
        $curl_errno = curl_errno($ch);
        curl_close($ch);

        if ($curl_errno > 0) {
            return json_encode(array(
                'ResultCode' => 0,
                'Msg' => 'Curl error: error code ('.$curl_errno.')'
                ));
        }

        return $output;
    }catch(Exception $e){
        print $e->getMessage();   
        exit();
    }
}

Posted by Gabriel_Haukness on Wed, 29 May 2019 04:28:29 -0700