作者 郭盛
1 个管道 的构建 通过 耗费 4 秒

用户授权接口以及一些配置文件

1 -<?php  
2 -  
3 -namespace app\api\controller;  
4 -  
5 -use app\common\controller\Api;  
6 -  
7 -/**  
8 - * 示例接口  
9 - */  
10 -class Demo extends Api  
11 -{  
12 -  
13 - //如果$noNeedLogin为空表示所有接口都需要登录才能请求  
14 - //如果$noNeedRight为空表示所有接口都需要验证权限才能请求  
15 - //如果接口已经设置无需登录,那也就无需鉴权了  
16 - //  
17 - // 无需登录的接口,*表示全部  
18 - protected $noNeedLogin = ['test', 'test1'];  
19 - // 无需鉴权的接口,*表示全部  
20 - protected $noNeedRight = ['test2'];  
21 -  
22 - /**  
23 - * 测试方法  
24 - *  
25 - * @ApiTitle (测试名称)  
26 - * @ApiSummary (测试描述信息)  
27 - * @ApiMethod (POST)  
28 - * @ApiRoute (/api/demo/test/id/{id}/name/{name})  
29 - * @ApiHeaders (name=token, type=string, required=true, description="请求的Token")  
30 - * @ApiParams (name="id", type="integer", required=true, description="会员ID")  
31 - * @ApiParams (name="name", type="string", required=true, description="用户名")  
32 - * @ApiParams (name="data", type="object", sample="{'user_id':'int','user_name':'string','profile':{'email':'string','age':'integer'}}", description="扩展数据")  
33 - * @ApiReturnParams (name="code", type="integer", required=true, sample="0")  
34 - * @ApiReturnParams (name="msg", type="string", required=true, sample="返回成功")  
35 - * @ApiReturnParams (name="data", type="object", sample="{'user_id':'int','user_name':'string','profile':{'email':'string','age':'integer'}}", description="扩展数据返回")  
36 - * @ApiReturn ({  
37 - 'code':'1',  
38 - 'msg':'返回成功'  
39 - })  
40 - */  
41 - public function test()  
42 - {  
43 - $this->success('返回成功', $this->request->param());  
44 - }  
45 -  
46 - /**  
47 - * 无需登录的接口  
48 - *  
49 - */  
50 - public function test1()  
51 - {  
52 - $this->success('返回成功', ['action' => 'test1']);  
53 - }  
54 -  
55 - /**  
56 - * 需要登录的接口  
57 - *  
58 - */  
59 - public function test2()  
60 - {  
61 - $this->success('返回成功', ['action' => 'test2']);  
62 - }  
63 -  
64 - /**  
65 - * 需要登录且需要验证有相应组的权限  
66 - *  
67 - */  
68 - public function test3()  
69 - {  
70 - $this->success('返回成功', ['action' => 'test3']);  
71 - }  
72 -  
73 -}  
1 -<?php  
2 -  
3 -namespace app\api\controller;  
4 -  
5 -use app\common\controller\Api;  
6 -use fast\Random;  
7 -  
8 -/**  
9 - * Token接口  
10 - */  
11 -class Token extends Api  
12 -{  
13 - protected $noNeedLogin = [];  
14 - protected $noNeedRight = '*';  
15 -  
16 - /**  
17 - * 检测Token是否过期  
18 - *  
19 - */  
20 - public function check()  
21 - {  
22 - $token = $this->auth->getToken();  
23 - $tokenInfo = \app\common\library\Token::get($token);  
24 - $this->success('', ['token' => $tokenInfo['token'], 'expires_in' => $tokenInfo['expires_in']]);  
25 - }  
26 -  
27 - /**  
28 - * 刷新Token  
29 - *  
30 - */  
31 - public function refresh()  
32 - {  
33 - //删除源Token  
34 - $token = $this->auth->getToken();  
35 - \app\common\library\Token::delete($token);  
36 - //创建新Token  
37 - $token = Random::uuid();  
38 - \app\common\library\Token::set($token, $this->auth->id, 2592000);  
39 - $tokenInfo = \app\common\library\Token::get($token);  
40 - $this->success('', ['token' => $tokenInfo['token'], 'expires_in' => $tokenInfo['expires_in']]);  
41 - }  
42 -}  
@@ -3,318 +3,253 @@ @@ -3,318 +3,253 @@
3 namespace app\api\controller; 3 namespace app\api\controller;
4 4
5 use app\common\controller\Api; 5 use app\common\controller\Api;
6 -use app\common\library\Ems;  
7 -use app\common\library\Sms;  
8 -use fast\Random; 6 +use fast\Http;
  7 +use think\Db;
9 use think\Validate; 8 use think\Validate;
  9 +use wxapp\aes\WXBizDataCrypt;
