This commit is contained in:
gongfuxiang 2019-01-02 01:55:03 +08:00
parent 3902f2ae2d
commit 8d1f68a61c
9 changed files with 355 additions and 68 deletions

View File

@ -102,6 +102,45 @@ class User extends Common
}
}
/**
* 微信小程序获取用户授权
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2018-11-06
* @desc description
*/
public function WechatUserAuth()
{
$result = (new \base\Wechat('111', '222'))->GetAuthSessionKey(input('authcode'));
if($result !== false)
{
return DataReturn('授权登录成功', 0, $result);
}
return DataReturn('授权登录失败', -100);
}
/**
* 微信小程序获取用户信息
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2018-11-06
* @desc description
*/
public function WechatUserInfo()
{
$result = (new \base\Wechat('100', '200'))->DecryptData(R('encrypted_data'), input('iv'), input('openid'));
if(is_array($result))
{
$result['openid'] = $result['openId'];
$result['referrer']= isset($this->data_post['referrer']) ? intval($this->data_post['referrer']) : 0;
return UserService::AuthUserProgram($result, 'wechat_openid');
}
return DataReturn('获取用户信息失败', -100);
}
/**
* 百度小程序获取用户信息
* @author Devil

238
extend/base/Wechat.php Normal file
View File

@ -0,0 +1,238 @@
<?php
// +----------------------------------------------------------------------
// | ShopXO 国内领先企业级B2C免费开源电商系统
// +----------------------------------------------------------------------
// | Copyright (c) 2011~2018 http://shopxo.net All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: Devil
// +----------------------------------------------------------------------
namespace base;
/**
* 微信驱动
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2018-06-28
* @desc 支持所有文件存储到硬盘
*/
class Wechat
{
// appid
private $_appid;
// appsecret
private $_appsecret;
/**
* [__construct 构造方法]
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @datetime 2017-12-30T18:04:05+0800
* @param [string] $app_id [应用appid]
* @param [string] $app_secret [应用密钥]
*/
public function __construct($app_id, $app_secret)
{
$this->_appid = $app_id;
$this->_appsecret = $app_secret;
}
/**
* [DecryptData 检验数据的真实性,并且获取解密后的明文]
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @datetime 2017-12-30T18:20:53+0800
* @param [string] $encrypted_data [加密的用户数据]
* @param [string] $iv [与用户数据一同返回的初始向量]
* @param [string] $openid [解密后的原文]
* @return [array|string] [成功返回用户信息数组, 失败返回错误信息]
*/
public function DecryptData($encrypted_data, $iv, $openid)
{
// 登录授权session
$login_key = 'wechat_user_login_'.$openid;
$session_data = GS($login_key);
if($session_data === false)
{
return 'session key不存在';
}
$aes_key = base64_decode($session_data['session_key']);
if(strlen($iv) != 24)
{
return 'iv长度错误';
}
$aes_iv = base64_decode($iv);
$aes_cipher = base64_decode($encrypted_data);
$result = openssl_decrypt($aes_cipher, "AES-128-CBC", $aes_key, 1, $aes_iv);
$data = json_decode($result, true);
if($data == NULL)
{
return '数据解密失败';
}
if($data['watermark']['appid'] != $this->_appid )
{
return 'appid不匹配';
}
// 缓存存储
$data_key = 'wechat_user_info_'.$openid;
SS($data_key, $data);
return $data;
}
/**
* [GetAuthSessionKey 根据授权code获取 session_key openid]
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @datetime 2017-12-30T18:20:53+0800
* @param [string] $authcode [用户授权码]
* @return [string|boolean] [失败false, 成功返回appid|]
*/
public function GetAuthSessionKey($authcode)
{
// 请求获取session_key
$url = 'https://api.weixin.qq.com/sns/jscode2session?appid='.$this->_appid.'&secret='.$this->_appsecret.'&js_code='.$authcode.'&grant_type=authorization_code';
$result = $this->HttpRequestGet($url);
if(!empty($result['openid']))
{
// 从缓存获取用户信息
$key = 'wechat_user_login_'.$result['openid'];
// 缓存存储
SS($key, $result);
return $result['openid'];
}
return false;
}
/**
* [MiniQrCodeCreate 二维码创建]
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @datetime 2018-01-02T19:53:10+0800
* @param [array] $params [输入参数]
* @return [string] [成功返回文件流, 失败则空]
*/
public function MiniQrCodeCreate($params)
{
// 参数校验
if(empty($params['path']))
{
return '页面地址不能为空';
}
$params['width'] = empty($params['width']) ? 1000 : intval($params['width']);
// 获取access_token
$access_token = $this->GetMiniAccessToken();
if($access_token === false)
{
return '';
}
// 网络请求
$url = 'https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token='.$access_token;
$data = [
'path' => $params['path'],
'width' => $params['width'],
];
return $this->HttpRequestPost($url, json_encode($data), false);
}
/**
* [GetMiniAccessToken 获取access_token]
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @datetime 2018-01-02T19:53:42+0800
*/
private function GetMiniAccessToken()
{
// 缓存key
$key = $this->_appid.'_access_token';
$result = GS($key);
if($result !== false)
{
if($result['expires_in'] > time())
{
return $result['access_token'];
}
}
// 网络请求
$url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.$this->_appid.'&secret='.$this->_appsecret;
$result = $this->HttpRequestGet($url);
if(!empty($result['access_token']))
{
// 缓存存储
$result['expires_in'] += time();
SS($key, $result);
return $result['access_token'];
}
return false;
}
/**
* [HttpRequestGet get请求]
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @datetime 2018-01-03T19:21:38+0800
* @param [string] $url [url地址]
* @return [array] [返回数据]
*/
private function HttpRequestGet($url)
{
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_TIMEOUT, 500);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_URL, $url);
$res = curl_exec($curl);
curl_close($curl);
return json_decode($res, true);
}
/**
* [HttpRequestPost curl模拟post]
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @datetime 2017-09-25T09:10:46+0800
* @param [string] $url [请求地址]
* @param [array] $data [发送的post数据]
* @param [array] $is_parsing [是否需要解析数据]
* @return [array] [返回的数据]
*/
private function HttpRequestPost($url, $data, $is_parsing = true)
{
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_TIMEOUT, 500);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
curl_setopt($curl, CURLOPT_POST, true);
$res = curl_exec($curl);
if($is_parsing === true)
{
return json_decode($reponse, true);
}
return $res;
}
}
?>

