作者 杨育虎

微信配置

  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: hooklife
  5 + * Date: 2017/1/12
  6 + * Time: 11:52
  7 + */
  8 +return [
  9 + /**
  10 + * Debug 模式,bool 值:true/false
  11 + *
  12 + * 当值为 false 时,所有的日志都不会记录
  13 + */
  14 + 'debug' => true,
  15 + /**
  16 + * 账号基本信息,请从微信公众平台/开放平台获取
  17 + */
  18 + 'app_id' => 'wxb4238fbc5c39db5d', // AppID
  19 + 'secret' => '9d95998ab1a23374c7235a30b53f3a3c', // AppSecret
  20 + 'token' => 'your-token', // Token
  21 + 'aes_key' => '', // EncodingAESKey,安全模式下请一定要填写!!!
  22 + /**
  23 + * 日志配置
  24 + *
  25 + * level: 日志级别, 可选为:
  26 + * debug/info/notice/warning/error/critical/alert/emergency
  27 + * permission:日志文件权限(可选),默认为null(若为null值,monolog会取0644)
  28 + * file:日志文件位置(绝对路径!!!),要求可写权限
  29 + */
  30 + 'log' => [
  31 + 'level' => 'debug',
  32 + 'permission' => 0777,
  33 + 'file' => LOG_PATH.'easywechat.log',
  34 + ],
  35 + /**
  36 + * OAuth 配置
  37 + *
  38 + * scopes:公众平台(snsapi_userinfo / snsapi_base),开放平台:snsapi_login
  39 + * callback:OAuth授权完成后的回调页地址
  40 + */
  41 + 'oauth' => [
  42 + 'scopes' => ['snsapi_userinfo'],
  43 + 'callback' => '/user/index/callback',
  44 + ],
  45 + /**
  46 + * 微信支付
  47 + */
  48 + 'payment' => [
  49 + 'merchant_id' => '1509104971',
  50 + 'key' => 'ebfe7fba8f7a0fba3e19efcc547b956d',
  51 + 'cert_path' => 'wechat/cert/apiclient_cert.pem', // XXX: 绝对路径!!!!
  52 + 'key_path' => 'wechat/cert/apiclient_key.pem', // XXX: 绝对路径!!!!
  53 + // 'device_info' => '013467007045764',
  54 + // 'sub_app_id' => '',
  55 + // 'sub_merchant_id' => '',
  56 + // ...
  57 + ],
  58 + /**
  59 + * Guzzle 全局设置
  60 + *
  61 + * 更多请参考: http://docs.guzzlephp.org/en/latest/request-options.html
  62 + */
  63 + 'guzzle' => [
  64 + 'timeout' => 3.0, // 超时时间(秒)
  65 + //'verify' => false, // 关掉 SSL 认证(强烈不建议!!!)
  66 + ],
  67 +];
@@ -12,9 +12,23 @@ namespace app\user\controller; @@ -12,9 +12,23 @@ namespace app\user\controller;
12 12
13 use cmf\controller\HomeBaseController; 13 use cmf\controller\HomeBaseController;
14 use think\Db; 14 use think\Db;
  15 +use EasyWeChat\Foundation\Application;