10 10
11 /** 11 /**
12 - * 会员接口 12 + * 登录接口
13 */ 13 */
14 class User extends Api 14 class User extends Api
15 { 15 {
16 - protected $noNeedLogin = ['login', 'mobilelogin', 'register', 'resetpwd', 'changeemail', 'changemobile', 'third']; 16 + protected $noNeedLogin = '*';
17 protected $noNeedRight = '*'; 17 protected $noNeedRight = '*';
18 18
19 - public function _initialize()  
20 - {  
21 - parent::_initialize();  
22 - } 19 +// public function _initialize()
  20 +// {
  21 +// parent::_initialize();
  22 +// }
23 23
24 /** 24 /**
25 - * 会员中心 25 + * @ApiTitle (获取sessionKey和openid)
  26 + * @ApiSummary (获取sessionKey和openid)
  27 + * @ApiMethod (POST)
  28 + * @ApiRoute (/api/user/getSessionKey)
  29 + * @ApiParams (name="code", type="string", required=true, description="小程序code")
  30 + * @ApiReturn({
  31 + "code": 1,
  32 + "msg": "获取成功",
  33 + "time": "1553839125",
  34 + "data": {
  35 + "session_key": "session_key",//token
  36 + "openid": "openid",//openid
  37 + },
  38 + })
26 */ 39 */
27 - public function index() 40 + public function getSessionKey()
28 { 41 {
29 - $this->success('', ['welcome' => $this->auth->nickname]);  
30 - } 42 + $validate = new Validate([
  43 + 'code' => 'require',
  44 + ]);
31 45
32 - /**  
33 - * 会员登录  
34 - *  
35 - * @param string $account 账号  
36 - * @param string $password 密码  
37 - */  
38 - public function login()  
39 - {  
40 - $account = $this->request->request('account');  
41 - $password = $this->request->request('password');  
42 - if (!$account || !$password) {  
43 - $this->error(__('Invalid parameters')); 46 + $validate->message([
  47 + 'code.require' => '缺少参数code!',
  48 + ]);
  49 +
  50 + $data = $this->request->param();
  51 + if (!$validate->check($data)) {
  52 + $this->error(['code' => '40003', 'msg' => $validate->getError()]);
44 } 53 }
45 - $ret = $this->auth->login($account, $password);  
46 - if ($ret) {  
47 - $data = ['userinfo' => $this->auth->getUserinfo()];  
48 - $this->success(__('Logged in successful'), $data);  
49 - } else {  
50 - $this->error($this->auth->getError()); 54 +
  55 + $code = $data['code'];
  56 + $appId = config('app_id');
  57 + $appSecret = config('app_secret');
  58 +
  59 + $response = "https://api.weixin.qq.com/sns/jscode2session?appid=$appId&secret=$appSecret&js_code=$code&grant_type=authorization_code";
  60 + $response = $this->http_get($response);
  61 + $response = json_decode($response, true);
  62 + if(!empty($response['errcode'])) {
  63 + $this->error('操作失败',$response['errcode']);
51 } 64 }
  65 + $this->success('获取成功',$response);
  66 + }
  67 + //curl get请求
  68 + public function http_get($url){
  69 + $curl = curl_init();//启动一个CURL会话
  70 + curl_setopt($curl, CURLOPT_URL,$url);
  71 + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // 对认证证书来源的检查
  72 + curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); // 从证书中检查SSL加密算法是否存在
  73 + curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
  74 + curl_setopt($curl, CURLOPT_HEADER, false);//不开启header
  75 + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); // 获取的信息以文件流的形式返回
  76 + $result = curl_exec($curl); //执行操作
  77 + curl_close($curl);
  78 + return $result;
52 } 79 }
53 80
54 /** 81 /**
55 - * 手机验证码登录  
56 - *  
57 - * @param string $mobile 手机号  
58 - * @param string $captcha 验证码 82 + * @ApiTitle (小程序登录注册)
  83 + * @ApiSummary (小程序登录注册)
  84 + * @ApiMethod (POST)
  85 + * @ApiRoute (/api/user/login)
  86 + * @ApiParams (name="openid", type="string", required=true, description="openid")
  87 + * @ApiParams (name="session_key", type="string", required=true, description="session_key")
  88 + * @ApiParams (name="encrypted_data", type="string", required=true, description="encrypted_data")
  89 + * @ApiParams (name="iv", type="string", required=true, description="iv")
  90 + * @ApiReturn({
  91 + "code": 1,
  92 + "msg": "登陆成功",
  93 + "time": "1553839125",
  94 + "data": {
  95 + "token": "token",//登录唯一标识
  96 + },
  97 + })
59 */ 98 */
60 - public function mobilelogin() 99 + public function login()
61 { 100 {
62 - $mobile = $this->request->request('mobile');  
63 - $captcha = $this->request->request('captcha');  
64 - if (!$mobile || !$captcha) {  
65 - $this->error(__('Invalid parameters'));  
66 - }  
67 - if (!Validate::regex($mobile, "^1\d{10}$")) {  
68 - $this->error(__('Mobile is incorrect')); 101 + $validate = new Validate([
  102 + 'openid' => 'require',
  103 + 'session_key' => 'require',
  104 + 'encrypted_data' => 'require',
  105 + 'iv' => 'require',
  106 + ]);
  107 +
  108 + $validate->message([
  109 + 'openid.require' => '缺少参数openid!',
  110 + 'session_key.require' => '缺少参数session_key!',
  111 + 'encrypted_data.require' => '缺少参数encrypted_data!',
  112 + 'iv.require' => '缺少参数iv!',
  113 + ]);
  114 +
  115 + $data = $this->request->param();
  116 + if (!$validate->check($data)) {
  117 + $this->error(['code' => '40003', 'msg' => $validate->getError()]);
69 } 118 }
70 - if (!Sms::check($mobile, $captcha, 'mobilelogin')) {  
71 - $this->error(__('Captcha is incorrect')); 119 +
  120 + $appId = config('app_id');
  121 +
  122 + $openid = $data['openid'];
  123 + $sessionKey = $data['session_key'];
  124 +
  125 + $pc = new WXBizDataCrypt($appId, $sessionKey);
  126 + $errCode = $pc->decryptData($data['encrypted_data'], $data['iv'], $wxUserData);
  127 +
  128 + if ($errCode != 0) {
  129 + $this->error('检验数据失败!', ['errCode' => $errCode, 'param' => $data]);
72 } 130 }
73 - $user = \app\common\model\User::getByMobile($mobile);  
74 - if ($user) {  
75 - if ($user->status != 'normal') {  
76 - $this->error(__('Account is locked')); 131 +
  132 + $findThirdPartyUser = Db::name("third")
  133 + ->where('openid', $openid)
  134 + ->where('app_id', $appId)
  135 + ->find();
  136 +
  137 + $currentTime = time();
  138 + $ip = $this->request->ip(0, true);
  139 +
  140 + $wxUserData['sessionKey'] = $sessionKey;
  141 + unset($wxUserData['watermark']);
  142 +
  143 + if ($findThirdPartyUser) {
  144 + $token = generate_user_token($findThirdPartyUser['user_id']);
  145 +
  146 + $userData = [
  147 + 'loginip' => $ip,
  148 + 'logintime' => $currentTime,
  149 + 'login_times' => Db::raw('login_times+1'),
  150 + 'more' => json_encode($wxUserData)
  151 + ];
  152 +
  153 + if (isset($wxUserData['unionId'])) {
  154 + $userData['union_id'] = $wxUserData['unionId'];
77 } 155 }
78 - //如果已经有账号则直接登录  
79 - $ret = $this->auth->direct($user->id);  
80 - } else {  
81 - $ret = $this->auth->register($mobile, Random::alnum(), '', $mobile, []);  
82 - }  
83 - if ($ret) {  
84 - Sms::flush($mobile, 'mobilelogin');  
85 - $data = ['userinfo' => $this->auth->getUserinfo()];  
86 - $this->success(__('Logged in successful'), $data);  
87 - } else {  
88 - $this->error($this->auth->getError());  
89 - }  
90 - }  
91 156
92 - /**  
93 - * 注册会员  
94 - *  
95 - * @param string $username 用户名  
96 - * @param string $password 密码  
97 - * @param string $email 邮箱  
98 - * @param string $mobile 手机号  
99 - * @param string $code 验证码  
100 - */  
101 - public function register()  
102 - {  
103 - $username = $this->request->request('username');  
104 - $password = $this->request->request('password');  
105 - $email = $this->request->request('email');  
106 - $mobile = $this->request->request('mobile');  
107 - $code = $this->request->request('code');  
108 - if (!$username || !$password) {  
109 - $this->error(__('Invalid parameters'));  
110 - }  
111 - if ($email && !Validate::is($email, "email")) {  
112 - $this->error(__('Email is incorrect'));  
113 - }  
114 - if ($mobile && !Validate::regex($mobile, "^1\d{10}$")) {  
115 - $this->error(__('Mobile is incorrect'));  
116 - }  
117 - $ret = Sms::check($mobile, $code, 'register');  
118 - if (!$ret) {  
119 - $this->error(__('Captcha is incorrect'));  
120 - }  
121 - $ret = $this->auth->register($username, $password, $email, $mobile, []);  
122 - if ($ret) {  
123 - $data = ['userinfo' => $this->auth->getUserinfo()];  
124 - $this->success(__('Sign up successful'), $data); 157 + Db::name("third")
  158 + ->where('openid', $openid)
  159 + ->where('app_id', $appId)
  160 + ->update($userData);
  161 + $this->success("登录成功!", ['token' => $token]);
125 } else { 162 } else {
126 - $this->error($this->auth->getError()); 163 + Db::startTrans();
  164 + $userId = Db::name("user")->insertGetId([
  165 + 'status' => 'normal',
  166 + 'id_num' => date('Ymd').str_pad(mt_rand(1, 99999),5,'0',STR_PAD_LEFT).'8',
  167 + 'gender' => $wxUserData['gender'],
  168 + 'nickname' => $wxUserData['nickName'],
  169 + 'avatar' => $wxUserData['avatarUrl'],
  170 + 'joinip' => $ip,
  171 + 'jointime' => $currentTime,
  172 + 'createtime' => $currentTime,
  173 + 'updatetime' => $currentTime,
  174 + 'loginip' => $ip,
  175 + 'logintime' => $currentTime,
  176 + ]);
  177 + $row = Db::name("third")->insert([
  178 + 'openid' => $openid,
  179 + 'user_id' => $userId,
  180 + 'nickname' => $wxUserData['nickName'],
  181 + 'app_id' => $appId,
  182 + 'loginip' => $ip,
  183 + 'union_id' => '',
  184 + 'logintime' => $currentTime,
  185 + 'createtime' => $currentTime,
  186 + 'login_times' => 1,
  187 + 'more' => json_encode($wxUserData)
  188 + ]);
  189 +
  190 + if ($userId && $row) {
  191 + Db::commit();
  192 + $token = generate_user_token($userId);
  193 + $this->success("登录成功!", ['token' => $token]);
  194 + } else {
  195 + Db::rollback();
  196 + $this->error('登录失败');
  197 + }
  198 +
127 } 199 }
128 - }  
129 200
130 - /**  
131 - * 注销登录  
132 - */  
133 - public function logout()  
134 - {  
135 - $this->auth->logout();  
136 - $this->success(__('Logout successful'));  
137 } 201 }
138 -  
139 /** 202 /**
140 - * 修改会员个人信息  
141 - *  
142 - * @param string $avatar 头像地址  
143 - * @param string $username 用户名  
144 - * @param string $nickname 昵称  
145 - * @param string $bio 个人简介 203 + * @ApiTitle (通过code获取token)
  204 + * @ApiSummary (通过code获取token)
  205 + * @ApiMethod (POST)
  206 + * @ApiRoute (/api/user/getToken)
  207 + * @ApiParams (name="code", type="string", required=true, description="code")
  208 + * @ApiReturn({
  209 + "code": 1,
  210 + "msg": "SUCCESS",
  211 + "time": "1553839125",
  212 + "data": {
  213 + "token": "token",//登录唯一标识
  214 + },
  215 + })
146 */ 216 */
147 - public function profile()  
148 - {  
149 - $user = $this->auth->getUser();  
150 - $username = $this->request->request('username');  
151 - $nickname = $this->request->request('nickname');  
152 - $bio = $this->request->request('bio');  
153 - $avatar = $this->request->request('avatar', '', 'trim,strip_tags,htmlspecialchars');  
154 - if ($username) {  
155 - $exists = \app\common\model\User::where('username', $username)->where('id', '<>', $this->auth->id)->find();  
156 - if ($exists) {  
157 - $this->error(__('Username already exists'));  
158 - }  
159 - $user->username = $username;  
160 - }  
161 - $user->nickname = $nickname;  
162 - $user->bio = $bio;  
163 - $user->avatar = $avatar;  
164 - $user->save();  
165 - $this->success();  
166 - } 217 + public function getToken(){
  218 + $validate = new Validate([
  219 + 'code' => 'require',
  220 + ]);
167 221
168 - /**  
169 - * 修改邮箱  
170 - *  
171 - * @param string $email 邮箱  
172 - * @param string $captcha 验证码  
173 - */  
174 - public function changeemail()  
175 - {  
176 - $user = $this->auth->getUser();  
177 - $email = $this->request->post('email');  
178 - $captcha = $this->request->request('captcha');  
179 - if (!$email || !$captcha) {  
180 - $this->error(__('Invalid parameters'));  
181 - }  
182 - if (!Validate::is($email, "email")) {  
183 - $this->error(__('Email is incorrect'));  
184 - }  
185 - if (\app\common\model\User::where('email', $email)->where('id', '<>', $user->id)->find()) {  
186 - $this->error(__('Email already exists'));  
187 - }  
188 - $result = Ems::check($email, $captcha, 'changeemail');  
189 - if (!$result) {  
190 - $this->error(__('Captcha is incorrect'));  
191 - }  
192 - $verification = $user->verification;  
193 - $verification->email = 1;  
194 - $user->verification = $verification;  
195 - $user->email = $email;  
196 - $user->save();  
197 -  
198 - Ems::flush($email, 'changeemail');  
199 - $this->success();  
200 - } 222 + $validate->message([
  223 + 'code.require' => '缺少参数code!',
  224 + ]);
201 225
202 - /**  
203 - * 修改手机号  
204 - *  
205 - * @param string $email 手机号  
206 - * @param string $captcha 验证码  
207 - */  
208 - public function changemobile()  
209 - {  
210 - $user = $this->auth->getUser();  
211 - $mobile = $this->request->request('mobile');  
212 - $captcha = $this->request->request('captcha');  
213 - if (!$mobile || !$captcha) {  
214 - $this->error(__('Invalid parameters'));  
215 - }  
216 - if (!Validate::regex($mobile, "^1\d{10}$")) {  
217 - $this->error(__('Mobile is incorrect')); 226 + $data = $this->request->param();
  227 + if (!$validate->check($data)) {
  228 + $this->error(['code'=>'40003','msg'=>$validate->getError()]);
218 } 229 }
219 - if (\app\common\model\User::where('mobile', $mobile)->where('id', '<>', $user->id)->find()) {  
220 - $this->error(__('Mobile already exists'));  
221 - }  
222 - $result = Sms::check($mobile, $captcha, 'changemobile');  
223 - if (!$result) {  
224 - $this->error(__('Captcha is incorrect'));  
225 - }  
226 - $verification = $user->verification;  
227 - $verification->mobile = 1;  
228 - $user->verification = $verification;  
229 - $user->mobile = $mobile;  
230 - $user->save();  
231 -  
232 - Sms::flush($mobile, 'changemobile');  
233 - $this->success();  
234 - }  
235 230
236 - /**  
237 - * 第三方登录  
238 - *  
239 - * @param string $platform 平台名称  
240 - * @param string $code Code码  
241 - */  
242 - public function third()  
243 - {  
244 - $url = url('user/index');  
245 - $platform = $this->request->request("platform");  
246 - $code = $this->request->request("code");  
247 - $config = get_addon_config('third');  
248 - if (!$config || !isset($config[$platform])) {  
249 - $this->error(__('Invalid parameters')); 231 + $code = $data['code'];
  232 + $appId = config('app_id');
  233 + $appSecret = config('app_secret');
  234 +
  235 + $response = Http::sendRequest("https://api.weixin.qq.com/sns/jscode2session?appid=$appId&secret=$appSecret&js_code=$code&grant_type=authorization_code");
  236 +
  237 + if (!empty($response['errcode'])) {
  238 + $this->error('操作失败:',$response['errcode']);
250 } 239 }
251 - $app = new \addons\third\library\Application($config);  
252 - //通过code换access_token和绑定会员  
253 - $result = $app->{$platform}->getUserInfo(['code' => $code]);  
254 - if ($result) {  
255 - $loginret = \addons\third\library\Service::connect($platform, $result);  
256 - if ($loginret) {  
257 - $data = [  
258 - 'userinfo' => $this->auth->getUserinfo(),  
259 - 'thirdinfo' => $result  
260 - ];  
261 - $this->success(__('Logged in successful'), $data);  
262 - } 240 +
  241 + $third = Db::name('third')->where(['openid'=>json_decode($response['msg'],true)['openid']])->find();
  242 + if(empty($third)){
  243 + $this->error('查无此人');
263 } 244 }
264 - $this->error(__('Operation failed'), $url); 245 + $user_token = Db::name('user_token')->where('user_id',$third['user_id'])->find();
  246 + $data['token'] = $user_token['token'];
  247 + $this->success('SUCCESS',$data);
265 } 248 }
266 249
267 - /**  
268 - * 重置密码  
269 - *  
270 - * @param string $mobile 手机号  
271 - * @param string $newpassword 新密码  
272 - * @param string $captcha 验证码  
273 - */  
274 - public function resetpwd()  
275 - {  
276 - $type = $this->request->request("type");  
277 - $mobile = $this->request->request("mobile");  
278 - $email = $this->request->request("email");  
279 - $newpassword = $this->request->request("newpassword");  
280 - $captcha = $this->request->request("captcha");  
281 - if (!$newpassword || !$captcha) {  
282 - $this->error(__('Invalid parameters'));  
283 - }  
284 - if ($type == 'mobile') {  
285 - if (!Validate::regex($mobile, "^1\d{10}$")) {  
286 - $this->error(__('Mobile is incorrect'));  
287 - }  
288 - $user = \app\common\model\User::getByMobile($mobile);  
289 - if (!$user) {  
290 - $this->error(__('User not found'));  
291 - }  
292 - $ret = Sms::check($mobile, $captcha, 'resetpwd');  
293 - if (!$ret) {  
294 - $this->error(__('Captcha is incorrect'));  
295 - }  
296 - Sms::flush($mobile, 'resetpwd');  
297 - } else {  
298 - if (!Validate::is($email, "email")) {  
299 - $this->error(__('Email is incorrect'));  
300 - }  
301 - $user = \app\common\model\User::getByEmail($email);  
302 - if (!$user) {  
303 - $this->error(__('User not found'));  
304 - }  
305 - $ret = Ems::check($email, $captcha, 'resetpwd');  
306 - if (!$ret) {  
307 - $this->error(__('Captcha is incorrect'));  
308 - }  
309 - Ems::flush($email, 'resetpwd');  
310 - }  
311 - //模拟一次登录  
312 - $this->auth->direct($user->id);  
313 - $ret = $this->auth->changepwd($newpassword, '', true);  
314 - if ($ret) {  
315 - $this->success(__('Reset password successful'));  
316 - } else {  
317 - $this->error($this->auth->getError());  
318 - } 250 + public function member(){
  251 + $this->success('SUCCESS',$this->user);
319 } 252 }
  253 +
  254 +
