作者 杨育虎

微信配置

<?php
/**
* Created by PhpStorm.
* User: hooklife
* Date: 2017/1/12
* Time: 11:52
*/
return [
/**
* Debug 模式,bool 值:true/false
*
* 当值为 false 时,所有的日志都不会记录
*/
'debug' => true,
/**
* 账号基本信息,请从微信公众平台/开放平台获取
*/
'app_id' => 'wxb4238fbc5c39db5d', // AppID
'secret' => '9d95998ab1a23374c7235a30b53f3a3c', // AppSecret
'token' => 'your-token', // Token
'aes_key' => '', // EncodingAESKey,安全模式下请一定要填写!!!
/**
* 日志配置
*
* level: 日志级别, 可选为:
* debug/info/notice/warning/error/critical/alert/emergency
* permission:日志文件权限(可选),默认为null(若为null值,monolog会取0644)
* file:日志文件位置(绝对路径!!!),要求可写权限
*/
'log' => [
'level' => 'debug',
'permission' => 0777,
'file' => LOG_PATH.'easywechat.log',
],
/**
* OAuth 配置
*
* scopes:公众平台(snsapi_userinfo / snsapi_base),开放平台:snsapi_login
* callback:OAuth授权完成后的回调页地址
*/
'oauth' => [
'scopes' => ['snsapi_userinfo'],
'callback' => '/user/index/callback',
],
/**
* 微信支付
*/
'payment' => [
'merchant_id' => '1509104971',
'key' => 'ebfe7fba8f7a0fba3e19efcc547b956d',
'cert_path' => 'wechat/cert/apiclient_cert.pem', // XXX: 绝对路径!!!!
'key_path' => 'wechat/cert/apiclient_key.pem', // XXX: 绝对路径!!!!
// 'device_info' => '013467007045764',
// 'sub_app_id' => '',
// 'sub_merchant_id' => '',
// ...
],
/**
* Guzzle 全局设置
*
* 更多请参考: http://docs.guzzlephp.org/en/latest/request-options.html
*/
'guzzle' => [
'timeout' => 3.0, // 超时时间(秒)
//'verify' => false, // 关掉 SSL 认证(强烈不建议!!!)
],
];
\ No newline at end of file
... ...
... ... @@ -12,9 +12,23 @@ namespace app\user\controller;
use cmf\controller\HomeBaseController;
use think\Db;
use EasyWeChat\Foundation\Application;
class IndexController extends HomeBaseController
{
public function callback(){
$config = [];
$app = new Application($config);
$oauth = $app->oauth;
$user = $oauth->user();
$wechat_user = $user->toArray();
//todo $wechat_user与数据库对比
session('wechat_user',$wechat_user);
$target_url=session('target_url');
$targetUrl = empty($target_url) ? '/' : $target_url;
header('location:'. $targetUrl);
}
/**
* 前台用户首页(公开)
... ...
不能预览此文件类型
-----BEGIN CERTIFICATE-----
MIIEZDCCA82gAwIBAgIEAhEzATANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMC
Q04xEjAQBgNVBAgTCUd1YW5nZG9uZzERMA8GA1UEBxMIU2hlbnpoZW4xEDAOBgNV
BAoTB1RlbmNlbnQxDDAKBgNVBAsTA1dYRzETMBEGA1UEAxMKTW1wYXltY2hDQTEf
MB0GCSqGSIb3DQEJARYQbW1wYXltY2hAdGVuY2VudDAeFw0xODA3MDMxMjMwNDVa
Fw0yODA2MzAxMjMwNDVaMIGTMQswCQYDVQQGEwJDTjESMBAGA1UECBMJR3Vhbmdk
b25nMREwDwYDVQQHEwhTaGVuemhlbjEQMA4GA1UEChMHVGVuY2VudDEOMAwGA1UE
CxMFTU1QYXkxJzAlBgNVBAMUHuWkqea0peaWueebruenkeaKgOaciemZkOWFrOWP
uDESMBAGA1UEBBMJMTAwODkxMjUxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAsLJARXruD6jC8cchcOFHqsX9FPCypVafg4pVrVMDwlXNzqWqlizaRaGY
HPsDhgJvU3YX+xWo43aocsPkXw+Yl24SnwAwAUz1gL3RA1yrT1S2uFVMZ3uLVXTk
qnxa2iWtrjf46Qx6wEX++Fw99HCQldu/B3zaOjK5XizJNWc/dr8ZSbsEzWN5NNje
Fv68fYnYqWiSTezKbzvRAMh5Ho3hY60wsc0gPXHCUOcucAjM21Z9a1yBqu0XWhL4
UVCXI10sBICEyoSXwx0tnzmy8cO76wA0DlYC5PCmCGSKRBXFCpgbCPg+QRRWu4a8
p4qqENmbYpz7zW6/PYRza52/6/Jj4wIDAQABo4IBRjCCAUIwCQYDVR0TBAIwADAs
BglghkgBhvhCAQ0EHxYdIkNFUy1DQSBHZW5lcmF0ZSBDZXJ0aWZpY2F0ZSIwHQYD
VR0OBBYEFP6DEaEgkaDlDyLok8ARpTwS0TZIMIG/BgNVHSMEgbcwgbSAFD4FJvYi
YrQVW4jNZH6w1GKn5YZ0oYGQpIGNMIGKMQswCQYDVQQGEwJDTjESMBAGA1UECBMJ
R3Vhbmdkb25nMREwDwYDVQQHEwhTaGVuemhlbjEQMA4GA1UEChMHVGVuY2VudDEM
MAoGA1UECxMDV1hHMRMwEQYDVQQDEwpNbXBheW1jaENBMR8wHQYJKoZIhvcNAQkB
FhBtbXBheW1jaEB0ZW5jZW50ggkAu1SXK7wA6FcwDgYDVR0PAQH/BAQDAgbAMBYG
A1UdJQEB/wQMMAoGCCsGAQUFBwMCMA0GCSqGSIb3DQEBBQUAA4GBAEA1ND+JEyog
Fd4+3De5voIHdyWKWF94EouysL9tCCngTeVHTQBlP+/QVwfbfCaRnmgwAmzHR49Q
rh7tQltzTpNoNk0H4MZxck2xmtKKQqNWItPuJWCdGA9J38hIxjaeIiBVcsxt2ARP
3JKPPOsWd3uJ8pSVMfolAi0738ToE2lm
-----END CERTIFICATE-----
... ...
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCwskBFeu4PqMLx
xyFw4Ueqxf0U8LKlVp+DilWtUwPCVc3OpaqWLNpFoZgc+wOGAm9Tdhf7Fajjdqhy
w+RfD5iXbhKfADABTPWAvdEDXKtPVLa4VUxne4tVdOSqfFraJa2uN/jpDHrARf74
XD30cJCV278HfNo6MrleLMk1Zz92vxlJuwTNY3k02N4W/rx9idipaJJN7MpvO9EA
yHkejeFjrTCxzSA9ccJQ5y5wCMzbVn1rXIGq7RdaEvhRUJcjXSwEgITKhJfDHS2f
ObLxw7vrADQOVgLk8KYIZIpEFcUKmBsI+D5BFFa7hryniqoQ2ZtinPvNbr89hHNr
nb/r8mPjAgMBAAECggEAI4u4YkHYok3Q6dKlZ4/qWvB5eTzys1A5xryNf9CzcOTS
AkBRkOR1BIz9jNbyXoMe4itfp6Mz1o6IVI4T4wvAJrZ+CH6BKcHRoZSN958s10iz
eWGvfSHdZdOeLK3XmQr7ZZDdAgUArK1oHY5w6Du82mjahScYv5x0rf1UfOnIWprB
Hk0kE6Q918zgwmuTuPhRc+YXXJyf++XnFEqi/ue6im/sBmKfqVu92qfk4jgxu5kw
gsJc6f6rFLzZ4jRMc8oB++lIrS/4y2f4n7/fUWTY+w77AqdbGm+fTHIBZcn/cweS
Q9IrzNmkKD6q3f4NkwAZ2S74lx5gY8X4HUxbIuHUAQKBgQDnAsGpIZLVboCecIh3
f9sfq/CULyhhnbzirytaOC1cojyD0wYgzIQDEfuu3bo84dwWLZgZN+bHxj3c4DaQ
wim9IftbYVTtuaGENcg+wxJ1HHcnXiByuAacRQcChXY/ZBkq75BUuewoRb5NPzJ1
jhw7H9O/ZBhCU5g1Krn9DPfihQKBgQDDz2VtrOVtLAoaElbFhiXSOoavxsR5vX9+
lj2ZvmbcA7jwKkx4/rAXqk2umTLVzcVaRXp4/G5KOtL1jqbJ82fTbhtxDV4mZgz7
SAkVZoiv0XzQsgcBOmA30fElG5sSIqGhljaFghSWz9M/oLcMaZ6uD6nSqYNkBISO
WGofKFudRwKBgQC1MYhM7LSLC91+aK3hbTumH+rXkBWQW3ToKJVMcnvCCM6GZ2KL
H178OYK7qdaGInHKQ4DlZt9xGqEzOfoSmPi8DIdnKXS/8bYqSTUDZWZ4zRb4ne+9
i3JD6DCTXbNeDVlgP/9pNVtySyH03PjrE8g458HigNQ2UfM04Ip5XU6hMQKBgE6L
tkMddNarMM4uhxIq8qb3BSojkJLJGgh8We9/OiGNeLUWMqDigV6s2QZtu7+aEE1a
y3sWv2MVX6RS+cLO2dotM+LQmvDKRPDTf5lPDQuB/BB3KWorsYcStynMfhLzQ2Tf
LbW2bW3lpfbDEEpxX86wx82SY/tN+KJlAwTGmqFnAoGAJSnB0fyAhT2oB1+t6pax
93CeBbEBXnrWSmGrUgHVFHcR2Vvq5O7A3F66VXNn88ij+TUsbjEa1XHg1kHwhP2m
UoyF0imlaHH1kHFpT4okG1vLWSExAdSmgOwAKWd2QXrwVtn2rAzjnp527mWCuWx3
SWZVYzS3kFSBxpHR+VWVezo=
-----END PRIVATE KEY-----
... ...
欢迎使用微信支付!
附件中的三份文件(证书pkcs12格式、证书pem格式、证书密钥pem格式),为接口中强制要求时需携带的证书文件。
证书属于敏感信息,请妥善保管不要泄露和被他人复制。
不同开发语言下的证书格式不同,以下为说明指引:
证书pkcs12格式(apiclient_cert.p12)
包含了私钥信息的证书文件,为p12(pfx)格式,由微信支付签发给您用来标识和界定您的身份
部分安全性要求较高的API需要使用该证书来确认您的调用身份
windows上可以直接双击导入系统,导入过程中会提示输入证书密码,证书密码默认为您的商户ID(如:10010000)
证书pem格式(apiclient_cert.pem)
从apiclient_cert.p12中导出证书部分的文件,为pem格式,请妥善保管不要泄漏和被他人复制
部分开发语言和环境,不能直接使用p12文件,而需要使用pem,所以为了方便您使用,已为您直接提供
您也可以使用openssl命令来自己导出:openssl pkcs12 -clcerts -nokeys -in apiclient_cert.p12 -out apiclient_cert.pem
证书密钥pem格式(apiclient_key.pem)
从apiclient_cert.p12中导出密钥部分的文件,为pem格式
部分开发语言和环境,不能直接使用p12文件,而需要使用pem,所以为了方便您使用,已为您直接提供
您也可以使用openssl命令来自己导出:openssl pkcs12 -nocerts -in apiclient_cert.p12 -out apiclient_key.pem
备注说明:
由于绝大部分操作系统已内置了微信支付服务器证书的根CA证书, 2018年3月6日后, 不再提供CA证书文件(rootca.pem)下载
\ No newline at end of file
... ...
<?php
// +----------------------------------------------------------------------
// | bronet [ 以客户为中心 以奋斗者为本 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2013-2017 http://www.bronet.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +---------------------------------------------------------------------
// | Author: Tiger
// +----------------------------------------------------------------------
namespace cmf\controller;
use app\user\model\UserModel;
use EasyWeChat\Foundation\Application;
use think\Db;
use app\admin\model\ThemeModel;
use think\View;
class WeChatBaseController extends BaseController
{
public function _initialize()
{
// 监听home_init
hook('home_init');
parent::_initialize();
$siteInfo = cmf_get_site_info();
View::share('site_info', $siteInfo);
}
public function _initializeView()
{
$cmfThemePath = config('cmf_theme_path');
$cmfDefaultTheme = cmf_get_current_theme();
$themePath = "{$cmfThemePath}{$cmfDefaultTheme}";
$root = cmf_get_root();
//使cdn设置生效
$cdnSettings = cmf_get_option('cdn_settings');
if (empty($cdnSettings['cdn_static_root'])) {
$viewReplaceStr = [
'__ROOT__' => $root,
'__TMPL__' => "{$root}/{$themePath}",
'__STATIC__' => "{$root}/static",
'__WEB_ROOT__' => $root
];
} else {
$cdnStaticRoot = rtrim($cdnSettings['cdn_static_root'], '/');
$viewReplaceStr = [
'__ROOT__' => $root,
'__TMPL__' => "{$cdnStaticRoot}/{$themePath}",
'__STATIC__' => "{$cdnStaticRoot}/static",
'__WEB_ROOT__' => $cdnStaticRoot
];
}
$viewReplaceStr = array_merge(config('view_replace_str'), $viewReplaceStr);
config('template.view_base', "{$themePath}/");
config('view_replace_str', $viewReplaceStr);
$themeErrorTmpl = "{$themePath}/error.html";
if (file_exists_case($themeErrorTmpl)) {
config('dispatch_error_tmpl', $themeErrorTmpl);
}
$themeSuccessTmpl = "{$themePath}/success.html";
if (file_exists_case($themeSuccessTmpl)) {
config('dispatch_success_tmpl', $themeSuccessTmpl);
}
}
/**
* 加载模板输出
* @access protected
* @param string $template 模板文件名
* @param array $vars 模板输出变量
* @param array $replace 模板替换
* @param array $config 模板参数
* @return mixed
*/
protected function fetch($template = '', $vars = [], $replace = [], $config = [])
{
$template = $this->parseTemplate($template);
$more = $this->getThemeFileMore($template);
$this->assign('theme_vars', $more['vars']);
$this->assign('theme_widgets', $more['widgets']);
return parent::fetch($template, $vars, $replace, $config);
}
/**
* 自动定位模板文件
* @access private
* @param string $template 模板文件规则
* @return string
*/
private function parseTemplate($template)
{
// 分析模板文件规则
$request = $this->request;
// 获取视图根目录
if (strpos($template, '@')) {
// 跨模块调用
list($module, $template) = explode('@', $template);
}
$viewBase = config('template.view_base');
if ($viewBase) {
// 基础视图目录
$module = isset($module) ? $module : $request->module();
$path = $viewBase . ($module ? $module . DS : '');
} else {
$path = isset($module) ? APP_PATH . $module . DS . 'view' . DS : config('template.view_path');
}
$depr = config('template.view_depr');
if (0 !== strpos($template, '/')) {
$template = str_replace(['/', ':'], $depr, $template);
$controller = cmf_parse_name($request->controller());
if ($controller) {
if ('' == $template) {
// 如果模板文件名为空 按照默认规则定位
$template = str_replace('.', DS, $controller) . $depr . $request->action();
} elseif (false === strpos($template, $depr)) {
$template = str_replace('.', DS, $controller) . $depr . $template;
}
}
} else {
$template = str_replace(['/', ':'], $depr, substr($template, 1));
}
return $path . ltrim($template, '/') . '.' . ltrim(config('template.view_suffix'), '.');
}
/**
* 获取模板文件变量
* @param string $file
* @param string $theme
* @return array
*/
private function getThemeFileMore($file, $theme = "")
{
//TODO 增加缓存
$theme = empty($theme) ? cmf_get_current_theme() : $theme;
// 调试模式下自动更新模板
if (APP_DEBUG) {
$themeModel = new ThemeModel();
$themeModel->updateTheme($theme);
}
$themePath = config('cmf_theme_path');
$file = str_replace('\\', '/', $file);
$file = str_replace('//', '/', $file);
$file = str_replace(['.html', '.php', $themePath . $theme . "/"], '', $file);
$files = Db::name('theme_file')->field('more')->where(['theme' => $theme])->where(function ($query) use ($file) {
$query->where(['is_public' => 1])->whereOr(['file' => $file]);
})->select();
$vars = [];
$widgets = [];
foreach ($files as $file) {
$oldMore = json_decode($file['more'], true);
if (!empty($oldMore['vars'])) {
foreach ($oldMore['vars'] as $varName => $var) {
$vars[$varName] = $var['value'];
}
}
if (!empty($oldMore['widgets'])) {
foreach ($oldMore['widgets'] as $widgetName => $widget) {
$widgetVars = [];
if (!empty($widget['vars'])) {
foreach ($widget['vars'] as $varName => $var) {
$widgetVars[$varName] = $var['value'];
}
}
$widget['vars'] = $widgetVars;
$widgets[$widgetName] = $widget;
}
}
}
return ['vars' => $vars, 'widgets' => $widgets];
}
public function checkUserLogin()
{
$userId = cmf_get_current_user_id();
if (empty($userId)) {
$this->error("用户尚未登录", url("user/login/index"));
}
}
/**
* 检查微信用户登录
*/
public function checkWeChatUserLogin()
{
$userId = cmf_get_current_user_id();
if (empty($userId)) {
$config = [
'oauth' => [
'scopes' => ['snsapi_userinfo'],
'callback' => '/oauth_callback',
],
];
$app = new Application($config);
$oauth = $app->oauth;
$target_url='http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
session('target_url',$target_url);
return $oauth->redirect();
}
}
}
\ No newline at end of file
... ...