15 16
16 class IndexController extends HomeBaseController 17 class IndexController extends HomeBaseController
17 { 18 {
  19 + public function callback(){
  20 + $config = [];
  21 +
  22 + $app = new Application($config);
  23 + $oauth = $app->oauth;
  24 + $user = $oauth->user();
  25 + $wechat_user = $user->toArray();
  26 + //todo $wechat_user与数据库对比
  27 + session('wechat_user',$wechat_user);
  28 + $target_url=session('target_url');
  29 + $targetUrl = empty($target_url) ? '/' : $target_url;
  30 + header('location:'. $targetUrl);
  31 + }
18 32
19 /** 33 /**
20 * 前台用户首页(公开) 34 * 前台用户首页(公开)
不能预览此文件类型
  1 +-----BEGIN CERTIFICATE-----
  2 +MIIEZDCCA82gAwIBAgIEAhEzATANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMC
  3 +Q04xEjAQBgNVBAgTCUd1YW5nZG9uZzERMA8GA1UEBxMIU2hlbnpoZW4xEDAOBgNV
  4 +BAoTB1RlbmNlbnQxDDAKBgNVBAsTA1dYRzETMBEGA1UEAxMKTW1wYXltY2hDQTEf
  5 +MB0GCSqGSIb3DQEJARYQbW1wYXltY2hAdGVuY2VudDAeFw0xODA3MDMxMjMwNDVa
  6 +Fw0yODA2MzAxMjMwNDVaMIGTMQswCQYDVQQGEwJDTjESMBAGA1UECBMJR3Vhbmdk
  7 +b25nMREwDwYDVQQHEwhTaGVuemhlbjEQMA4GA1UEChMHVGVuY2VudDEOMAwGA1UE
  8 +CxMFTU1QYXkxJzAlBgNVBAMUHuWkqea0peaWueebruenkeaKgOaciemZkOWFrOWP
  9 +uDESMBAGA1UEBBMJMTAwODkxMjUxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
  10 +CgKCAQEAsLJARXruD6jC8cchcOFHqsX9FPCypVafg4pVrVMDwlXNzqWqlizaRaGY
  11 +HPsDhgJvU3YX+xWo43aocsPkXw+Yl24SnwAwAUz1gL3RA1yrT1S2uFVMZ3uLVXTk
  12 +qnxa2iWtrjf46Qx6wEX++Fw99HCQldu/B3zaOjK5XizJNWc/dr8ZSbsEzWN5NNje
  13 +Fv68fYnYqWiSTezKbzvRAMh5Ho3hY60wsc0gPXHCUOcucAjM21Z9a1yBqu0XWhL4
  14 +UVCXI10sBICEyoSXwx0tnzmy8cO76wA0DlYC5PCmCGSKRBXFCpgbCPg+QRRWu4a8
  15 +p4qqENmbYpz7zW6/PYRza52/6/Jj4wIDAQABo4IBRjCCAUIwCQYDVR0TBAIwADAs
  16 +BglghkgBhvhCAQ0EHxYdIkNFUy1DQSBHZW5lcmF0ZSBDZXJ0aWZpY2F0ZSIwHQYD
  17 +VR0OBBYEFP6DEaEgkaDlDyLok8ARpTwS0TZIMIG/BgNVHSMEgbcwgbSAFD4FJvYi
  18 +YrQVW4jNZH6w1GKn5YZ0oYGQpIGNMIGKMQswCQYDVQQGEwJDTjESMBAGA1UECBMJ
  19 +R3Vhbmdkb25nMREwDwYDVQQHEwhTaGVuemhlbjEQMA4GA1UEChMHVGVuY2VudDEM
  20 +MAoGA1UECxMDV1hHMRMwEQYDVQQDEwpNbXBheW1jaENBMR8wHQYJKoZIhvcNAQkB
  21 +FhBtbXBheW1jaEB0ZW5jZW50ggkAu1SXK7wA6FcwDgYDVR0PAQH/BAQDAgbAMBYG
  22 +A1UdJQEB/wQMMAoGCCsGAQUFBwMCMA0GCSqGSIb3DQEBBQUAA4GBAEA1ND+JEyog
  23 +Fd4+3De5voIHdyWKWF94EouysL9tCCngTeVHTQBlP+/QVwfbfCaRnmgwAmzHR49Q
  24 +rh7tQltzTpNoNk0H4MZxck2xmtKKQqNWItPuJWCdGA9J38hIxjaeIiBVcsxt2ARP
  25 +3JKPPOsWd3uJ8pSVMfolAi0738ToE2lm
  26 +-----END CERTIFICATE-----
  1 +-----BEGIN PRIVATE KEY-----
  2 +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCwskBFeu4PqMLx
  3 +xyFw4Ueqxf0U8LKlVp+DilWtUwPCVc3OpaqWLNpFoZgc+wOGAm9Tdhf7Fajjdqhy
  4 +w+RfD5iXbhKfADABTPWAvdEDXKtPVLa4VUxne4tVdOSqfFraJa2uN/jpDHrARf74
  5 +XD30cJCV278HfNo6MrleLMk1Zz92vxlJuwTNY3k02N4W/rx9idipaJJN7MpvO9EA
  6 +yHkejeFjrTCxzSA9ccJQ5y5wCMzbVn1rXIGq7RdaEvhRUJcjXSwEgITKhJfDHS2f
  7 +ObLxw7vrADQOVgLk8KYIZIpEFcUKmBsI+D5BFFa7hryniqoQ2ZtinPvNbr89hHNr
  8 +nb/r8mPjAgMBAAECggEAI4u4YkHYok3Q6dKlZ4/qWvB5eTzys1A5xryNf9CzcOTS
  9 +AkBRkOR1BIz9jNbyXoMe4itfp6Mz1o6IVI4T4wvAJrZ+CH6BKcHRoZSN958s10iz
  10 +eWGvfSHdZdOeLK3XmQr7ZZDdAgUArK1oHY5w6Du82mjahScYv5x0rf1UfOnIWprB
  11 +Hk0kE6Q918zgwmuTuPhRc+YXXJyf++XnFEqi/ue6im/sBmKfqVu92qfk4jgxu5kw
  12 +gsJc6f6rFLzZ4jRMc8oB++lIrS/4y2f4n7/fUWTY+w77AqdbGm+fTHIBZcn/cweS
  13 +Q9IrzNmkKD6q3f4NkwAZ2S74lx5gY8X4HUxbIuHUAQKBgQDnAsGpIZLVboCecIh3
  14 +f9sfq/CULyhhnbzirytaOC1cojyD0wYgzIQDEfuu3bo84dwWLZgZN+bHxj3c4DaQ
  15 +wim9IftbYVTtuaGENcg+wxJ1HHcnXiByuAacRQcChXY/ZBkq75BUuewoRb5NPzJ1
  16 +jhw7H9O/ZBhCU5g1Krn9DPfihQKBgQDDz2VtrOVtLAoaElbFhiXSOoavxsR5vX9+
  17 +lj2ZvmbcA7jwKkx4/rAXqk2umTLVzcVaRXp4/G5KOtL1jqbJ82fTbhtxDV4mZgz7
  18 +SAkVZoiv0XzQsgcBOmA30fElG5sSIqGhljaFghSWz9M/oLcMaZ6uD6nSqYNkBISO
  19 +WGofKFudRwKBgQC1MYhM7LSLC91+aK3hbTumH+rXkBWQW3ToKJVMcnvCCM6GZ2KL
  20 +H178OYK7qdaGInHKQ4DlZt9xGqEzOfoSmPi8DIdnKXS/8bYqSTUDZWZ4zRb4ne+9
  21 +i3JD6DCTXbNeDVlgP/9pNVtySyH03PjrE8g458HigNQ2UfM04Ip5XU6hMQKBgE6L
  22 +tkMddNarMM4uhxIq8qb3BSojkJLJGgh8We9/OiGNeLUWMqDigV6s2QZtu7+aEE1a
  23 +y3sWv2MVX6RS+cLO2dotM+LQmvDKRPDTf5lPDQuB/BB3KWorsYcStynMfhLzQ2Tf
  24 +LbW2bW3lpfbDEEpxX86wx82SY/tN+KJlAwTGmqFnAoGAJSnB0fyAhT2oB1+t6pax
  25 +93CeBbEBXnrWSmGrUgHVFHcR2Vvq5O7A3F66VXNn88ij+TUsbjEa1XHg1kHwhP2m
  26 +UoyF0imlaHH1kHFpT4okG1vLWSExAdSmgOwAKWd2QXrwVtn2rAzjnp527mWCuWx3
  27 +SWZVYzS3kFSBxpHR+VWVezo=
  28 +-----END PRIVATE KEY-----
  1 +欢迎使用微信支付!
  2 +附件中的三份文件(证书pkcs12格式、证书pem格式、证书密钥pem格式),为接口中强制要求时需携带的证书文件。
  3 +证书属于敏感信息,请妥善保管不要泄露和被他人复制。
  4 +不同开发语言下的证书格式不同,以下为说明指引:
  5 + 证书pkcs12格式(apiclient_cert.p12)
  6 + 包含了私钥信息的证书文件,为p12(pfx)格式,由微信支付签发给您用来标识和界定您的身份
  7 + 部分安全性要求较高的API需要使用该证书来确认您的调用身份
  8 + windows上可以直接双击导入系统,导入过程中会提示输入证书密码,证书密码默认为您的商户ID(如:10010000)
  9 + 证书pem格式(apiclient_cert.pem)
  10 + 从apiclient_cert.p12中导出证书部分的文件,为pem格式,请妥善保管不要泄漏和被他人复制
  11 + 部分开发语言和环境,不能直接使用p12文件,而需要使用pem,所以为了方便您使用,已为您直接提供
  12 + 您也可以使用openssl命令来自己导出:openssl pkcs12 -clcerts -nokeys -in apiclient_cert.p12 -out apiclient_cert.pem
  13 + 证书密钥pem格式(apiclient_key.pem)
  14 + 从apiclient_cert.p12中导出密钥部分的文件,为pem格式
  15 + 部分开发语言和环境,不能直接使用p12文件,而需要使用pem,所以为了方便您使用,已为您直接提供
  16 + 您也可以使用openssl命令来自己导出:openssl pkcs12 -nocerts -in apiclient_cert.p12 -out apiclient_key.pem
  17 +备注说明:
  18 + 由于绝大部分操作系统已内置了微信支付服务器证书的根CA证书, 2018年3月6日后, 不再提供CA证书文件(rootca.pem)下载
  1 +<?php
  2 +// +----------------------------------------------------------------------
  3 +// | bronet [ 以客户为中心 以奋斗者为本 ]
  4 +// +----------------------------------------------------------------------
  5 +// | Copyright (c) 2013-2017 http://www.bronet.cn All rights reserved.
  6 +// +----------------------------------------------------------------------
  7 +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8 +// +---------------------------------------------------------------------
  9 +// | Author: Tiger
  10 +// +----------------------------------------------------------------------
  11 +namespace cmf\controller;
  12 +
  13 +use app\user\model\UserModel;
  14 +use EasyWeChat\Foundation\Application;
  15 +use think\Db;
  16 +use app\admin\model\ThemeModel;
  17 +use think\View;
  18 +
  19 +class WeChatBaseController extends BaseController
  20 +{
  21 +
  22 + public function _initialize()
  23 + {
  24 + // 监听home_init
  25 + hook('home_init');
  26 + parent::_initialize();
  27 + $siteInfo = cmf_get_site_info();
  28 + View::share('site_info', $siteInfo);
  29 + }
  30 +
  31 + public function _initializeView()
  32 + {
  33 + $cmfThemePath = config('cmf_theme_path');
  34 + $cmfDefaultTheme = cmf_get_current_theme();
  35 +
  36 + $themePath = "{$cmfThemePath}{$cmfDefaultTheme}";
  37 +
  38 + $root = cmf_get_root();
  39 + //使cdn设置生效
  40 + $cdnSettings = cmf_get_option('cdn_settings');
  41 + if (empty($cdnSettings['cdn_static_root'])) {
  42 + $viewReplaceStr = [
  43 + '__ROOT__' => $root,
  44 + '__TMPL__' => "{$root}/{$themePath}",
  45 + '__STATIC__' => "{$root}/static",
  46 + '__WEB_ROOT__' => $root
  47 + ];
  48 + } else {
  49 + $cdnStaticRoot = rtrim($cdnSettings['cdn_static_root'], '/');
  50 + $viewReplaceStr = [
  51 + '__ROOT__' => $root,
  52 + '__TMPL__' => "{$cdnStaticRoot}/{$themePath}",
  53 + '__STATIC__' => "{$cdnStaticRoot}/static",
  54 + '__WEB_ROOT__' => $cdnStaticRoot
  55 + ];
  56 + }
  57 +
  58 + $viewReplaceStr = array_merge(config('view_replace_str'), $viewReplaceStr);
  59 + config('template.view_base', "{$themePath}/");
  60 + config('view_replace_str', $viewReplaceStr);
  61 +
  62 + $themeErrorTmpl = "{$themePath}/error.html";
  63 + if (file_exists_case($themeErrorTmpl)) {
  64 + config('dispatch_error_tmpl', $themeErrorTmpl);
  65 + }
  66 +
  67 + $themeSuccessTmpl = "{$themePath}/success.html";
  68 + if (file_exists_case($themeSuccessTmpl)) {
  69 + config('dispatch_success_tmpl', $themeSuccessTmpl);
  70 + }
  71 +
  72 +
  73 + }
  74 +
  75 + /**
  76 + * 加载模板输出
  77 + * @access protected
  78 + * @param string $template 模板文件名
  79 + * @param array $vars 模板输出变量
  80 + * @param array $replace 模板替换
  81 + * @param array $config 模板参数
  82 + * @return mixed
  83 + */
  84 + protected function fetch($template = '', $vars = [], $replace = [], $config = [])
  85 + {
  86 + $template = $this->parseTemplate($template);
  87 + $more = $this->getThemeFileMore($template);
  88 + $this->assign('theme_vars', $more['vars']);
  89 + $this->assign('theme_widgets', $more['widgets']);
  90 + return parent::fetch($template, $vars, $replace, $config);
  91 + }
  92 +
  93 + /**
  94 + * 自动定位模板文件
  95 + * @access private
  96 + * @param string $template 模板文件规则
  97 + * @return string
  98 + */
  99 + private function parseTemplate($template)
  100 + {
  101 + // 分析模板文件规则
  102 + $request = $this->request;
  103 + // 获取视图根目录
  104 + if (strpos($template, '@')) {
  105 + // 跨模块调用
  106 + list($module, $template) = explode('@', $template);
  107 + }
  108 +
  109 + $viewBase = config('template.view_base');
  110 +
  111 + if ($viewBase) {
  112 + // 基础视图目录
  113 + $module = isset($module) ? $module : $request->module();
  114 + $path = $viewBase . ($module ? $module . DS : '');
  115 + } else {
  116 + $path = isset($module) ? APP_PATH . $module . DS . 'view' . DS : config('template.view_path');
  117 + }
  118 +
  119 + $depr = config('template.view_depr');
  120 + if (0 !== strpos($template, '/')) {
  121 + $template = str_replace(['/', ':'], $depr, $template);
  122 + $controller = cmf_parse_name($request->controller());
  123 + if ($controller) {
  124 + if ('' == $template) {
  125 + // 如果模板文件名为空 按照默认规则定位
  126 + $template = str_replace('.', DS, $controller) . $depr . $request->action();
  127 + } elseif (false === strpos($template, $depr)) {
  128 + $template = str_replace('.', DS, $controller) . $depr . $template;
  129 + }
  130 + }
  131 + } else {
  132 + $template = str_replace(['/', ':'], $depr, substr($template, 1));
  133 + }
  134 + return $path . ltrim($template, '/') . '.' . ltrim(config('template.view_suffix'), '.');
  135 + }
  136 +
  137 + /**
  138 + * 获取模板文件变量
  139 + * @param string $file
  140 + * @param string $theme
  141 + * @return array
  142 + */
  143 + private function getThemeFileMore($file, $theme = "")
  144 + {
  145 +
  146 + //TODO 增加缓存
  147 + $theme = empty($theme) ? cmf_get_current_theme() : $theme;
  148 +
  149 + // 调试模式下自动更新模板
  150 + if (APP_DEBUG) {
  151 + $themeModel = new ThemeModel();
  152 + $themeModel->updateTheme($theme);
  153 + }
  154 +
  155 + $themePath = config('cmf_theme_path');
  156 + $file = str_replace('\\', '/', $file);
  157 + $file = str_replace('//', '/', $file);
  158 + $file = str_replace(['.html', '.php', $themePath . $theme . "/"], '', $file);
  159 +
  160 + $files = Db::name('theme_file')->field('more')->where(['theme' => $theme])->where(function ($query) use ($file) {
  161 + $query->where(['is_public' => 1])->whereOr(['file' => $file]);
  162 + })->select();
  163 +
  164 + $vars = [];
  165 + $widgets = [];
  166 + foreach ($files as $file) {
  167 + $oldMore = json_decode($file['more'], true);
  168 + if (!empty($oldMore['vars'])) {
  169 + foreach ($oldMore['vars'] as $varName => $var) {
  170 + $vars[$varName] = $var['value'];
  171 + }
  172 + }
  173 +
  174 + if (!empty($oldMore['widgets'])) {
  175 + foreach ($oldMore['widgets'] as $widgetName => $widget) {
  176 +
  177 + $widgetVars = [];
  178 + if (!empty($widget['vars'])) {
  179 + foreach ($widget['vars'] as $varName => $var) {
  180 + $widgetVars[$varName] = $var['value'];
  181 + }
  182 + }
  183 +
  184 + $widget['vars'] = $widgetVars;
  185 + $widgets[$widgetName] = $widget;
  186 + }
  187 + }
  188 + }
  189 +
  190 + return ['vars' => $vars, 'widgets' => $widgets];
  191 + }
  192 +
  193 + public function checkUserLogin()
  194 + {
  195 + $userId = cmf_get_current_user_id();
  196 + if (empty($userId)) {
  197 + $this->error("用户尚未登录", url("user/login/index"));
  198 + }
  199 + }
  200 +
  201 + /**
  202 + * 检查微信用户登录
  203 + */
  204 + public function checkWeChatUserLogin()
  205 + {
  206 + $userId = cmf_get_current_user_id();
  207 + if (empty($userId)) {
  208 + $config = [
  209 + 'oauth' => [
  210 + 'scopes' => ['snsapi_userinfo'],
  211 + 'callback' => '/oauth_callback',
  212 + ],
  213 + ];
  214 +
  215 + $app = new Application($config);
  216 + $oauth = $app->oauth;
  217 + $target_url='http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
  218 + session('target_url',$target_url);
  219 + return $oauth->redirect();
  220 + }
  221 + }
  222 +
  223 +}