320 } 255 }
1 -<?php  
2 -  
3 -namespace app\api\controller;  
4 -  
5 -use app\common\controller\Api;  
6 -use app\common\model\User;  
7 -  
8 -/**  
9 - * 验证接口  
10 - */  
11 -class Validate extends Api  
12 -{  
13 - protected $noNeedLogin = '*';  
14 - protected $layout = '';  
15 - protected $error = null;  
16 -  
17 - public function _initialize()  
18 - {  
19 - parent::_initialize();  
20 - }  
21 -  
22 - /**  
23 - * 检测邮箱  
24 - *  
25 - * @param string $email 邮箱  
26 - * @param string $id 排除会员ID  
27 - */  
28 - public function check_email_available()  
29 - {  
30 - $email = $this->request->request('email');  
31 - $id = (int)$this->request->request('id');  
32 - $count = User::where('email', '=', $email)->where('id', '<>', $id)->count();  
33 - if ($count > 0) {  
34 - $this->error(__('邮箱已经被占用'));  
35 - }  
36 - $this->success();  
37 - }  
38 -  
39 - /**  
40 - * 检测用户名  
41 - *  
42 - * @param string $username 用户名  
43 - * @param string $id 排除会员ID  
44 - */  
45 - public function check_username_available()  
46 - {  
47 - $email = $this->request->request('username');  
48 - $id = (int)$this->request->request('id');  
49 - $count = User::where('username', '=', $email)->where('id', '<>', $id)->count();  
50 - if ($count > 0) {  
51 - $this->error(__('用户名已经被占用'));  
52 - }  
53 - $this->success();  
54 - }  
55 -  
56 - /**  
57 - * 检测手机  
58 - *  
59 - * @param string $mobile 手机号  
60 - * @param string $id 排除会员ID  
61 - */  
62 - public function check_mobile_available()  
63 - {  
64 - $mobile = $this->request->request('mobile');  
65 - $id = (int)$this->request->request('id');  
66 - $count = User::where('mobile', '=', $mobile)->where('id', '<>', $id)->count();  
67 - if ($count > 0) {  
68 - $this->error(__('该手机号已经占用'));  
69 - }  
70 - $this->success();  
71 - }  
72 -  
73 - /**  
74 - * 检测手机  
75 - *  
76 - * @param string $mobile 手机号  
77 - */  
78 - public function check_mobile_exist()  
79 - {  
80 - $mobile = $this->request->request('mobile');  
81 - $count = User::where('mobile', '=', $mobile)->count();  
82 - if (!$count) {  
83 - $this->error(__('手机号不存在'));  
84 - }  
85 - $this->success();  
86 - }  
87 -  
88 - /**  
89 - * 检测邮箱  
90 - *  
91 - * @param string $mobile 邮箱  
92 - */  
93 - public function check_email_exist()  
94 - {  
95 - $email = $this->request->request('email');  
96 - $count = User::where('email', '=', $email)->count();  
97 - if (!$count) {  
98 - $this->error(__('邮箱不存在'));  
99 - }  
100 - $this->success();  
101 - }  
102 -  
103 - /**  
104 - * 检测手机验证码  
105 - *  
106 - * @param string $mobile 手机号  
107 - * @param string $captcha 验证码  
108 - * @param string $event 事件  
109 - */  
110 - public function check_sms_correct()  
111 - {  
112 - $mobile = $this->request->request('mobile');  
113 - $captcha = $this->request->request('captcha');  
114 - $event = $this->request->request('event');  
115 - if (!\app\common\library\Sms::check($mobile, $captcha, $event)) {  
116 - $this->error(__('验证码不正确'));  
117 - }  
118 - $this->success();  
119 - }  
120 -  
121 - /**  
122 - * 检测邮箱验证码  
123 - *  
124 - * @param string $email 邮箱  
125 - * @param string $captcha 验证码  
126 - * @param string $event 事件  
127 - */  
128 - public function check_ems_correct()  
129 - {  
130 - $email = $this->request->request('email');  
131 - $captcha = $this->request->request('captcha');  
132 - $event = $this->request->request('event');  
133 - if (!\app\common\library\Ems::check($email, $captcha, $event)) {  
134 - $this->error(__('验证码不正确'));  
135 - }  
136 - $this->success();  
137 - }  
138 -}  
@@ -12,12 +12,21 @@ use think\Loader; @@ -12,12 +12,21 @@ use think\Loader;
12 use think\Request; 12 use think\Request;
13 use think\Response; 13 use think\Response;
14 use think\Route; 14 use think\Route;
  15 +use think\Db;