View File

@ -205,18 +205,6 @@ App({
}
},
/**
* 获取本系统用户信息
*/
GetMyUserInfo() {
var user = this.GetUserCacheInfo();
if (user == false) {
return null;
} else {
return user.my_user || null;
}
},
/**
* 从缓存获取用户信息
*/
@ -225,9 +213,6 @@ App({
if ((user || null) == null) {
return false;
}
if ((user.my_user || null) == null) {
user.my_user = null;
}
return user;
},
@ -258,17 +243,21 @@ App({
// 请求授权接口
wx.getSetting({
success(res) {
console.log('app.js 授权部分');
wx.navigateTo({
url: "/pages/login/login"
});
if (!res.authSetting['scope.userInfo']) {
wx.authorize({
scope: 'scope.userInfo',
success() {
$this.user_auth_login(object, method);
},
fail: (e) => {
wx.hideLoading();
$this.showToast('授权失败');
}
});
// wx.authorize({
// scope: 'scope.userInfo',
// success() {
// $this.user_auth_login(object, method);
// },
// fail: (e) => {
// wx.hideLoading();
// $this.showToast('授权失败');
// }
// });
} else {
$this.user_auth_login(object, method);
}
@ -314,7 +303,7 @@ App({
success: (res) => {
if (res.code) {
wx.request({
url: $this.get_request_url('GetWechatUserLogin', 'User'),
url: $this.get_request_url('WechatUserAuth', 'user'),
method: 'POST',
data: { authcode: res.code },
dataType: 'json',
@ -358,7 +347,7 @@ App({
success: function (res) {
// 远程解密数据
wx.request({
url: $this.get_request_url('GetWechatUserInfo', 'User'),
url: $this.get_request_url('WechatUserInfo', 'user'),
method: 'POST',
data: { encrypted_data: res.encryptedData, iv: res.iv, openid: openid },
dataType: 'json',

View File

@ -1,8 +1,8 @@
{
"pages": [
"pages": ["pages/cart/cart",
"pages/index/index",
"pages/goods-category/goods-category",
"pages/cart/cart",
"pages/user/user",
"pages/web-view/web-view",
"pages/login/login",

View File

@ -1,7 +1,5 @@
{
"enablePullDownRefresh": true,
"usingComponents": {
"list-item": "mini-antui/es/list/list-item/index",
"swipe-action": "mini-antui/es/swipe-action/index"
}
}

View File

@ -1,41 +1,39 @@
<view wx:if="{{data_list.length > 0}}" class="page">
<view wx:for="{{data_list}}" class="goods-item oh bg-white">
<swipe-action index="{{index}}" restore="{{swipe_index === null || swipe_index !== index}}" right="{{item.right}}" onRightItemClick="right_item_event" onSwipeStart="swipe_start_event" extra="{{index}}">
<!-- 选择 -->
<view bindtap="selectedt_event" data-type="node" data-index="{{index}}" class="fl selected">
<image wx:if="{{(item.selected || false)}}" class="icon" src="/images/default-select-active-icon.png" mode="widthFix" />
<image wx:else class="icon" src="/images/default-select-icon.png" mode="widthFix" />
<view wx:for="{{data_list}}" wx:key="key" class="goods-item oh bg-white">
<!-- 选择 -->
<view bindtap="selectedt_event" data-type="node" data-index="{{index}}" class="fl selected">
<image wx:if="{{(item.selected || false)}}" class="icon" src="/images/default-select-active-icon.png" mode="widthFix" />
<image wx:else class="icon" src="/images/default-select-icon.png" mode="widthFix" />
</view>
<view class="bg-white items">
<!-- 图片/链接 -->
<navigator url="/pages/goods-detail/goods-detail?goods_id={{item.goods_id}}">
<image class="goods-image fl" src="{{item.images}}" mode="aspectFill" />
</navigator>
<!-- 基础 -->
<view class="goods-base">
<view class="goods-title multi-text">{{item.title}}
</view>
<block wx:if="{{item.spec != null}}">
<view class="goods-attribute cr-888" wx:for="{{item.spec}}" wx:for-item="spec">{{spec.type}}:{{spec.value}}</view>
</block>
</view>
<!-- 数量 -->
<view class="number-content tc oh">
<view bindtap="goods_buy_number_event" class="number-submit tc cr-888 fl" data-index="{{index}}" data-type="0">-</view>
<input onBlur="goods_buy_number_blur" class="tc cr-888 fl" type="number" value="{{item.stock}}" data-index="{{index}}" />
<view bindtap="goods_buy_number_event" class="number-submit tc cr-888 fl" data-index="{{index}}" data-type="1">+</view>
</view>
<view class="bg-white items">
<!-- 图片/链接 -->
<navigator url="/pages/goods-detail/goods-detail?goods_id={{item.goods_id}}">
<image class="goods-image fl" src="{{item.images}}" mode="aspectFill" />
</navigator>
<!-- 基础 -->
<view class="goods-base">
<view class="goods-title multi-text">{{item.title}}
</view>
<block wx:if="{{item.spec != null}}">
<view class="goods-attribute cr-888" wx:for="{{item.spec}}" wx:for-item="spec">{{spec.type}}:{{spec.value}}</view>
</block>
</view>
<!-- 数量 -->
<view class="number-content tc oh">
<view bindtap="goods_buy_number_event" class="number-submit tc cr-888 fl" data-index="{{index}}" data-type="0">-</view>
<input onBlur="goods_buy_number_blur" class="tc cr-888 fl" type="number" value="{{item.stock}}" data-index="{{index}}" />
<view bindtap="goods_buy_number_event" class="number-submit tc cr-888 fl" data-index="{{index}}" data-type="1">+</view>
</view>
<!-- 价格 -->
<view class="oh goods-price">
<text class="sales-price">¥{{item.price}}</text>
<text wx:if="{{item.original_price > 0}}" class="original-price">¥{{item.original_price}}</text>
<text class="buy-number cr-888">x{{item.stock}}</text>
</view>
<!-- 价格 -->
<view class="oh goods-price">
<text class="sales-price">¥{{item.price}}</text>
<text wx:if="{{item.original_price > 0}}" class="original-price">¥{{item.original_price}}</text>
<text class="buy-number cr-888">x{{item.stock}}</text>
</view>
</swipe-action>
</view>
</view>
<!-- 操作导航 -->

View File

@ -20,9 +20,19 @@ Page({
wx.setNavigationBarTitle({title: '手机绑定'});
// 设置用户信息
this.setData({params: option, user: app.GetUserCacheInfo()});
this.setData({
params: option,
user: app.GetUserCacheInfo() || null
});
},
/**
* 登录授权事件
*/
get_user_info_event(e) {
console.log(e, e.detail.userInfo)
}
/**
* 输入手机号码事件
*/

View File

@ -1,4 +1,4 @@
<view class="content">
<view wx:if="{{user != null}}" class="content">
<form bindsubmit="formSubmit">
<input type="number" placeholder="输入手机号码" maxlength="11" name="mobile" onInput="bind_key_input" class="mobile" />
<view class="code clearfix">
@ -7,4 +7,9 @@
</view>
<button type="default" formType="submit" hover-class="none" plain loading="{{form_submit_loading}}" disabled="{{form_submit_loading}}" class="submit {{form_submit_loading ? 'my-btn-gray' : 'my-btn-default'}}">确认绑定</button>
</form>
</view>
</view>
<view wx:if="{{user == null}}" class="wx-login tc">
<view class="cr-888 fs-12">确认登录授权,为您提供更优质的服务</view>
<button type="primary" size="mini" open-type="getUserInfo" bindgetuserinfo="get_user_info_event">授权登录</button>
</view>

View File

@ -46,4 +46,14 @@ page{
bottom: 34rpx;
height: 90rpx;
line-height: 90rpx;
}
/**
授权登录
*/
.wx-login {
padding-top: 30%;
}
.wx-login button {
margin-top: 30rpx;
}