15 16
16 /** 17 /**
17 * API控制器基类 18 * API控制器基类
18 */ 19 */
19 class Api 20 class Api
20 { 21 {
  22 + //token
  23 + protected $token = '';
  24 +
  25 + //用户 id
  26 + protected $userId = 0;
  27 +
  28 + //用户
  29 + protected $user;
21 30
22 /** 31 /**
23 * @var Request Request 实例 32 * @var Request Request 实例
@@ -91,7 +100,23 @@ class Api @@ -91,7 +100,23 @@ class Api
91 */ 100 */
92 protected function _initialize() 101 protected function _initialize()
93 { 102 {
94 - if (Config::get('url_domain_deploy')) { 103 + $token = $this->request->header('token');
  104 + if(empty($token)){
  105 + return;
  106 + }
  107 + $this->token = $token;
  108 + $user = Db::name('user_token')
  109 + ->alias('a')
  110 + ->field('b.*')
  111 + ->where(['a.token' => $token])
  112 + ->join('__USER__ b', 'a.user_id = b.id')
  113 + ->find();
  114 +
  115 + if (!empty($user)) {
  116 + $this->user = $user;
  117 + $this->userId = $user['id'];
  118 + }
  119 + /*if (Config::get('url_domain_deploy')) {
95 $domain = Route::rules('domain'); 120 $domain = Route::rules('domain');
96 if (isset($domain['api'])) { 121 if (isset($domain['api'])) {
97 if (isset($_SERVER['HTTP_ORIGIN'])) { 122 if (isset($_SERVER['HTTP_ORIGIN'])) {
@@ -155,7 +180,7 @@ class Api @@ -155,7 +180,7 @@ class Api
155 Config::set('upload', array_merge(Config::get('upload'), $upload)); 180 Config::set('upload', array_merge(Config::get('upload'), $upload));
156 181
157 // 加载当前控制器语言包 182 // 加载当前控制器语言包
158 - $this->loadlang($controllername); 183 + $this->loadlang($controllername);*/
159 } 184 }
160 185
161 /** 186 /**
@@ -319,4 +344,35 @@ class Api @@ -319,4 +344,35 @@ class Api
319 344
320 return true; 345 return true;
321 } 346 }
  347 +
  348 + /**
  349 + * 获取当前登录用户的id
  350 + * @return int
  351 + */
  352 + protected function getUserId()
  353 + {
  354 + if (empty($this->userId)) {
  355 + $this->success('');
  356 + }
  357 + $user = Db::name('user')->where(['id'=>$this->userId])->find();
  358 + if($user['status'] != 'normal'){
  359 + $this->error('您已被拉黑');
  360 + }
  361 + return $this->userId;
  362 + }
  363 +
  364 + /**
  365 + * 获取当前用户openid
  366 + * @return mixed
  367 + * @return int
  368 + */
  369 + protected function getOpenId()
  370 + {
  371 + if (empty($this->userId)) {
  372 + $this->error('用户未登录');
  373 + }
  374 + $third = Db::name('third')->where(['user_id'=>$this->userId])->find();
  375 +
  376 + return $third['openid'];
  377 + }
322 } 378 }
  1 +<?php
  2 +
  3 +namespace wxapp\aes;
  4 +/**
  5 + * error code 说明.
  6 + * <ul>
  7 + * <li>-41001: encodingAesKey 非法</li>
  8 + * <li>-41003: aes 解密失败</li>
  9 + * <li>-41004: 解密后得到的buffer非法</li>
  10 + * <li>-41005: base64加密失败</li>
  11 + * <li>-41016: base64解密失败</li>
  12 + * </ul>
  13 + */
  14 +
  15 +class ErrorCode
  16 +{
  17 + public static $OK = 0;
  18 + public static $IllegalAesKey = -41001;
  19 + public static $IllegalIv = -41002;
  20 + public static $IllegalBuffer = -41003;
  21 + public static $DecodeBase64Error = -41004;
  22 +}
  1 +<?php
  2 +namespace wxapp\aes;
  3 +
  4 +/**
  5 + * PKCS7Encoder class
  6 + *
  7 + * 提供基于PKCS7算法的加解密接口.
  8 + */
  9 +class PKCS7Encoder
  10 +{
  11 + public static $block_size = 16;
  12 +
  13 + /**
  14 + * 对需要加密的明文进行填充补位
  15 + * @param $text 需要进行填充补位操作的明文
  16 + * @return 补齐明文字符串
  17 + */
  18 + function encode($text)
  19 + {
  20 + $block_size = PKCS7Encoder::$block_size;
  21 + $text_length = strlen($text);
  22 + //计算需要填充的位数
  23 + $amount_to_pad = PKCS7Encoder::$block_size - ($text_length % PKCS7Encoder::$block_size);
  24 + if ($amount_to_pad == 0) {
  25 + $amount_to_pad = PKCS7Encoder::block_size;
  26 + }
  27 + //获得补位所用的字符
  28 + $pad_chr = chr($amount_to_pad);
  29 + $tmp = "";
  30 + for ($index = 0; $index < $amount_to_pad; $index++) {
  31 + $tmp .= $pad_chr;
  32 + }
  33 + return $text . $tmp;
  34 + }
  35 +
  36 + /**
  37 + * 对解密后的明文进行补位删除
  38 + * @param decrypted 解密后的明文
  39 + * @return 删除填充补位后的明文
  40 + */
  41 + function decode($text)
  42 + {
  43 +
  44 + $pad = ord(substr($text, -1));
  45 + if ($pad < 1 || $pad > 32) {
  46 + $pad = 0;
  47 + }
  48 + return substr($text, 0, (strlen($text) - $pad));
  49 + }
  50 +
  51 +}
  52 +
  1 +<?php
  2 +namespace wxapp\aes;
  3 +
  4 +/**
  5 + * Prpcrypt class
  6 + *
  7 + *
  8 + */
  9 +class Prpcrypt
  10 +{
  11 + public $key;
  12 +
  13 + public function __construct($k)
  14 + {
  15 + $this->key = $k;
  16 + }
  17 +
  18 + /**
  19 + * 对密文进行解密
  20 + * @param string $aesCipher 需要解密的密文
  21 + * @param string $aesIV 解密的初始向量
  22 + * @return string 解密得到的明文
  23 + */
  24 + public function decrypt($aesCipher, $aesIV)
  25 + {
  26 +
  27 + if (function_exists('mcrypt_module_open')) {
  28 + try {
  29 +
  30 + $module = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
  31 +
  32 + mcrypt_generic_init($module, $this->key, $aesIV);
  33 +
  34 + //解密
  35 + $decrypted = mdecrypt_generic($module, $aesCipher);
  36 + mcrypt_generic_deinit($module);
  37 + mcrypt_module_close($module);
  38 + } catch (\Exception $e) {
  39 + return [ErrorCode::$IllegalBuffer, null];
  40 + }
  41 + } else if (function_exists('openssl_decrypt')) {
  42 +
  43 + $decrypted = openssl_decrypt($aesCipher, 'AES-128-CBC', $this->key, OPENSSL_RAW_DATA, $aesIV);
  44 +
  45 + if ($decrypted === false) return [ErrorCode::$IllegalBuffer, null];
  46 + }
  47 +
  48 +
  49 + try {
  50 + //去除补位字符
  51 + $pkc_encoder = new PKCS7Encoder;
  52 + $result = $pkc_encoder->decode($decrypted);
  53 +
  54 + } catch (\Exception $e) {
  55 + //print $e;
  56 + return [ErrorCode::$IllegalBuffer, null];
  57 + }
  58 + return [0, $result];
  59 + }
  60 +}
  1 +<?php
  2 +namespace wxapp\aes;
  3 +/**
  4 + * 对微信小程序用户加密数据进行解密.
  5 + *
  6 + * @copyright Copyright (c) 1998-2014 Tencent Inc.
  7 + */
  8 +
  9 +
  10 +class WXBizDataCrypt
  11 +{
  12 + private $appid;
  13 + private $sessionKey;
  14 +
  15 + /**
  16 + * 构造函数
  17 + * @param $sessionKey string 用户在小程序登录后获取的会话密钥
  18 + * @param $appid string 小程序的appid
  19 + */
  20 + public function __construct($appid, $sessionKey)
  21 + {
  22 + $this->sessionKey = $sessionKey;
  23 + $this->appid = $appid;
  24 + }
  25 +
  26 +
  27 + /**
  28 + * 检验数据的真实性,并且获取解密后的明文.
  29 + * @param $encryptedData string 加密的用户数据
  30 + * @param $iv string 与用户数据一同返回的初始向量
  31 + * @param $data string 解密后的原文
  32 + *
  33 + * @return int 成功0,失败返回对应的错误码
  34 + */
  35 + public function decryptData($encryptedData, $iv, &$data)
  36 + {
  37 + if (strlen($this->sessionKey) != 24) {
  38 + return ErrorCode::$IllegalAesKey;
  39 + }
  40 + $aesKey = base64_decode($this->sessionKey);
  41 +
  42 +
  43 + if (strlen($iv) != 24) {
  44 + return ErrorCode::$IllegalIv;
  45 + }
  46 + $aesIV = base64_decode($iv);
  47 +
  48 + $aesCipher = base64_decode($encryptedData);
  49 +
  50 + $pc = new Prpcrypt($aesKey);
  51 + $result = $pc->decrypt($aesCipher, $aesIV);
  52 +
  53 + if ($result[0] != 0) {
  54 + return $result[0];
  55 + }
  56 +
  57 + $dataObj = json_decode($result[1], true);
  58 + if (empty($dataObj)) {
  59 + return ErrorCode::$IllegalBuffer;
  60 + }
  61 + if ($dataObj['watermark']['appid'] != $this->appid) {
  62 + return ErrorCode::$IllegalBuffer;
  63 + }
  64 + $data = $dataObj;
  65 + return ErrorCode::$OK;
  66 + }
  67 +
  68 +}
  69 +
  1 +<?php
  2 +
  3 +use wxapp\aes\WXBizDataCrypt;
  4 +
  5 +$appid = 'wx4f4bc4dec97d474b';
  6 +$sessionKey = 'tiihtNczf5v6AKRyjwEUhQ==';
  7 +
  8 +$encryptedData = "CiyLU1Aw2KjvrjMdj8YKliAjtP4gsMZM
  9 + QmRzooG2xrDcvSnxIMXFufNstNGTyaGS
  10 + 9uT5geRa0W4oTOb1WT7fJlAC+oNPdbB+
  11 + 3hVbJSRgv+4lGOETKUQz6OYStslQ142d
  12 + NCuabNPGBzlooOmB231qMM85d2/fV6Ch
  13 + evvXvQP8Hkue1poOFtnEtpyxVLW1zAo6
  14 + /1Xx1COxFvrc2d7UL/lmHInNlxuacJXw
  15 + u0fjpXfz/YqYzBIBzD6WUfTIF9GRHpOn
  16 + /Hz7saL8xz+W//FRAUid1OksQaQx4CMs
  17 + 8LOddcQhULW4ucetDf96JcR3g0gfRK4P
  18 + C7E/r7Z6xNrXd2UIeorGj5Ef7b1pJAYB
  19 + 6Y5anaHqZ9J6nKEBvB4DnNLIVWSgARns
  20 + /8wR2SiRS7MNACwTyrGvt9ts8p12PKFd
  21 + lqYTopNHR1Vf7XjfhQlVsAJdNiKdYmYV
  22 + oKlaRv85IfVunYzO0IKXsyl7JCUjCpoG
  23 + 20f0a04COwfneQAGGwd5oa+T8yO5hzuy
  24 + Db/XcxxmK01EpqOyuxINew==";
  25 +
  26 +$iv = 'r7BXXKkLb8qrSNn05n0qiA==';
  27 +
  28 +$pc = new WXBizDataCrypt($appid, $sessionKey);
  29 +$errCode = $pc->decryptData($encryptedData, $iv, $data);
  30 +
  31 +if ($errCode == 0) {
  32 + print($data . "\n");
  33 +} else {
  34 + print($errCode . "\n");
  35 +}
  1 +<?php
  2 +namespace wxapp\pay;
  3 +/*
  4 + * 小程序微信支付
  5 + */
  6 +class WeixinPay {
  7 + protected $appid;
  8 + protected $mch_id;
  9 + protected $key;
  10 + protected $openid;
  11 + protected $out_trade_no;
  12 + protected $body;
  13 + protected $total_fee;
  14 + protected $notify_url;
  15 + function __construct() {
  16 + $this->appid = config('app_id');
  17 + $this->mch_id = config('wx_mch_id');
  18 + $this->key = config('wx_pay_key');
  19 +
  20 + }
  21 + public function pay($openid,$out_trade_no,$body,$total_fee,$notify_url) {
  22 + $this->openid = $openid;
  23 + $this->out_trade_no = $out_trade_no;
  24 + $this->body = $body;
  25 + $this->total_fee = $total_fee;
  26 + $this->notify_url = $notify_url;
  27 + //统一下单接口
  28 + $return = $this->weixinapp();
  29 + return $return;
  30 + }
  31 + //统一下单接口
  32 + protected function unifiedorder() {
  33 + $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
  34 + $parameters = array(
  35 + 'appid' => $this->appid, //小程序ID
  36 + 'mch_id' => $this->mch_id, //商户号
  37 + 'nonce_str' => $this->createNoncestr(), //随机字符串
  38 + 'body' => $this->body,
  39 + 'out_trade_no'=> $this->out_trade_no,
  40 + 'total_fee' => 1,//$this->total_fee*100,
  41 + 'spbill_create_ip' => get_client_ip(0,true),
  42 + 'notify_url' => $this->notify_url,
  43 + 'openid' => $this->openid, //用户id
  44 + 'trade_type' => 'JSAPI'//交易类型
  45 + );
  46 + //统一下单签名
  47 + $parameters['sign'] = $this->getSign($parameters);
  48 + $xmlData = $this->arrayToXml($parameters);
  49 + $return = $this->xmlToArray($this->postXmlCurl($xmlData, $url, 60));
  50 + return $return;
  51 + }
  52 + private static function postXmlCurl($xml, $url, $second = 30)
  53 + {
  54 + $ch = curl_init();
  55 + //设置超时
  56 + curl_setopt($ch, CURLOPT_TIMEOUT, $second);
  57 + curl_setopt($ch, CURLOPT_URL, $url);
  58 + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
  59 + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); //严格校验
  60 + //设置header
  61 + curl_setopt($ch, CURLOPT_HEADER, FALSE);
  62 + //要求结果为字符串且输出到屏幕上
  63 + curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
  64 + //post提交方式
  65 + curl_setopt($ch, CURLOPT_POST, TRUE);
  66 + curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
  67 + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20);
  68 + curl_setopt($ch, CURLOPT_TIMEOUT, 40);
  69 + set_time_limit(0);
  70 + //运行curl
  71 + $data = curl_exec($ch);
  72 + //返回结果
  73 + if ($data) {
  74 + curl_close($ch);
  75 + return $data;
  76 + } else {
  77 + $error = curl_errno($ch);
  78 + curl_close($ch);
  79 + throw new ErrorException("curl出错,错误码:$error");
  80 + }
  81 + }
  82 + //数组转换成xml
  83 + private function arrayToXml($arr) {
  84 + $xml = "<root>";
  85 + foreach ($arr as $key => $val) {
  86 + if (is_array($val)) {
  87 + $xml .= "<" . $key . ">" . $this->arrayToXml($val) . "</" . $key . ">";
  88 + } else {
  89 + $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
  90 + }
  91 + }
  92 + $xml .= "</root>";
  93 + return $xml;
  94 + }
  95 + //xml转换成数组
  96 + public function xmlToArray($xml) {
  97 + //禁止引用外部xml实体
  98 + libxml_disable_entity_loader(true);
  99 + $xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
  100 + $val = json_decode(json_encode($xmlstring), true);
  101 + return $val;
  102 + }
  103 + //微信小程序接口
  104 + private function weixinapp() {
  105 + //统一下单接口
  106 + $unifiedorder = $this->unifiedorder();
  107 + if(isset($unifiedorder['return_code'])&&$unifiedorder['return_code']=='FAIL'){
  108 + return $unifiedorder;
  109 + }
  110 + $parameters = array(
  111 + 'appId' => $this->appid, //小程序ID
  112 + 'timeStamp' => '' . time() . '', //时间戳
  113 + 'nonceStr' => $this->createNoncestr(), //随机串
  114 + 'package' => 'prepay_id=' . $unifiedorder['prepay_id'], //数据包
  115 + 'signType' => 'MD5'//签名方式
  116 + );
  117 + //签名
  118 + $parameters['paySign'] = $this->getSign($parameters);
  119 + return $parameters;
  120 + }
  121 + //作用:产生随机字符串,不长于32位
  122 + private function createNoncestr($length = 32) {
  123 + $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
  124 + $str = "";
  125 + for ($i = 0; $i < $length; $i++) {
  126 + $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
  127 + }
  128 + return $str;
  129 + }
  130 + //作用:生成签名
  131 + public function getSign($Obj) {
  132 + foreach ($Obj as $k => $v) {
  133 + $Parameters[$k] = $v;
  134 + }
  135 + //签名步骤一:按字典序排序参数
  136 + ksort($Parameters);
  137 + $String = $this->formatBizQueryParaMap($Parameters, false);
  138 + //签名步骤二:在string后加入KEY
  139 + $String = $String . "&key=" . $this->key;
  140 + //签名步骤三:MD5加密
  141 + $String = md5($String);
  142 + //签名步骤四:所有字符转为大写
  143 + $result_ = strtoupper($String);
  144 + return $result_;
  145 + }
  146 + ///作用:格式化参数,签名过程需要使用
  147 + private function formatBizQueryParaMap($paraMap, $urlencode) {
  148 + $buff = "";
  149 + ksort($paraMap);
  150 + foreach ($paraMap as $k => $v) {
  151 + if ($urlencode) {
  152 + $v = urlencode($v);
  153 + }
  154 + $buff .= $k . "=" . $v . "&";
  155 + }
  156 + $reqPar='';
  157 + if (strlen($buff) > 0) {
  158 + $reqPar = substr($buff, 0, strlen($buff) - 1);
  159 + }
  160 + return $reqPar;
  161 + }
  162 +}
  1 +<?php
  2 +namespace wxapp\pay;
  3 +
  4 +class WeixinRefund {
  5 + //证书目录
  6 + protected $SSLCERT_PATH;
  7 + protected $SSLKEY_PATH;
  8 + protected $appid;
  9 + protected $mchid;
  10 + protected $key;
  11 + protected $openid;
  12 + protected $outTradeNo;
  13 + protected $totalFee;
  14 + protected $outRefundNo;
  15 + protected $refundFee;
  16 +
  17 + function __construct(){
  18 + //初始化退款类需要的变量
  19 + $this->appid = config('app_id');
  20 + $this->mchid = config('wx_mch_id');
  21 + $this->key = config('wx_pay_key');
  22 + $this->SSLCERT_PATH = config('cert_path');
  23 + $this->SSLKEY_PATH = config('key_path');
  24 + }
  25 + public function refund($openid,$outTradeNo,$totalFee,$outRefundNo,$refundFee){
  26 + $this->openid = $openid;
  27 + $this->outTradeNo = $outTradeNo;
  28 + $this->totalFee = $totalFee;
  29 + $this->outRefundNo = $outRefundNo;
  30 + $this->refundFee = $refundFee;
  31 + //对外暴露的退款接口
  32 + $result = $this->wxrefundapi();
  33 + return $result;
  34 + }
  35 + private function wxrefundapi(){
  36 + //通过微信api进行退款流程
  37 + $parma = array(
  38 + 'appid'=> $this->appid,
  39 + 'mch_id'=> $this->mchid,
  40 + 'nonce_str'=> $this->createNoncestr(),
  41 + 'out_refund_no'=> $this->outRefundNo,//退款订单号
  42 + 'out_trade_no'=> $this->outTradeNo,//商户订单号
  43 + 'total_fee'=> $this->totalFee*100,//订单总金额
  44 + 'refund_fee'=> $this->refundFee*100,//申请退款金额
  45 + );
  46 + $parma['sign'] = $this->getSign($parma);
  47 + $xmldata = $this->arrayToXml($parma);
  48 + $xmlresult = $this->postXmlSSLCurl($xmldata,'https://api.mch.weixin.qq.com/secapi/pay/refund');
  49 + $result = $this->xmlToArray($xmlresult);
  50 + return $result;
  51 + }
  52 + //作用:产生随机字符串,不长于32位
  53 + private function createNoncestr($length = 32) {
  54 + $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
  55 + $str = "";
  56 + for ($i = 0; $i < $length; $i++) {
  57 + $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
  58 + }
  59 + return $str;
  60 + }
  61 + //作用:生成签名
  62 + private function getSign($Obj) {
  63 + foreach ($Obj as $k => $v) {
  64 + $Parameters[$k] = $v;
  65 + }
  66 + //签名步骤一:按字典序排序参数
  67 + ksort($Parameters);
  68 + $String = $this->formatBizQueryParaMap($Parameters, false);
  69 + //签名步骤二:在string后加入KEY
  70 + $String = $String . "&key=" . $this->key;
  71 + //签名步骤三:MD5加密
  72 + $String = md5($String);
  73 + //签名步骤四:所有字符转为大写
  74 + $result_ = strtoupper($String);
  75 + return $result_;
  76 + }
  77 + //数组转换成xml
  78 + private function arrayToXml($arr) {
  79 + $xml = "<root>";
  80 + foreach ($arr as $key => $val) {
  81 + if (is_array($val)) {
  82 + $xml .= "<" . $key . ">" . arrayToXml($val) . "</" . $key . ">";
  83 + } else {
  84 + $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
  85 + }
  86 + }
  87 + $xml .= "</root>";
  88 + return $xml;
  89 + }
  90 + //xml转换成数组
  91 + private function xmlToArray($xml) {
  92 + //禁止引用外部xml实体
  93 + libxml_disable_entity_loader(true);
  94 + $xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
  95 + $val = json_decode(json_encode($xmlstring), true);
  96 + return $val;
  97 + }
  98 + //需要使用证书的请求
  99 + function postXmlSSLCurl($xml,$url,$second=30){
  100 + $ch = curl_init();
  101 + //超时时间
  102 + curl_setopt($ch,CURLOPT_TIMEOUT,$second);
  103 + //这里设置代理,如果有的话
  104 + //curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
  105 + //curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
  106 + curl_setopt($ch,CURLOPT_URL, $url);
  107 + curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
  108 + curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);
  109 + //设置header
  110 + curl_setopt($ch,CURLOPT_HEADER,FALSE);
  111 + //要求结果为字符串且输出到屏幕上
  112 + curl_setopt($ch,CURLOPT_RETURNTRANSFER,TRUE);
  113 + //设置证书
  114 + //使用证书:cert 与 key 分别属于两个.pem文件
  115 + //默认格式为PEM,可以注释
  116 + curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
  117 + curl_setopt($ch,CURLOPT_SSLCERT, $this->SSLCERT_PATH);
  118 + //默认格式为PEM,可以注释
  119 + curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
  120 + curl_setopt($ch,CURLOPT_SSLKEY, $this->SSLKEY_PATH);
  121 + //post提交方式
  122 + curl_setopt($ch,CURLOPT_POST, true);
  123 + curl_setopt($ch,CURLOPT_POSTFIELDS,$xml);
  124 + $data = curl_exec($ch);
  125 + //返回结果
  126 + if($data){
  127 + curl_close($ch);
  128 + return $data;
  129 + } else {
  130 + $error = curl_errno($ch);
  131 + echo "curl出错,错误码:$error"."<br>";
  132 + curl_close($ch);
  133 + return false;
  134 + }
  135 + }
  136 + ///作用:格式化参数,签名过程需要使用
  137 + private function formatBizQueryParaMap($paraMap, $urlencode) {
  138 + $buff = "";
  139 + ksort($paraMap);
  140 + foreach ($paraMap as $k => $v) {
  141 + if ($urlencode) {
  142 + $v = urlencode($v);
  143 + }
  144 + $buff .= $k . "=" . $v . "&";
  145 + }
  146 + $reqPar = '';
  147 + if (strlen($buff) > 0) {
  148 + $reqPar = substr($buff, 0, strlen($buff) - 1);
  149 + }
  150 + return $reqPar;
  151 + }
  152 +}
此 diff 太大无法显示。