作者 李忠强

更新

要显示太多修改。

为保证性能只显示 44 of 44+ 个文件。

1 -{  
2 - "directory": "public/assets/libs",  
3 - "ignoredDependencies": [  
4 - "es6-promise",  
5 - "file-saver",  
6 - "html2canvas",  
7 - "jspdf",  
8 - "jspdf-autotable"  
9 - ]  
10 -}  
1 -[app]  
2 -debug = false  
3 -trace = false  
4 -  
5 -[database]  
6 -hostname = 127.0.0.1  
7 -database = fastadmin  
8 -username = root  
9 -password = root  
10 -hostport = 3306  
11 -prefix = fa_  
1 -/runtime/*  
2 -/public/uploads/*  
3 -/public/api.html  
4 -.idea  
5 -composer.lock  
6 -*.log  
7 -*.css.map  
8 -!.gitkeep  
9 -.env  
10 -.svn  
11 -.vscode  
12 -node_modules  
1 -Apache License  
2 -Version 2.0, January 2004  
3 -http://www.apache.org/licenses/  
4 -  
5 -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION  
6 -  
7 -1. Definitions.  
8 -  
9 -"License" shall mean the terms and conditions for use, reproduction, and  
10 -distribution as defined by Sections 1 through 9 of this document.  
11 -  
12 -"Licensor" shall mean the copyright owner or entity authorized by the copyright  
13 -owner that is granting the License.  
14 -  
15 -"Legal Entity" shall mean the union of the acting entity and all other entities  
16 -that control, are controlled by, or are under common control with that entity.  
17 -For the purposes of this definition, "control" means (i) the power, direct or  
18 -indirect, to cause the direction or management of such entity, whether by  
19 -contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the  
20 -outstanding shares, or (iii) beneficial ownership of such entity.  
21 -  
22 -"You" (or "Your") shall mean an individual or Legal Entity exercising  
23 -permissions granted by this License.  
24 -  
25 -"Source" form shall mean the preferred form for making modifications, including  
26 -but not limited to software source code, documentation source, and configuration  
27 -files.  
28 -  
29 -"Object" form shall mean any form resulting from mechanical transformation or  
30 -translation of a Source form, including but not limited to compiled object code,  
31 -generated documentation, and conversions to other media types.  
32 -  
33 -"Work" shall mean the work of authorship, whether in Source or Object form, made  
34 -available under the License, as indicated by a copyright notice that is included  
35 -in or attached to the work (an example is provided in the Appendix below).  
36 -  
37 -"Derivative Works" shall mean any work, whether in Source or Object form, that  
38 -is based on (or derived from) the Work and for which the editorial revisions,  
39 -annotations, elaborations, or other modifications represent, as a whole, an  
40 -original work of authorship. For the purposes of this License, Derivative Works  
41 -shall not include works that remain separable from, or merely link (or bind by  
42 -name) to the interfaces of, the Work and Derivative Works thereof.  
43 -  
44 -"Contribution" shall mean any work of authorship, including the original version  
45 -of the Work and any modifications or additions to that Work or Derivative Works  
46 -thereof, that is intentionally submitted to Licensor for inclusion in the Work  
47 -by the copyright owner or by an individual or Legal Entity authorized to submit  
48 -on behalf of the copyright owner. For the purposes of this definition,  
49 -"submitted" means any form of electronic, verbal, or written communication sent  
50 -to the Licensor or its representatives, including but not limited to  
51 -communication on electronic mailing lists, source code control systems, and  
52 -issue tracking systems that are managed by, or on behalf of, the Licensor for  
53 -the purpose of discussing and improving the Work, but excluding communication  
54 -that is conspicuously marked or otherwise designated in writing by the copyright  
55 -owner as "Not a Contribution."  
56 -  
57 -"Contributor" shall mean Licensor and any individual or Legal Entity on behalf  
58 -of whom a Contribution has been received by Licensor and subsequently  
59 -incorporated within the Work.  
60 -  
61 -2. Grant of Copyright License.  
62 -  
63 -Subject to the terms and conditions of this License, each Contributor hereby  
64 -grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,  
65 -irrevocable copyright license to reproduce, prepare Derivative Works of,  
66 -publicly display, publicly perform, sublicense, and distribute the Work and such  
67 -Derivative Works in Source or Object form.  
68 -  
69 -3. Grant of Patent License.  
70 -  
71 -Subject to the terms and conditions of this License, each Contributor hereby  
72 -grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,  
73 -irrevocable (except as stated in this section) patent license to make, have  
74 -made, use, offer to sell, sell, import, and otherwise transfer the Work, where  
75 -such license applies only to those patent claims licensable by such Contributor  
76 -that are necessarily infringed by their Contribution(s) alone or by combination  
77 -of their Contribution(s) with the Work to which such Contribution(s) was  
78 -submitted. If You institute patent litigation against any entity (including a  
79 -cross-claim or counterclaim in a lawsuit) alleging that the Work or a  
80 -Contribution incorporated within the Work constitutes direct or contributory  
81 -patent infringement, then any patent licenses granted to You under this License  
82 -for that Work shall terminate as of the date such litigation is filed.  
83 -  
84 -4. Redistribution.  
85 -  
86 -You may reproduce and distribute copies of the Work or Derivative Works thereof  
87 -in any medium, with or without modifications, and in Source or Object form,  
88 -provided that You meet the following conditions:  
89 -  
90 -You must give any other recipients of the Work or Derivative Works a copy of  
91 -this License; and  
92 -You must cause any modified files to carry prominent notices stating that You  
93 -changed the files; and  
94 -You must retain, in the Source form of any Derivative Works that You distribute,  
95 -all copyright, patent, trademark, and attribution notices from the Source form  
96 -of the Work, excluding those notices that do not pertain to any part of the  
97 -Derivative Works; and  
98 -If the Work includes a "NOTICE" text file as part of its distribution, then any  
99 -Derivative Works that You distribute must include a readable copy of the  
100 -attribution notices contained within such NOTICE file, excluding those notices  
101 -that do not pertain to any part of the Derivative Works, in at least one of the  
102 -following places: within a NOTICE text file distributed as part of the  
103 -Derivative Works; within the Source form or documentation, if provided along  
104 -with the Derivative Works; or, within a display generated by the Derivative  
105 -Works, if and wherever such third-party notices normally appear. The contents of  
106 -the NOTICE file are for informational purposes only and do not modify the  
107 -License. You may add Your own attribution notices within Derivative Works that  
108 -You distribute, alongside or as an addendum to the NOTICE text from the Work,  
109 -provided that such additional attribution notices cannot be construed as  
110 -modifying the License.  
111 -You may add Your own copyright statement to Your modifications and may provide  
112 -additional or different license terms and conditions for use, reproduction, or  
113 -distribution of Your modifications, or for any such Derivative Works as a whole,  
114 -provided Your use, reproduction, and distribution of the Work otherwise complies  
115 -with the conditions stated in this License.  
116 -  
117 -5. Submission of Contributions.  
118 -  
119 -Unless You explicitly state otherwise, any Contribution intentionally submitted  
120 -for inclusion in the Work by You to the Licensor shall be under the terms and  
121 -conditions of this License, without any additional terms or conditions.  
122 -Notwithstanding the above, nothing herein shall supersede or modify the terms of  
123 -any separate license agreement you may have executed with Licensor regarding  
124 -such Contributions.  
125 -  
126 -6. Trademarks.  
127 -  
128 -This License does not grant permission to use the trade names, trademarks,  
129 -service marks, or product names of the Licensor, except as required for  
130 -reasonable and customary use in describing the origin of the Work and  
131 -reproducing the content of the NOTICE file.  
132 -  
133 -7. Disclaimer of Warranty.  
134 -  
135 -Unless required by applicable law or agreed to in writing, Licensor provides the  
136 -Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,  
137 -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,  
138 -including, without limitation, any warranties or conditions of TITLE,  
139 -NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are  
140 -solely responsible for determining the appropriateness of using or  
141 -redistributing the Work and assume any risks associated with Your exercise of  
142 -permissions under this License.  
143 -  
144 -8. Limitation of Liability.  
145 -  
146 -In no event and under no legal theory, whether in tort (including negligence),  
147 -contract, or otherwise, unless required by applicable law (such as deliberate  
148 -and grossly negligent acts) or agreed to in writing, shall any Contributor be  
149 -liable to You for damages, including any direct, indirect, special, incidental,  
150 -or consequential damages of any character arising as a result of this License or  
151 -out of the use or inability to use the Work (including but not limited to  
152 -damages for loss of goodwill, work stoppage, computer failure or malfunction, or  
153 -any and all other commercial damages or losses), even if such Contributor has  
154 -been advised of the possibility of such damages.  
155 -  
156 -9. Accepting Warranty or Additional Liability.  
157 -  
158 -While redistributing the Work or Derivative Works thereof, You may choose to  
159 -offer, and charge a fee for, acceptance of support, warranty, indemnity, or  
160 -other liability obligations and/or rights consistent with this License. However,  
161 -in accepting such obligations, You may act only on Your own behalf and on Your  
162 -sole responsibility, not on behalf of any other Contributor, and only if You  
163 -agree to indemnify, defend, and hold each Contributor harmless for any liability  
164 -incurred by, or claims asserted against, such Contributor by reason of your  
165 -accepting any such warranty or additional liability.  
166 -  
167 -END OF TERMS AND CONDITIONS  
168 -  
169 -APPENDIX: How to apply the Apache License to your work  
170 -  
171 -To apply the Apache License to your work, attach the following boilerplate  
172 -notice, with the fields enclosed by brackets "{}" replaced with your own  
173 -identifying information. (Don't include the brackets!) The text should be  
174 -enclosed in the appropriate comment syntax for the file format. We also  
175 -recommend that a file or class name and description of purpose be included on  
176 -the same "printed page" as the copyright notice for easier identification within  
177 -third-party archives.  
178 -  
179 - Copyright 2017 Karson  
180 -  
181 - Licensed under the Apache License, Version 2.0 (the "License");  
182 - you may not use this file except in compliance with the License.  
183 - You may obtain a copy of the License at  
184 -  
185 - http://www.apache.org/licenses/LICENSE-2.0  
186 -  
187 - Unless required by applicable law or agreed to in writing, software  
188 - distributed under the License is distributed on an "AS IS" BASIS,  
189 - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
190 - See the License for the specific language governing permissions and  
191 - limitations under the License.  
1 -FastAdmin是一款基于ThinkPHP+Bootstrap的极速后台开发框架。  
2 -  
3 -  
4 -## 主要特性  
5 -  
6 -* 基于`Auth`验证的权限管理系统  
7 - * 支持无限级父子级权限继承,父级的管理员可任意增删改子级管理员及权限设置  
8 - * 支持单管理员多角色  
9 - * 支持管理子级数据或个人数据  
10 -* 强大的一键生成功能  
11 - * 一键生成CRUD,包括控制器、模型、视图、JS、语言包、菜单、回收站等  
12 - * 一键压缩打包JS和CSS文件,一键CDN静态资源部署  
13 - * 一键生成控制器菜单和规则  
14 - * 一键生成API接口文档  
15 -* 完善的前端功能组件开发  
16 - * 基于`AdminLTE`二次开发  
17 - * 基于`Bootstrap`开发,自适应手机、平板、PC  
18 - * 基于`RequireJS`进行JS模块管理,按需加载  
19 - * 基于`Less`进行样式开发  
20 -* 强大的插件扩展功能,在线安装卸载升级插件  
21 -* 通用的会员模块和API模块  
22 -* 共用同一账号体系的Web端会员中心权限验证和API接口会员权限验证  
23 -* 二级域名部署支持,同时域名支持绑定到应用插件  
24 -* 多语言支持,服务端及客户端支持  
25 -* 支持大文件分片上传、剪切板粘贴上传、拖拽上传,进度条显示,图片上传前压缩  
26 -* 支持表格固定列、固定表头、跨页选择、Excel导出、模板渲染等功能  
27 -* 强大的第三方应用模块支持([CMS](https://www.fastadmin.net/store/cms.html)[博客](https://www.fastadmin.net/store/blog.html)[知识付费问答](https://www.fastadmin.net/store/ask.html)[在线投票系统](https://www.fastadmin.net/store/vote.html)[B2C商城](https://www.fastadmin.net/store/shopro.html)[B2B2C商城](https://www.fastadmin.net/store/wanlshop.html))  
28 -* 支持CMS、博客、知识付费问答无缝整合[Xunsearch全文搜索](https://www.fastadmin.net/store/xunsearch.html)  
29 -* 第三方小程序支持([CMS小程序](https://www.fastadmin.net/store/cms.html)[预订小程序](https://www.fastadmin.net/store/ball.html)[问答小程序](https://www.fastadmin.net/store/ask.html)[点餐小程序](https://www.fastadmin.net/store/unidrink.html)[B2C小程序](https://www.fastadmin.net/store/shopro.html)[B2B2C小程序](https://www.fastadmin.net/store/wanlshop.html)[博客小程序](https://www.fastadmin.net/store/blog.html))  
30 -* 整合第三方短信接口(阿里云、腾讯云短信)  
31 -* 无缝整合第三方云存储(七牛云、阿里云OSS、又拍云)功能,支持云储存分片上传  
32 -* 第三方富文本编辑器支持(Summernote、Kindeditor、百度编辑器)  
33 -* 第三方登录(QQ、微信、微博)整合  
34 -* 第三方支付(微信、支付宝)无缝整合,微信支持PC端扫码支付  
35 -* 丰富的插件应用市场  
36 -  
37 -## 安装使用  
38 -  
39 -https://doc.fastadmin.net  
40 -  
41 -## 在线演示  
42 -  
43 -https://demo.fastadmin.net  
44 -  
45 -用户名:admin  
46 -  
47 -密 码:123456  
48 -  
49 -提 示:演示站数据无法进行修改,请下载源码安装体验全部功能  
50 -  
51 -## 界面截图  
52 -![控制台](https://images.gitee.com/uploads/images/2020/0929/202947_8db2d281_10933.gif "控制台")  
53 -  
54 -## 问题反馈  
55 -  
56 -在使用中有任何问题,请使用以下联系方式联系我们  
57 -  
58 -交流社区: https://ask.fastadmin.net  
59 -  
60 -QQ群: [636393962](https://jq.qq.com/?_wv=1027&k=487PNBb)() [708784003](https://jq.qq.com/?_wv=1027&k=5ObjtwM)(满) [964776039](https://jq.qq.com/?_wv=1027&k=59qjU2P)(3群) [749803490](https://jq.qq.com/?_wv=1027&k=5tczi88)(满) [767103006](https://jq.qq.com/?_wv=1027&k=5Z1U751)() [675115483](https://jq.qq.com/?_wv=1027&k=54I6mts)(6群)  
61 -  
62 -Github: https://github.com/karsonzhang/fastadmin  
63 -  
64 -Gitee: https://gitee.com/karson/fastadmin  
65 -  
66 -## 特别鸣谢  
67 -  
68 -感谢以下的项目,排名不分先后  
69 -  
70 -ThinkPHP:http://www.thinkphp.cn  
71 -  
72 -AdminLTE:https://adminlte.io  
73 -  
74 -Bootstrap:http://getbootstrap.com  
75 -  
76 -jQuery:http://jquery.com  
77 -  
78 -Bootstrap-table:https://github.com/wenzhixin/bootstrap-table  
79 -  
80 -Nice-validator: https://validator.niceue.com  
81 -  
82 -SelectPage: https://github.com/TerryZ/SelectPage  
83 -  
84 -Layer: https://layer.layui.com  
85 -  
86 -DropzoneJS: https://www.dropzonejs.com  
87 -  
88 -  
89 -## 版权信息  
90 -  
91 -FastAdmin遵循Apache2开源协议发布,并提供免费使用。  
92 -  
93 -本项目包含的第三方源码和二进制文件之版权信息另行标注。  
94 -  
95 -版权所有Copyright © 2017-2020 by FastAdmin (https://www.fastadmin.net)  
96 -  
97 -All rights reserved。  
1 -{"files":[],"license":"regular","licenseto":"10789","licensekey":"89rbzyMwR7egBFAo EyUfEJxJ9VFzYuZOURRwgg==","domains":[],"licensecodes":[],"validations":[]}  
1 -<?php  
2 -  
3 -namespace addons\address;  
4 -  
5 -use think\Addons;  
6 -  
7 -/**  
8 - * 地址选择  
9 - * @author [MiniLing] <[laozheyouxiang@163.com]>  
10 - */  
11 -class Address extends Addons  
12 -{  
13 -  
14 - /**  
15 - * 插件安装方法  
16 - * @return bool  
17 - */  
18 - public function install()  
19 - {  
20 - return true;  
21 - }  
22 -  
23 - /**  
24 - * 插件卸载方法  
25 - * @return bool  
26 - */  
27 - public function uninstall()  
28 - {  
29 - return true;  
30 - }  
31 -  
32 -}  
1 -require([], function () {  
2 - //绑定data-toggle=addresspicker属性点击事件  
3 -  
4 - $(document).on('click', "[data-toggle='addresspicker']", function () {  
5 - var that = this;  
6 - var callback = $(that).data('callback');  
7 - var input_id = $(that).data("input-id") ? $(that).data("input-id") : "";  
8 - var lat_id = $(that).data("lat-id") ? $(that).data("lat-id") : "";  
9 - var lng_id = $(that).data("lng-id") ? $(that).data("lng-id") : "";  
10 - var lat = lat_id ? $("#" + lat_id).val() : '';  
11 - var lng = lng_id ? $("#" + lng_id).val() : '';  
12 - var url = "/addons/address/index/select";  
13 - url += (lat && lng) ? '?lat=' + lat + '&lng=' + lng : '';  
14 - Fast.api.open(url, '位置选择', {  
15 - callback: function (res) {  
16 - input_id && $("#" + input_id).val(res.address).trigger("change");  
17 - lat_id && $("#" + lat_id).val(res.lat).trigger("change");  
18 - lng_id && $("#" + lng_id).val(res.lng).trigger("change");  
19 - try {  
20 - //执行回调函数  
21 - if (typeof callback === 'function') {  
22 - callback.call(that, res);  
23 - }  
24 - } catch (e) {  
25 -  
26 - }  
27 - }  
28 - });  
29 - });  
30 -});  
1 -<?php  
2 -  
3 -return [  
4 - [  
5 - 'name' => 'maptype',  
6 - 'title' => '默认地图类型',  
7 - 'type' => 'radio',  
8 - 'content' => [  
9 - 'baidu' => '百度地图',  
10 - 'amap' => '高德地图',  
11 - 'tencent' => '腾讯地图',  
12 - ],  
13 - 'value' => 'tencent',  
14 - 'rule' => 'required',  
15 - 'msg' => '',  
16 - 'tip' => '',  
17 - 'ok' => '',  
18 - 'extend' => '',  
19 - ],  
20 - [  
21 - 'name' => 'location',  
22 - 'title' => '默认检索城市',  
23 - 'type' => 'string',  
24 - 'content' => [],  
25 - 'value' => '天津',  
26 - 'rule' => 'required',  
27 - 'msg' => '',  
28 - 'tip' => '',  
29 - 'ok' => '',  
30 - 'extend' => '',  
31 - ],  
32 - [  
33 - 'name' => 'zoom',  
34 - 'title' => '默认缩放级别',  
35 - 'type' => 'string',  
36 - 'content' => [],  
37 - 'value' => '12',  
38 - 'rule' => 'required',  
39 - 'msg' => '',  
40 - 'tip' => '',  
41 - 'ok' => '',  
42 - 'extend' => '',  
43 - ],  
44 - [  
45 - 'name' => 'lat',  
46 - 'title' => '默认Lat',  
47 - 'type' => 'string',  
48 - 'content' => [],  
49 - 'value' => '39.135927',  
50 - 'rule' => 'required',  
51 - 'msg' => '',  
52 - 'tip' => '',  
53 - 'ok' => '',  
54 - 'extend' => '',  
55 - ],  
56 - [  
57 - 'name' => 'lng',  
58 - 'title' => '默认Lng',  
59 - 'type' => 'string',  
60 - 'content' => [],  
61 - 'value' => '117.21023',  
62 - 'rule' => 'required',  
63 - 'msg' => '',  
64 - 'tip' => '',  
65 - 'ok' => '',  
66 - 'extend' => '',  
67 - ],  
68 - [  
69 - 'name' => 'baidukey',  
70 - 'title' => '百度地图KEY',  
71 - 'type' => 'string',  
72 - 'content' => [],  
73 - 'value' => 'hAeMFHmpyHa2ZjaCH9VVridl',  
74 - 'rule' => 'required',  
75 - 'msg' => '',  
76 - 'tip' => '',  
77 - 'ok' => '',  
78 - 'extend' => '',  
79 - ],  
80 - [  
81 - 'name' => 'amapkey',  
82 - 'title' => '高德地图KEY',  
83 - 'type' => 'string',  
84 - 'content' => [],  
85 - 'value' => '608d75903d29ad471362f8c58c550daf',  
86 - 'rule' => 'required',  
87 - 'msg' => '',  
88 - 'tip' => '',  
89 - 'ok' => '',  
90 - 'extend' => '',  
91 - ],  
92 - [  
93 - 'name' => 'tencentkey',  
94 - 'title' => '腾讯地图KEY',  
95 - 'type' => 'string',  
96 - 'content' => [],  
97 - 'value' => 'FBZBZ-OCF6W-5QXRV-O7G42-GZGRE-UNBWO',  
98 - 'rule' => 'required',  
99 - 'msg' => '',  
100 - 'tip' => '',  
101 - 'ok' => '',  
102 - 'extend' => '',  
103 - ],  
104 - [  
105 - 'name' => '__tips__',  
106 - 'title' => '温馨提示',  
107 - 'type' => '',  
108 - 'content' => [],  
109 - 'value' => '请先申请对应地图的Key,配置后再使用',  
110 - 'rule' => '',  
111 - 'msg' => '',  
112 - 'tip' => '',  
113 - 'ok' => '',  
114 - 'extend' => 'alert-danger-light',  
115 - ],  
116 -];  
1 -<?php  
2 -  
3 -namespace addons\address\controller;  
4 -  
5 -use think\addons\Controller;  
6 -use think\Config;  
7 -use think\Hook;  
8 -  
9 -class Index extends Controller  
10 -{  
11 -  
12 - public function index()  
13 - {  
14 - // 语言检测  
15 - $lang = strip_tags($this->request->langset());  
16 -  
17 - $site = Config::get("site");  
18 -  
19 - // 配置信息  
20 - $config = [  
21 - 'site' => array_intersect_key($site, array_flip(['name', 'cdnurl', 'version', 'timezone', 'languages'])),  
22 - 'upload' => null,  
23 - 'modulename' => 'addons',  
24 - 'controllername' => 'index',  
25 - 'actionname' => 'index',  
26 - 'jsname' => 'addons/address',  
27 - 'moduleurl' => '',  
28 - 'language' => $lang  
29 - ];  
30 - $config = array_merge($config, Config::get("view_replace_str"));  
31 -  
32 - // 配置信息后  
33 - Hook::listen("config_init", $config);  
34 - // 加载当前控制器语言包  
35 - $this->view->assign('site', $site);  
36 - $this->view->assign('config', $config);  
37 -  
38 - return $this->view->fetch();  
39 - }  
40 -  
41 - /**  
42 - * 选择地址  
43 - * @return string  
44 - * @throws \think\Exception  
45 - */  
46 - public function select()  
47 - {  
48 - $config = get_addon_config('address');  
49 - $lat = $this->request->get('lat', $config['lat']);  
50 - $lng = $this->request->get('lng', $config['lng']);  
51 - $this->view->assign('lat', $lat);  
52 - $this->view->assign('lng', $lng);  
53 - $this->view->assign('location', $config['location']);  
54 - return $this->view->fetch('index/' . $config['maptype']);  
55 - }  
56 -  
57 -}  
1 -name = address  
2 -title = 地址选择  
3 -intro = 地图位置选择插件,可返回地址和经纬度  
4 -author = FastAdmin  
5 -website = https://www.fastadmin.net  
6 -version = 1.0.5  
7 -state = 1  
8 -url = /addons/address  
9 -license = regular  
10 -licenseto = 10789  
1 -<!DOCTYPE html>  
2 -<html>  
3 -<head>  
4 - <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">  
5 - <title>地址选择器</title>  
6 - <link rel="stylesheet" href="__CDN__/assets/css/bootstrap.min.css"/>  
7 - <link rel="stylesheet" href="__CDN__/assets/css/fastadmin.min.css"/>  
8 - <link rel="stylesheet" href="__CDN__/assets/libs/font-awesome/css/font-awesome.min.css"/>  
9 - <style type="text/css">  
10 - body {  
11 - margin: 0;  
12 - padding: 0;  
13 - }  
14 -  
15 - #container {  
16 - position: absolute;  
17 - left: 0;  
18 - top: 0;  
19 - right: 0;  
20 - bottom: 0;  
21 - }  
22 -  
23 - .confirm {  
24 - position: absolute;  
25 - bottom: 30px;  
26 - right: 4%;  
27 - z-index: 99;  
28 - height: 50px;  
29 - width: 50px;  
30 - line-height: 50px;  
31 - font-size: 15px;  
32 - text-align: center;  
33 - background-color: white;  
34 - background: #1ABC9C;  
35 - color: white;  
36 - border: none;  
37 - cursor: pointer;  
38 - border-radius: 50%;  
39 - }  
40 -  
41 - .search {  
42 - position: absolute;  
43 - width: 400px;  
44 - top: 0;  
45 - left: 50%;  
46 - padding: 5px;  
47 - margin-left: -200px;  
48 - }  
49 -  
50 - .amap-marker-label {  
51 - border: 0;  
52 - background-color: transparent;  
53 - }  
54 -  
55 - .info {  
56 - padding: .75rem 1.25rem;  
57 - margin-bottom: 1rem;  
58 - border-radius: .25rem;  
59 - position: fixed;  
60 - top: 2rem;  
61 - background-color: white;  
62 - width: auto;  
63 - min-width: 22rem;  
64 - border-width: 0;  
65 - left: 1.8rem;  
66 - box-shadow: 0 2px 6px 0 rgba(114, 124, 245, .5);  
67 - }  
68 - </style>  
69 -</head>  
70 -<body>  
71 -<div class="search">  
72 - <div class="input-group">  
73 - <input type="text" id="place" name="q" class="form-control" placeholder="输入地点"/>  
74 - <span class="input-group-btn">  
75 - <button type="submit" name="search" id="search-btn" class="btn btn-success">  
76 - <i class="fa fa-search"></i>  
77 - </button>  
78 - </span>  
79 - </div>  
80 -</div>  
81 -<div class="confirm">确定</div>  
82 -<div id="container"></div>  
83 -<script type="text/javascript" src="//webapi.amap.com/maps?v=1.4.11&key={$config.amapkey|default=''}&plugin=AMap.ToolBar,AMap.Autocomplete,AMap.PlaceSearch,AMap.Geocoder"></script>  
84 -<!-- UI组件库 1.0 -->  
85 -<script src="//webapi.amap.com/ui/1.0/main.js?v=1.0.11"></script>  
86 -<script src="__CDN__/assets/libs/jquery/dist/jquery.min.js"></script>  
87 -<script type="text/javascript">  
88 - $(function () {  
89 - var as, address, map, lat, lng, geocoder;  
90 - var init = function () {  
91 - AMapUI.loadUI(['misc/PositionPicker', 'misc/PoiPicker'], function (PositionPicker, PoiPicker) {  
92 - //加载PositionPicker,loadUI的路径参数为模块名中 'ui/' 之后的部分  
93 - map = new AMap.Map('container', {  
94 - zoom: parseInt('{$config.zoom}')  
95 - });  
96 - geocoder = new AMap.Geocoder({  
97 - radius: 1000 //范围,默认:500  
98 - });  
99 - var positionPicker = new PositionPicker({  
100 - mode: 'dragMarker',//设定为拖拽地图模式,可选'dragMap'、'dragMarker',默认为'dragMap'  
101 - map: map//依赖地图对象  
102 - });  
103 - //输入提示  
104 - var autoOptions = {  
105 - input: "place"  
106 - };  
107 -  
108 - var relocation = function (lnglat) {  
109 - lng = lnglat.lng;  
110 - lat = lnglat.lat;  
111 - map.panTo([lng, lat]);  
112 - positionPicker.start(lnglat);  
113 - geocoder.getAddress(lng + ',' + lat, function (status, result) {  
114 - if (status === 'complete' && result.regeocode) {  
115 - var address = result.regeocode.formattedAddress;  
116 - var label = '<div class="info">地址:' + address + '<br>经度:' + lng + '<br>纬度:' + lat + '</div>';  
117 - positionPicker.marker.setLabel({  
118 - content: label //显示内容  
119 - });  
120 - } else {  
121 - console.log(JSON.stringify(result));  
122 - }  
123 - });  
124 - };  
125 - var auto = new AMap.Autocomplete(autoOptions);  
126 -  
127 - //构造地点查询类  
128 - var placeSearch = new AMap.PlaceSearch({  
129 - map: map  
130 - });  
131 - //注册监听,当选中某条记录时会触发  
132 - AMap.event.addListener(auto, "select", function (e) {  
133 - placeSearch.setCity(e.poi.adcode);  
134 - placeSearch.search(e.poi.name); //关键字查询查询  
135 - });  
136 - AMap.event.addListener(map, 'click', function (e) {  
137 - relocation(e.lnglat);  
138 - });  
139 -  
140 - //加载工具条  
141 - var tool = new AMap.ToolBar();  
142 - map.addControl(tool);  
143 -  
144 - var poiPicker = new PoiPicker({  
145 - input: 'place',  
146 - placeSearchOptions: {  
147 - map: map,  
148 - pageSize: 6 //关联搜索分页  
149 - }  
150 - });  
151 - poiPicker.on('poiPicked', function (poiResult) {  
152 - poiPicker.hideSearchResults();  
153 - $('.poi .nearpoi').text(poiResult.item.name);  
154 - $('.address .info').text(poiResult.item.address);  
155 - $('#address').val(poiResult.item.address);  
156 - $("#place").val(poiResult.item.name);  
157 -  
158 - relocation(poiResult.item.location);  
159 - });  
160 -  
161 - positionPicker.on('success', function (positionResult) {  
162 - as = positionResult.position;  
163 - address = positionResult.address;  
164 - lat = as.lat;  
165 - lng = as.lng;  
166 - });  
167 - positionPicker.on('fail', function (positionResult) {  
168 - address = '';  
169 - });  
170 - positionPicker.start();  
171 - });  
172 - };  
173 -  
174 - //点击确定后执行回调赋值  
175 - var close = function (data) {  
176 - var index = parent.Layer.getFrameIndex(window.name);  
177 - var callback = parent.$("#layui-layer" + index).data("callback");  
178 - //再执行关闭  
179 - parent.Layer.close(index);  
180 - //再调用回传函数  
181 - if (typeof callback === 'function') {  
182 - callback.call(undefined, data);  
183 - }  
184 - };  
185 -  
186 - //点击搜索按钮  
187 - $(document).on('click', '.confirm', function () {  
188 - var zoom = map.getZoom();  
189 - var data = {lat: lat, lng: lng, zoom: zoom, address: address};  
190 - close(data);  
191 - });  
192 - init();  
193 - });  
194 -</script>  
195 -</body>  
196 -</html>  
1 -<!DOCTYPE html>  
2 -<html>  
3 -<head>  
4 - <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">  
5 - <title>地址选择器</title>  
6 - <link rel="stylesheet" href="__CDN__/assets/css/bootstrap.min.css"/>  
7 - <link rel="stylesheet" href="__CDN__/assets/css/fastadmin.min.css"/>  
8 - <link rel="stylesheet" href="__CDN__/assets/libs/font-awesome/css/font-awesome.min.css"/>  
9 - <style type="text/css">  
10 - body {  
11 - margin: 0;  
12 - padding: 0;  
13 - }  
14 -  
15 - #container {  
16 - position: absolute;  
17 - left: 0;  
18 - top: 0;  
19 - right: 0;  
20 - bottom: 0;  
21 - }  
22 -  
23 - .confirm {  
24 - position: absolute;  
25 - bottom: 30px;  
26 - right: 4%;  
27 - z-index: 99;  
28 - height: 50px;  
29 - width: 50px;  
30 - line-height: 50px;  
31 - font-size: 15px;  
32 - text-align: center;  
33 - background-color: white;  
34 - background: #1ABC9C;  
35 - color: white;  
36 - border: none;  
37 - cursor: pointer;  
38 - border-radius: 50%;  
39 - }  
40 -  
41 - .search {  
42 - position: absolute;  
43 - width: 400px;  
44 - top: 0;  
45 - left: 50%;  
46 - padding: 5px;  
47 - margin-left: -200px;  
48 - }  
49 -  
50 - label.BMapLabel {  
51 - max-width: inherit;  
52 - padding: .75rem 1.25rem;  
53 - margin-bottom: 1rem;  
54 - background-color: white;  
55 - width: auto;  
56 - min-width: 22rem;  
57 - border: none;  
58 - box-shadow: 0 2px 6px 0 rgba(114, 124, 245, .5);  
59 - }  
60 -  
61 - </style>  
62 -</head>  
63 -<body>  
64 -<div class="search">  
65 - <div class="input-group">  
66 - <input type="text" id="place" name="q" class="form-control" placeholder="输入地点"/>  
67 - <div id="searchResultPanel" style="border:1px solid #C0C0C0;width:150px;height:auto; display:none;"></div>  
68 - <span class="input-group-btn">  
69 - <button type="button" name="search" id="address" class="btn btn-success">  
70 - <i class="fa fa-search"></i>  
71 - </button>  
72 - </span>  
73 - </div>  
74 -</div>  
75 -<div class="confirm">确定</div>  
76 -<div id="container"></div>  
77 -<script type="text/javascript" src="//api.map.baidu.com/api?v=2.0&ak={$config.baidukey|default=''}"></script>  
78 -<script src="__CDN__/assets/libs/jquery/dist/jquery.min.js"></script>  
79 -<script type="text/javascript">  
80 - $(function () {  
81 - // 百度地图API功能  
82 - function G(id) {  
83 - return document.getElementById(id);  
84 - }  
85 -  
86 - var map, marker, searchService, address = null, lng, lat;  
87 -  
88 - var init = function () {  
89 - map = new BMap.Map("container"); // 创建地图实例  
90 - var point = new BMap.Point({$lng}, {$lat}); // 创建点坐标  
91 - map.enableScrollWheelZoom(true); //开启鼠标滚轮缩放  
92 - map.centerAndZoom(point, parseInt("{$config.zoom}")); // 初始化地图,设置中心点坐标和地图级别  
93 -  
94 - var size = new BMap.Size(10, 20);  
95 - map.addControl(new BMap.CityListControl({  
96 - anchor: BMAP_ANCHOR_TOP_LEFT,  
97 - offset: size,  
98 - }));  
99 -  
100 - var geoc = new BMap.Geocoder();  
101 -  
102 - var addpoint = function (point) {  
103 - //通过点击百度地图,可以获取到对应的point, 由point的lng、lat属性就可以获取对应的经度纬度  
104 - var pt = point;  
105 - geoc.getLocation(pt, function (rs) {  
106 - //对象可以获取到详细的地址信息  
107 - address = rs.address;  
108 - deletePoint();  
109 - var mk = new BMap.Marker(pt);  
110 - map.addOverlay(mk);  
111 - map.panTo(pt);  
112 - var label = new BMap.Label('<div class="info">地址:' + address + '<br>经度:' + pt.lng + '<br>纬度:' + pt.lat + '</div>', {offset: new BMap.Size(16, 20)});  
113 - label.setStyle({  
114 - border: 'none',  
115 - padding: '.75rem 1.25rem'  
116 - });  
117 - mk.setLabel(label);  
118 - //将对应的HTML元素设置值  
119 - lng = pt.lng;  
120 - lat = pt.lat;  
121 - });  
122 - };  
123 -  
124 - if ("{$lng}" != '' && "{$lat}" != '') {  
125 - addpoint(point);  
126 - }  
127 -  
128 - ac = new BMap.Autocomplete({"input": "place", "location": map}); //建立一个自动完成的对象  
129 - ac.addEventListener("onhighlight", function (e) { //鼠标放在下拉列表上的事件  
130 - var str = "";  
131 - var _value = e.fromitem.value;  
132 - var value = "";  
133 - if (e.fromitem.index > -1) {  
134 - value = _value.province + _value.city + _value.district + _value.street + _value.business;  
135 - }  
136 - str = "FromItem<br />index = " + e.fromitem.index + "<br />value = " + value;  
137 -  
138 - value = "";  
139 - if (e.toitem.index > -1) {  
140 - _value = e.toitem.value;  
141 - value = _value.province + _value.city + _value.district + _value.street + _value.business;  
142 - }  
143 - str += "<br />ToItem<br />index = " + e.toitem.index + "<br />value = " + value;  
144 - G("searchResultPanel").innerHTML = str;  
145 - });  
146 - ac.addEventListener("onconfirm", function (e) { //鼠标点击下拉列表后的事件  
147 - var _value = e.item.value;  
148 - myValue = _value.province + _value.city + _value.district + _value.street + _value.business;  
149 - G("searchResultPanel").innerHTML = "onconfirm<br />index = " + e.item.index + "<br />myValue = " + myValue;  
150 - setPlace();  
151 - });  
152 -  
153 - function setPlace() {  
154 - map.clearOverlays(); //清除地图上所有覆盖物  
155 - function myFun() {  
156 - var result = local.getResults().getPoi(0);  
157 - var pp = result.point; //获取第一个智能搜索的结果  
158 - map.centerAndZoom(pp, 18);  
159 - map.addOverlay(new BMap.Marker(pp)); //添加标注  
160 - lng = pp.lng;  
161 - lat = pp.lat;  
162 - address = result.address;  
163 - }  
164 -  
165 - var local = new BMap.LocalSearch(map, { //智能搜索  
166 - onSearchComplete: myFun  
167 - });  
168 - local.search(myValue);  
169 - }  
170 -  
171 - map.addEventListener("click", function (e) {  
172 - //通过点击百度地图,可以获取到对应的point, 由point的lng、lat属性就可以获取对应的经度纬度  
173 - var pt = e.point;  
174 - addpoint(e.point);  
175 - });  
176 -  
177 - /**  
178 - * 清除覆盖物  
179 - */  
180 - function deletePoint() {  
181 - var allOverlay = map.getOverlays();  
182 - for (var i = 0; i < allOverlay.length; i++) {  
183 - map.removeOverlay(allOverlay[i]);  
184 - }  
185 - }  
186 - };  
187 -  
188 - var close = function (data) {  
189 - var index = parent.Layer.getFrameIndex(window.name);  
190 - var callback = parent.$("#layui-layer" + index).data("callback");  
191 - //再执行关闭  
192 - parent.Layer.close(index);  
193 - //再调用回传函数  
194 - if (typeof callback === 'function') {  
195 - callback.call(undefined, data);  
196 - }  
197 - };  
198 -  
199 - //点击确定后执行回调赋值  
200 - $(document).on('click', '.confirm', function () {  
201 - var zoom = map.getZoom();  
202 - var data = {lat: lat, lng: lng, zoom: zoom, address: address};  
203 - close(data);  
204 - });  
205 -  
206 - init();  
207 - });  
208 -</script>  
209 -</body>  
210 -</html>  
1 -<!DOCTYPE html>  
2 -<html>  
3 -<head>  
4 - <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>  
5 -  
6 - <title>地图位置(经纬度)选择插件 - FastAdmin</title>  
7 -  
8 - <!-- Bootstrap Core CSS -->  
9 - <link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet">  
10 -  
11 - <!-- Custom CSS -->  
12 - <link href="https://cdn.demo.fastadmin.net/assets/css/frontend.css" rel="stylesheet">  
13 -  
14 - <!-- Plugin CSS -->  
15 - <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">  
16 -  
17 - <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->  
18 - <!--[if lt IE 9]>  
19 - <script src="https://cdn.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script>  
20 - <script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script>  
21 - <![endif]-->  
22 -</head>  
23 -<body>  
24 -<div class="container">  
25 -  
26 - <div class="bs-docs-section clearfix">  
27 - <div class="row">  
28 - <div class="col-lg-12">  
29 - <div class="page-header">  
30 - <h2 id="navbar">地图位置(经纬度)选择示例</h2>  
31 - </div>  
32 -  
33 - <div class="bs-component">  
34 - <form action="" method="post" role="form">  
35 - <div class="form-group">  
36 - <label for=""></label>  
37 - <input type="text" class="form-control" name="" id="address" placeholder="地址">  
38 - </div>  
39 - <div class="form-group">  
40 - <label for=""></label>  
41 - <input type="text" class="form-control" name="" id="lng" placeholder="经度">  
42 - </div>  
43 - <div class="form-group">  
44 - <label for=""></label>  
45 - <input type="text" class="form-control" name="" id="lat" placeholder="纬度">  
46 - </div>  
47 -  
48 - <button type="button" class="btn btn-primary" data-toggle='addresspicker' data-input-id="address" data-lng-id="lng" data-lat-id="lat">点击选择地址获取经纬度</button>  
49 - </form>  
50 - </div>  
51 -  
52 - <div class="page-header">  
53 - <h2 id="code">调用代码</h2>  
54 - </div>  
55 - <div class="bs-component">  
56 - <textarea class="form-control" rows="17">  
57 -<form action="" method="post" role="form">  
58 - <div class="form-group">  
59 - <label for=""></label>  
60 - <input type="text" class="form-control" name="" id="address" placeholder="地址">  
61 - </div>  
62 - <div class="form-group">  
63 - <label for=""></label>  
64 - <input type="text" class="form-control" name="" id="lng" placeholder="经度">  
65 - </div>  
66 - <div class="form-group">  
67 - <label for=""></label>  
68 - <input type="text" class="form-control" name="" id="lat" placeholder="纬度">  
69 - </div>  
70 -  
71 - <button type="button" class="btn btn-primary" data-toggle='addresspicker' data-input-id="address" data-lng-id="lng" data-lat-id="lat">点击选择地址获取经纬度</button>  
72 -</form>  
73 - </textarea>  
74 - </div>  
75 - <div class="page-header">  
76 - <h2 id="navbar">参数说明</h2>  
77 - </div>  
78 -  
79 - <div class="bs-component">  
80 - <table class="table table-condensed table-hover">  
81 - <thead>  
82 - <tr>  
83 - <th>参数</th>  
84 - <th>释义</th>  
85 - </tr>  
86 - </thead>  
87 - <tbody>  
88 - <tr>  
89 - <td>data-input-id</td>  
90 - <td>填充地址的文本框ID</td>  
91 - </tr>  
92 - <tr>  
93 - <td>data-lng-id</td>  
94 - <td>填充经度的文本框ID</td>  
95 - </tr>  
96 - <tr>  
97 - <td>data-lat-id</td>  
98 - <td>填充纬度的文本框ID</td>  
99 - </tr>  
100 - </tbody>  
101 - </table>  
102 - </div>  
103 -  
104 - </div>  
105 - </div>  
106 - </div>  
107 -  
108 -</div>  
109 -<script type="text/javascript">  
110 - var require = {  
111 - config: {$config | json_encode  
112 - }  
113 - }  
114 - ;  
115 -</script>  
116 -  
117 -<script>  
118 - require.callback = function () {  
119 - define('addons/address', ['jquery', 'bootstrap', 'frontend', 'template'], function ($, undefined, Frontend, Template) {  
120 - var Controller = {  
121 - index: function () {  
122 - ;  
123 - }  
124 - };  
125 - return Controller;  
126 - });  
127 - define('lang', function () {  
128 - return [];  
129 - });  
130 - }  
131 -</script>  
132 -  
133 -  
134 -<script src="__CDN__/assets/js/require.min.js" data-main="__CDN__/assets/js/require-frontend.min.js?v={$site.version}"></script>  
135 -</body>  
136 -</html>  
1 -<!DOCTYPE html>  
2 -<html>  
3 -<head>  
4 - <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">  
5 - <title>地址选择器</title>  
6 - <link rel="stylesheet" href="__CDN__/assets/css/bootstrap.min.css"/>  
7 - <link rel="stylesheet" href="__CDN__/assets/css/fastadmin.min.css"/>  
8 - <link rel="stylesheet" href="__CDN__/assets/libs/font-awesome/css/font-awesome.min.css"/>  
9 - <style type="text/css">  
10 - body {  
11 - margin: 0;  
12 - padding: 0;  
13 - }  
14 -  
15 - #container {  
16 - position: absolute;  
17 - left: 0;  
18 - top: 0;  
19 - right: 0;  
20 - bottom: 0;  
21 - }  
22 -  
23 - .confirm {  
24 - position: absolute;  
25 - bottom: 30px;  
26 - right: 4%;  
27 - z-index: 99;  
28 - height: 50px;  
29 - width: 50px;  
30 - line-height: 50px;  
31 - font-size: 15px;  
32 - text-align: center;  
33 - background-color: white;  
34 - background: #1ABC9C;  
35 - color: white;  
36 - border: none;  
37 - cursor: pointer;  
38 - border-radius: 50%;  
39 - }  
40 -  
41 - .search {  
42 - position: absolute;  
43 - width: 400px;  
44 - top: 0;  
45 - left: 50%;  
46 - padding: 5px;  
47 - margin-left: -200px;  
48 - }  
49 - </style>  
50 -</head>  
51 -<body>  
52 -<div class="search">  
53 - <div class="input-group">  
54 - <input type="text" id="place" name="q" class="form-control" placeholder="输入地点"/>  
55 - <span class="input-group-btn">  
56 - <button type="submit" name="search" id="search-btn" class="btn btn-success">  
57 - <i class="fa fa-search"></i>  
58 - </button>  
59 - </span>  
60 - </div>  
61 -</div>  
62 -<div class="confirm">确定</div>  
63 -<div id="container"></div>  
64 -<script charset="utf-8" src="//map.qq.com/api/js?v=2.exp&libraries=place&key={$config.tencentkey|default=''}"></script>  
65 -<script src="__CDN__/assets/libs/jquery/dist/jquery.min.js"></script>  
66 -<script type="text/javascript">  
67 - $(function () {  
68 - var map, marker, geocoder, infoWin, searchService, address = null;  
69 - var init = function () {  
70 - var center = new qq.maps.LatLng({$lat}, {$lng});  
71 - map = new qq.maps.Map(document.getElementById('container'), {  
72 - center: center,  
73 - zoom: parseInt("{$config.zoom}")  
74 - });  
75 - //初始化marker  
76 - initmarker(center);  
77 -  
78 - //实例化信息窗口  
79 - infoWin = new qq.maps.InfoWindow({  
80 - map: map  
81 - });  
82 - geocoder = new qq.maps.Geocoder({  
83 - complete: function (result) {  
84 - infoWin.open();  
85 - address = result.detail.addressComponents.province +  
86 - result.detail.addressComponents.city +  
87 - result.detail.addressComponents.district;  
88 - if (result.detail.addressComponents.streetNumber == '') {  
89 - address += result.detail.addressComponents.street;  
90 - } else {  
91 - address += result.detail.addressComponents.streetNumber;  
92 - }  
93 - infoWin.setContent(address);  
94 - infoWin.setPosition(result.detail.location);  
95 - }  
96 - });  
97 - //显示当前marker的位置信息窗口  
98 - geocoder.getAddress(center);  
99 -  
100 - var latlngBounds = new qq.maps.LatLngBounds();  
101 - //查询poi类信息  
102 - searchService = new qq.maps.SearchService({  
103 - complete: function (results) {  
104 - var pois = results.detail.pois;  
105 - for (var i = 0, l = pois.length; i < l; i++) {  
106 - var poi = pois[i];  
107 - latlngBounds.extend(poi.latLng);  
108 - initmarker(poi.latLng);  
109 - //显示当前marker的位置信息窗口  
110 - geocoder.getAddress(poi.latLng);  
111 - }  
112 - map.fitBounds(latlngBounds);  
113 - }  
114 - });  
115 - //实例化自动完成  
116 - var ap = new qq.maps.place.Autocomplete(document.getElementById('place'));  
117 - //添加监听事件  
118 - qq.maps.event.addListener(ap, "confirm", function (res) {  
119 - searchKeyword();  
120 - });  
121 - qq.maps.event.addListener(  
122 - map,  
123 - 'click',  
124 - function (event) {  
125 - try {  
126 - infoWin.setContent('<div style="text-align:center;white-space:nowrap;margin:10px;">加载中</div>');  
127 - var latLng = event.latLng,  
128 - lat = latLng.getLat().toFixed(5),  
129 - lng = latLng.getLng().toFixed(5);  
130 - var location = new qq.maps.LatLng(lat, lng);  
131 - //调用获取位置方法  
132 - geocoder.getAddress(location);  
133 - infoWin.setPosition(location);  
134 - marker.setPosition(location);  
135 - } catch (e) {  
136 - console.log(e);  
137 - }  
138 - }  
139 - );  
140 - };  
141 -  
142 - //实例化marker和监听拖拽结束事件  
143 - var initmarker = function (latLng) {  
144 - marker = new qq.maps.Marker({  
145 - map: map,  
146 - position: latLng,  
147 - draggable: true,  
148 - title: '拖动图标选择位置'  
149 - });  
150 - //监听拖拽结束  
151 - qq.maps.event.addListener(marker, 'dragend', function (event) {  
152 - var latLng = event.latLng,  
153 - lat = latLng.getLat().toFixed(5),  
154 - lng = latLng.getLng().toFixed(5);  
155 - var location = new qq.maps.LatLng(lat, lng);  
156 - //调用获取位置方法  
157 - geocoder.getAddress(location);  
158 - });  
159 - };  
160 - var close = function (data) {  
161 - var index = parent.Layer.getFrameIndex(window.name);  
162 - var callback = parent.$("#layui-layer" + index).data("callback");  
163 - //再执行关闭  
164 - parent.Layer.close(index);  
165 - //再调用回传函数  
166 - if (typeof callback === 'function') {  
167 - callback.call(undefined, data);  
168 - }  
169 - };  
170 -  
171 - //执行搜索方法  
172 - var searchKeyword = function () {  
173 - searchService.clear();//先清除  
174 - marker.setMap(null);  
175 - infoWin.close();  
176 - var keyword = $("#place").val();  
177 - searchService.setLocation("{$location}");//设置默认检索范围(默认为全国),类型可以是坐标或指定的城市名称。  
178 - searchService.setPageIndex(0);//设置检索的特定页数。  
179 - searchService.setPageCapacity(1);//设置每页返回的结果数量。  
180 - searchService.search(keyword);//开始查询  
181 - };  
182 -  
183 - //点击确定后执行回调赋值  
184 - $(document).on('click', '.confirm', function () {  
185 - var as = marker.getPosition();  
186 - var x = as.getLat().toFixed(5);  
187 - var y = as.getLng().toFixed(5);  
188 - var zoom = map.getZoom();  
189 - var data = {lat: x, lng: y, zoom: zoom, address: address};  
190 - close(data);  
191 - });  
192 -  
193 - //点击搜索按钮  
194 - $(document).on('click', '#search-btn', function () {  
195 - if ($("#place").val() == '')  
196 - return;  
197 - searchKeyword();  
198 - });  
199 -  
200 - init();  
201 - });  
202 -</script>  
203 -</body>  
204 -</html>  
1 -{"files":["application\\admin\\controller\\Command.php","application\\admin\\lang\\zh-cn\\command.php","application\\admin\\model\\Command.php","application\\admin\\validate\\Command.php","application\\admin\\view\\command\\add.html","application\\admin\\view\\command\\detail.html","application\\admin\\view\\command\\index.html","public\\assets\\js\\backend\\command.js"],"license":"regular","licenseto":"10789","licensekey":"ogGuqfEhWU5smPv7 ZCMeDKwDoQx8JuH\/Lrj4FA==","domains":[],"licensecodes":[],"validations":[],"menus":["command","command\/index","command\/add","command\/detail","command\/execute","command\/del","command\/multi"]}  
1 -<?php  
2 -  
3 -namespace addons\command;  
4 -  
5 -use app\common\library\Menu;  
6 -use think\Addons;  
7 -  
8 -/**  
9 - * 在线命令插件  
10 - */  
11 -class Command extends Addons  
12 -{  
13 -  
14 - /**  
15 - * 插件安装方法  
16 - * @return bool  
17 - */  
18 - public function install()  
19 - {  
20 - $menu = [  
21 - [  
22 - 'name' => 'command',  
23 - 'title' => '在线命令管理',  
24 - 'icon' => 'fa fa-terminal',  
25 - 'sublist' => [  
26 - ['name' => 'command/index', 'title' => '查看'],  
27 - ['name' => 'command/add', 'title' => '添加'],  
28 - ['name' => 'command/detail', 'title' => '详情'],  
29 - ['name' => 'command/execute', 'title' => '运行'],  
30 - ['name' => 'command/del', 'title' => '删除'],  
31 - ['name' => 'command/multi', 'title' => '批量更新'],  
32 - ]  
33 - ]  
34 - ];  
35 - Menu::create($menu);  
36 - return true;  
37 - }  
38 -  
39 - /**  
40 - * 插件卸载方法  
41 - * @return bool  
42 - */  
43 - public function uninstall()  
44 - {  
45 - Menu::delete('command');  
46 - return true;  
47 - }  
48 -  
49 - /**  
50 - * 插件启用方法  
51 - * @return bool  
52 - */  
53 - public function enable()  
54 - {  
55 - Menu::enable('command');  
56 - return true;  
57 - }  
58 -  
59 - /**  
60 - * 插件禁用方法  
61 - * @return bool  
62 - */  
63 - public function disable()  
64 - {  
65 - Menu::disable('command');  
66 - return true;  
67 - }  
68 -  
69 -}  
1 -<?php  
2 -  
3 -return [  
4 -];  
1 -<?php  
2 -  
3 -namespace addons\command\controller;  
4 -  
5 -use think\addons\Controller;  
6 -  
7 -class Index extends Controller  
8 -{  
9 -  
10 - public function index()  
11 - {  
12 - $this->error("当前插件暂无前台页面");  
13 - }  
14 -  
15 -}  
1 -name = command  
2 -title = 在线命令  
3 -intro = 可在线执行FastAdmin的命令行相关命令  
4 -author = Karson  
5 -website = https://www.fastadmin.net  
6 -version = 1.0.6  
7 -state = 1  
8 -url = /addons/command  
9 -license = regular  
10 -licenseto = 10789  
1 -CREATE TABLE IF NOT EXISTS `__PREFIX__command` (  
2 - `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ID',  
3 - `type` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '类型',  
4 - `params` varchar(1500) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '参数',  
5 - `command` varchar(1500) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '命令',  
6 - `content` text COMMENT '返回结果',  
7 - `executetime` int(10) UNSIGNED DEFAULT NULL COMMENT '执行时间',  
8 - `createtime` int(10) UNSIGNED DEFAULT NULL COMMENT '创建时间',  
9 - `updatetime` int(10) UNSIGNED DEFAULT NULL COMMENT '更新时间',  
10 - `status` enum('successed','failured') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'failured' COMMENT '状态',  
11 - PRIMARY KEY (`id`) USING BTREE  
12 -) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '在线命令表';  
1 -<?php  
2 -  
3 -namespace addons\command\library;  
4 -  
5 -/**  
6 - * Class Output  
7 - */  
8 -class Output extends \think\console\Output  
9 -{  
10 -  
11 - protected $message = [];  
12 -  
13 - public function __construct($driver = 'console')  
14 - {  
15 - parent::__construct($driver);  
16 - }  
17 -  
18 - protected function block($style, $message)  
19 - {  
20 - $this->message[] = $message;  
21 - }  
22 -  
23 - public function getMessage()  
24 - {  
25 - return $this->message;  
26 - }  
27 -  
28 -}  
1 -{"files":["application\\admin\\controller\\Epay.php","public\\assets\\addons\\epay\\css\\common.css","public\\assets\\addons\\epay\\css\\epay.css","public\\assets\\addons\\epay\\images\\alipay.png","public\\assets\\addons\\epay\\images\\expired.png","public\\assets\\addons\\epay\\images\\logo-alipay.png","public\\assets\\addons\\epay\\images\\logo-wechat.png","public\\assets\\addons\\epay\\images\\paid.png","public\\assets\\addons\\epay\\images\\scan.png","public\\assets\\addons\\epay\\images\\screenshot-alipay.png","public\\assets\\addons\\epay\\images\\screenshot-wechat.png","public\\assets\\addons\\epay\\images\\wechat.png","public\\assets\\addons\\epay\\js\\common.js","public\\assets\\addons\\epay\\less\\common.less","public\\assets\\addons\\epay\\less\\epay.less"],"license":"regular","licenseto":"10789","licensekey":"v9xQbPO0C1w4Mnau dX3mcbJWxJ80kiBhb42x1Q==","domains":[],"licensecodes":[],"validations":[]}  
1 -<?php  
2 -  
3 -namespace addons\epay;  
4 -  
5 -use think\Addons;  
6 -use think\Config;  
7 -use think\Loader;  
8 -  
9 -/**  
10 - * 微信支付宝整合插件  
11 - */  
12 -class Epay extends Addons  
13 -{  
14 -  
15 - /**  
16 - * 插件安装方法  
17 - * @return bool  
18 - */  
19 - public function install()  
20 - {  
21 -  
22 - return true;  
23 - }  
24 -  
25 - /**  
26 - * 插件卸载方法  
27 - * @return bool  
28 - */  
29 - public function uninstall()  
30 - {  
31 -  
32 - return true;  
33 - }  
34 -  
35 - /**  
36 - * 插件启用方法  
37 - * @return bool  
38 - */  
39 - public function enable()  
40 - {  
41 -  
42 - return true;  
43 - }  
44 -  
45 - /**  
46 - * 插件禁用方法  
47 - * @return bool  
48 - */  
49 - public function disable()  
50 - {  
51 -  
52 - return true;  
53 - }  
54 -  
55 - /**  
56 - * 添加命名空间  
57 - */  
58 - public function appInit()  
59 - {  
60 - //添加命名空间  
61 - if (!class_exists('\Yansongda\Pay\Pay')) {  
62 - Loader::addNamespace('Yansongda\Pay', ADDON_PATH . 'epay' . DS . 'library' . DS . 'Yansongda' . DS . 'Pay' . DS);  
63 - }  
64 - if (!class_exists('\Yansongda\Supports\Logger')) {  
65 - Loader::addNamespace('Yansongda\Supports', ADDON_PATH . 'epay' . DS . 'library' . DS . 'Yansongda' . DS . 'Supports' . DS);  
66 - }  
67 - }  
68 -  
69 -}  
1 ------BEGIN CERTIFICATE-----  
2 -MIID8DCCAtigAwIBAgIUVNHUlZ6YeeUOeQu96LV6UjGfLHkwDQYJKoZIhvcNAQEL  
3 -BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT  
4 -FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg  
5 -Q0EwHhcNMjIwMTEyMDc1MDM3WhcNMjcwMTExMDc1MDM3WjCBgTETMBEGA1UEAwwK  
6 -MTYxOTE5MzEzMDEbMBkGA1UECgwS5b6u5L+h5ZWG5oi357O757ufMS0wKwYDVQQL  
7 -DCTotLXlt57mqZnlrZDnvZHnu5znp5HmioDmnInpmZDlhazlj7gxCzAJBgNVBAYM  
8 -AkNOMREwDwYDVQQHDAhTaGVuWmhlbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC  
9 -AQoCggEBAMUHCGGVLxl2AJdtGkAB7Ck/V4oLoOZAR0ZtCSEPhuBa840nl1RTt55O  
10 -KT8ZiRneZoBJ5yoegeDWz4gHjGXYkctIiwmmnTHDtdFhcnKvJMW58z3ZA0xAUrG1  
11 -hJSepiQtsaFJSg+XLOCL3773rO9PqwH/vSfpkipqxUapmYKWAYrWrUjyi+BX9hBv  
12 -9GhcATO6DSySMkBm1oAhngA3657WGdyU7YzihVn3IL7X12gjdYoE/DfV1g8Dw6ze  
13 -aN/hSu8GZ+V2+Npn99AJKRSu08EFgw5o7cMacGNhTDPQsc5CXHN/TKpI7cM0FtoP  
14 -BFTh0uo10ebE2eOIe7Nd2RA6I+wPn2kCAwEAAaOBgTB/MAkGA1UdEwQCMAAwCwYD  
15 -VR0PBAQDAgTwMGUGA1UdHwReMFwwWqBYoFaGVGh0dHA6Ly9ldmNhLml0cnVzLmNv  
16 -bS5jbi9wdWJsaWMvaXRydXNjcmw/Q0E9MUJENDIyMEU1MERCQzA0QjA2QUQzOTc1  
17 -NDk4NDZDMDFDM0U4RUJEMjANBgkqhkiG9w0BAQsFAAOCAQEALwQJsqW/yOqlk2mj  
18 -CGuASrOpdUZE22bpTw4ajshd+x+/3d4JYX8f7g7CfoJm44hs97lu3FqBr2akUJOo  
19 -xmf1RG0hEVzqy5o/rUvKKay2/gIky+m0tKNAlp2aPITFbiwaENckpc0EpcjB7I+W  
20 -FuGOR0V35pOxAH9RlGIQcyYUIqOEtm9omD06DPNG8YuBZxynBruajRXVxVznZAeU  
21 -zIWYGe3V6Im9r7ElGSI7AKrFXY4XVbUf0VFKEaw39AZdDqMDhA+JdGSQWJpIaPCV  
22 -QwAGMfob/+gsJ7SFOBx8uGyStsfGMWpuQqTAfHp0h3dSqKQWSp66V9VeglWbiZ5o  
23 -w/haRA==  
24 ------END CERTIFICATE-----  
1 ------BEGIN PRIVATE KEY-----  
2 -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDFBwhhlS8ZdgCX  
3 -bRpAAewpP1eKC6DmQEdGbQkhD4bgWvONJ5dUU7eeTik/GYkZ3maASecqHoHg1s+I  
4 -B4xl2JHLSIsJpp0xw7XRYXJyryTFufM92QNMQFKxtYSUnqYkLbGhSUoPlyzgi9++  
5 -96zvT6sB/70n6ZIqasVGqZmClgGK1q1I8ovgV/YQb/RoXAEzug0skjJAZtaAIZ4A  
6 -N+ue1hnclO2M4oVZ9yC+19doI3WKBPw31dYPA8Os3mjf4UrvBmfldvjaZ/fQCSkU  
7 -rtPBBYMOaO3DGnBjYUwz0LHOQlxzf0yqSO3DNBbaDwRU4dLqNdHmxNnjiHuzXdkQ  
8 -OiPsD59pAgMBAAECggEAOPuBtwc4afqwzRqmvuBPdtZ08N3QGQd6FaovO7qL3ZMw  
9 -YSCUKbVUo5ojX7Z46lxh9LRrAMl18prtxn+4YTQzZkGCxLXFPMFHcljmiriQwAa5  
10 -jKeYxpLL182RnJINpuT4PJc/riagugh6G3byMvwtjxRxlnt85HugtoESfqv3ojlW  
11 -AHcEVTUNxZZP4FkjZuPcfghq93jIILxuP/ancCtoe53VUDLiiB35XiChYyQZ+CDN  
12 -d8sQh2uJ/o/Ptte10f5XiX4CHTj54S9J0tWBIFkbk/jLLBzHsEznlgQdb4tIF4LO  
13 -cPsCyItHCA7uUCGy3C8tfC+qpZS2FGaA2EmoXxJEqQKBgQDxgJuwcHWQPC1/mbL3  
14 -bsaV+j3xIhVb2zWg54WuEUadOYxa5zrlS5ZCd5kMmrnv0Ssw5ZSZC0rL7CvwoW0U  
15 -QQeo4mIxrq0jErBobzSOa2S/UgKBAsvLk7HR2Xzl94xiIeDJdK1fGPsT1OdP28Ly  
16 -1i7WAYcN/efsRzzk/NwuvaseswKBgQDQ2u/0a7uRM/b2fJTxrG7zBkk4O5OVsMXc  
17 -Pl3qJ0danSrd0ryF8sO3BwJKR1rP+iFUWVoc3OCTj54ZLVzWrietRFK5Phxb9p//  
18 -o3XzB1CXeXUas4D4pPF4vyScwpOfWytpakNPTIqmbek/FprZu1gG2B/outIUSH2y  
19 -zVfYDTZXcwKBgQCE5hJHQUvg6Mzc+Fb9RQ+xfvlRVkFMwFA90MrG5KjoYr/zUmYd  
20 -wr/Yqfombos+BuxuxxhENGuf1sLDdAIT8ElnzdTdpFORBnrfrbrNWRojEt1f44sE  
21 -560mXzoVT2oIor4R/sxdleCtpC76ymP4wJcbm9GXiI91fiprlR8R9bxScwKBgD5K  
22 -/sTdGR2u7RsJf3cxogn0NwSBqHw+NFWDeIltW7foJq/wufANv1gozAMRk0Fy7lv1  
23 -Jo5zRrxcWqBRyl3xpb3lIfNEVjsLrR8XRwfMh7oWLNpg7be7opYMFMR4uIUQMTuI  
24 -yTiusLABGk+J03fbi97GuYW1qxEHqg4Zdvjmv+2HAoGBALWGekcrImaNFHodLN9T  
25 -L9iRcX9701d/U2OLU1RuyXTV3SaX9sgX2hz4G/QGopZvk9Vp3s0ZaaktvfKHfsmZ  
26 -CF4uYDFX+kqqAXqwkgnJXLqLq1LViV0df5V0KTnvCDYaqxURKTMKO6doLOBv/6uo  
27 -SEJ/RoWGTYYbsIm5PpRkjbB5  
28 ------END PRIVATE KEY-----  
1 -<form id="config-form" class="edit-form form-horizontal" role="form" data-toggle="validator" method="POST" action="">  
2 -  
3 - <div class="panel panel-default panel-intro">  
4 - <div class="panel-heading">  
5 - <ul class="nav nav-tabs nav-group">  
6 - <li class="active"><a href="#wechat" data-toggle="tab">微信支付</a></li>  
7 - <li><a href="#alipay" data-toggle="tab">支付宝</a></li>  
8 - </ul>  
9 - </div>  
10 -  
11 - <div class="panel-body">  
12 - <div id="myTabContent" class="tab-content">  
13 - {foreach $addon.config as $item}  
14 - {if $item.name=='wechat'}  
15 - <div class="tab-pane fade active in" id="wechat">  
16 - <table class="table table-striped table-config">  
17 - <tbody>  
18 - <tr>  
19 - <td width="15%">APP appid</td>  
20 - <td>  
21 - <div class="row">  
22 - <div class="col-sm-8 col-xs-12">  
23 - <input type="text" name="row[wechat][appid]" value="{$item.value.appid|default=''}" class="form-control" data-rule="" data-tip="APP应用中支付时使用"/>  
24 - </div>  
25 - <div class="col-sm-4"></div>  
26 - </div>  
27 - </td>  
28 - </tr>  
29 - <tr>  
30 - <td>公众号的app_id</td>  
31 - <td>  
32 - <div class="row">  
33 - <div class="col-sm-8 col-xs-12">  
34 - <input type="text" name="row[wechat][app_id]" value="{$item.value.app_id|default=''}" class="form-control" data-rule="" data-tip="公众号支付必须"/>  
35 - </div>  
36 - <div class="col-sm-4"></div>  
37 - </div>  
38 - </td>  
39 - </tr>  
40 - <tr>  
41 - <td>公众号的app_secret</td>  
42 - <td>  
43 - <div class="row">  
44 - <div class="col-sm-8 col-xs-12">  
45 - <input type="text" name="row[wechat][app_secret]" value="{$item.value.app_secret|default=''}" class="form-control" data-rule="" data-tip="仅在需要获取Openid时使用,一般情况下为空"/>  
46 - </div>  
47 - <div class="col-sm-4"></div>  
48 - </div>  
49 - </td>  
50 - </tr>  
51 - <tr>  
52 - <td>小程序的app_id</td>  
53 - <td>  
54 - <div class="row">  
55 - <div class="col-sm-8 col-xs-12">  
56 - <input type="text" name="row[wechat][miniapp_id]" value="{$item.value.miniapp_id|default=''}" class="form-control" data-rule="" data-tip="仅在小程序支付时使用"/>  
57 - </div>  
58 - <div class="col-sm-4"></div>  
59 - </div>  
60 - </td>  
61 - </tr>  
62 - <tr>  
63 - <td>微信支付商户号ID</td>  
64 - <td>  
65 - <div class="row">  
66 - <div class="col-sm-8 col-xs-12">  
67 - <input type="text" name="row[wechat][mch_id]" value="{$item.value.mch_id|default=''}" class="form-control" data-rule="" data-tip=""/>  
68 - </div>  
69 - <div class="col-sm-4"></div>  
70 - </div>  
71 - </td>  
72 - </tr>  
73 - <tr>  
74 - <td>微信支付商户的密钥</td>  
75 - <td>  
76 - <div class="row">  
77 - <div class="col-sm-8 col-xs-12">  
78 - <input type="text" name="row[wechat][key]" value="{$item.value.key|default=''}" class="form-control" data-rule="" data-tip=""/>  
79 - </div>  
80 - <div class="col-sm-4"></div>  
81 - </div>  
82 - </td>  
83 - </tr>  
84 - <tr>  
85 - <td>支付模式</td>  
86 - <td>  
87 - <div class="row">  
88 - <div class="col-sm-8 col-xs-12">  
89 - {:Form::radios('row[wechat][mode]',['normal'=>'正式环境','dev'=>'沙箱环境','service'=>'服务商模式'],$item.value.mode??'normal')}  
90 - </div>  
91 - <div class="col-sm-4"></div>  
92 - </div>  
93 - </td>  
94 - </tr>  
95 - <tr data-type="service" class="{:$item.value.mode!='service'?'hidden':''}">  
96 - <td>子商户商户号ID</td>  
97 - <td>  
98 - <div class="row">  
99 - <div class="col-sm-8 col-xs-12">  
100 - <input type="text" name="row[wechat][sub_mch_id]" value="{$item.value.sub_mch_id|default=''}" class="form-control" data-rule="" data-tip="如果未用到子商户,请勿填写"/>  
101 - </div>  
102 - <div class="col-sm-4"></div>  
103 - </div>  
104 - </td>  
105 - </tr>  
106 - <tr data-type="service" class="{:$item.value.mode!='service'?'hidden':''}">  
107 - <td>子商户 APP appid</td>  
108 - <td>  
109 - <div class="row">  
110 - <div class="col-sm-8 col-xs-12">  
111 - <input type="text" name="row[wechat][sub_appid]" value="{$item.value.sub_appid|default=''}" class="form-control" data-rule="" data-tip="如果未用到子商户,请勿填写"/>  
112 - </div>  
113 - <div class="col-sm-4"></div>  
114 - </div>  
115 - </td>  
116 - </tr>  
117 - <tr data-type="service" class="{:$item.value.mode!='service'?'hidden':''}">  
118 - <td>子商户公众号的appid</td>  
119 - <td>  
120 - <div class="row">  
121 - <div class="col-sm-8 col-xs-12">  
122 - <input type="text" name="row[wechat][sub_app_id]" value="{$item.value.sub_app_id|default=''}" class="form-control" data-rule="" data-tip="如果未用到子商户,请勿填写"/>  
123 - </div>  
124 - <div class="col-sm-4"></div>  
125 - </div>  
126 - </td>  
127 - </tr>  
128 - <tr data-type="service" class="{:$item.value.mode!='service'?'hidden':''}">  
129 - <td>子商户小程序的appid</td>  
130 - <td>  
131 - <div class="row">  
132 - <div class="col-sm-8 col-xs-12">  
133 - <input type="text" name="row[wechat][sub_miniapp_id]" value="{$item.value.sub_miniapp_id|default=''}" class="form-control" data-rule="" data-tip="如果未用到子商户,请勿填写"/>  
134 - </div>  
135 - <div class="col-sm-4"></div>  
136 - </div>  
137 - </td>  
138 - </tr>  
139 - <tr>  
140 - <td>回调通知地址</td>  
141 - <td>  
142 - <div class="row">  
143 - <div class="col-sm-8 col-xs-12">  
144 - <input type="text" name="row[wechat][notify_url]" value="{$item.value.notify_url|default=''}" class="form-control" data-rule="" data-tip="请勿随意修改,实际以逻辑代码中请求的为准"/>  
145 - </div>  
146 - <div class="col-sm-4"></div>  
147 - </div>  
148 - </td>  
149 - </tr>  
150 - <tr>  
151 - <td>微信支付API证书cert</td>  
152 - <td>  
153 - <div class="row">  
154 - <div class="col-sm-8 col-xs-12">  
155 - <div class="input-group">  
156 - <input id="c-cert_client" class="form-control" size="50" name="row[wechat][cert_client]" type="text" value="{$item.value.cert_client|htmlentities}" data-tip="可选, 仅在退款、红包等情况时需要用到">  
157 - <div class="input-group-addon no-border no-padding">  
158 - <span><button type="button" id="faupload-cert_client" class="btn btn-danger faupload" data-url="epay/upload" data-multipart='{"certname":"cert_client"}' data-mimetype="pem" data-input-id="c-cert_client" data-multiple="false"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>  
159 - </div>  
160 - <span class="msg-box n-right" for="c-cert_client"></span>  
161 - </div>  
162 - <div style="margin-top:5px;"><a href="https://pay.weixin.qq.com" target="_blank"><i class="fa fa-question-circle"></i> 如何获取微信支付API证书?</a></div>  
163 - </div>  
164 - <div class="col-sm-4"></div>  
165 - </div>  
166 - </td>  
167 - </tr>  
168 - <tr>  
169 - <td>微信支付API证书key</td>  
170 - <td>  
171 - <div class="row">  
172 - <div class="col-sm-8 col-xs-12">  
173 - <div class="input-group">  
174 - <input id="c-cert_key" class="form-control" size="50" name="row[wechat][cert_key]" type="text" value="{$item.value.cert_key|htmlentities}" data-tip="可选, 仅在退款、红包等情况时需要用到">  
175 - <div class="input-group-addon no-border no-padding">  
176 - <span><button type="button" id="faupload-cert_key" class="btn btn-danger faupload" data-url="epay/upload" data-multipart='{"certname":"cert_key"}' data-mimetype="pem" data-input-id="c-cert_key" data-multiple="false"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>  
177 - </div>  
178 - <span class="msg-box n-right" for="c-cert_key"></span>  
179 - </div>  
180 - <div style="margin-top:5px;"><a href="https://pay.weixin.qq.com" target="_blank"><i class="fa fa-question-circle"></i> 如何获取微信支付API证书?</a></div>  
181 - </div>  
182 - <div class="col-sm-4"></div>  
183 - </div>  
184 - </td>  
185 - </tr>  
186 -  
187 - <tr>  
188 - <td>记录日志</td>  
189 - <td>  
190 - <div class="row">  
191 - <div class="col-sm-8 col-xs-12">  
192 - {:Form::radios('row[wechat][log]',['1'=>'开启','0'=>'关闭'],$item.value.log)}  
193 - </div>  
194 - <div class="col-sm-4"></div>  
195 - </div>  
196 - </td>  
197 - </tr>  
198 - </tbody>  
199 - </table>  
200 - </div>  
201 - {elseif $item.name=='alipay'}  
202 - <div class="tab-pane fade" id="alipay">  
203 - <table class="table table-striped table-config">  
204 - <tbody>  
205 - <tr>  
206 - <td width="15%">应用ID(app_id)</td>  
207 - <td>  
208 - <div class="row">  
209 - <div class="col-sm-8 col-xs-12">  
210 - <input type="text" name="row[alipay][app_id]" value="{$item.value.app_id|default=''}" class="form-control" data-rule="" data-tip=""/>  
211 - </div>  
212 - <div class="col-sm-4"></div>  
213 - </div>  
214 - </td>  
215 - </tr>  
216 - <tr>  
217 - <td>支付模式</td>  
218 - <td>  
219 - <div class="row">  
220 - <div class="col-sm-8 col-xs-12">  
221 - {:Form::radios('row[alipay][mode]',['normal'=>'正式环境','dev'=>'沙箱环境'],$item.value.mode??'normal')}  
222 - </div>  
223 - <div class="col-sm-4"></div>  
224 - </div>  
225 - </td>  
226 - </tr>  
227 - <tr>  
228 - <td>回调通知地址</td>  
229 - <td>  
230 - <div class="row">  
231 - <div class="col-sm-8 col-xs-12">  
232 - <input type="text" name="row[alipay][notify_url]" value="{$item.value.notify_url|default=''}" class="form-control" data-rule="" data-tip="请勿随意修改,实际以逻辑代码中请求的为准"/>  
233 - </div>  
234 - <div class="col-sm-4"></div>  
235 - </div>  
236 - </td>  
237 - </tr>  
238 - <tr>  
239 - <td>支付跳转地址</td>  
240 - <td>  
241 - <div class="row">  
242 - <div class="col-sm-8 col-xs-12">  
243 - <input type="text" name="row[alipay][return_url]" value="{$item.value.return_url|default=''}" class="form-control" data-rule="" data-tip="请勿随意修改,实际以逻辑代码中请求的为准"/>  
244 - </div>  
245 - <div class="col-sm-4"></div>  
246 - </div>  
247 - </td>  
248 - </tr>  
249 - <tr>  
250 - <td>应用私钥(private_key)</td>  
251 - <td>  
252 - <div class="row">  
253 - <div class="col-sm-8 col-xs-12">  
254 - <input type="text" name="row[alipay][private_key]" value="{$item.value.private_key|default=''}" class="form-control" data-rule="" />  
255 - <div style="margin-top:5px;"><a href="https://opensupport.alipay.com/support/helpcenter/207/201602469554" target="_blank"><i class="fa fa-question-circle"></i> 如何获取应用私钥?</a></div>  
256 - </div>  
257 - <div class="col-sm-4"></div>  
258 - </div>  
259 - </td>  
260 - </tr>  
261 - <tr>  
262 - <td>支付宝公钥路径(ali_public_key)</td>  
263 - <td>  
264 - <div class="row">  
265 - <div class="col-sm-8 col-xs-12">  
266 - <div class="input-group">  
267 - <input id="c-ali_public_key" class="form-control" size="50" name="row[alipay][ali_public_key]" type="text" value="{$item.value.ali_public_key|default=''|htmlentities}" placeholder="公钥请直接粘贴,公钥证书请点击右侧的上传">  
268 - <div class="input-group-addon no-border no-padding">  
269 - <span><button type="button" id="faupload-ali_public_key" class="btn btn-danger faupload" data-url="epay/upload" data-multipart='{"certname":"ali_public_key"}' data-mimetype="crt" data-input-id="c-ali_public_key" data-multiple="false"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>  
270 - </div>  
271 - <span class="msg-box n-right" for="c-ali_public_key"></span>  
272 - </div>  
273 - <div style="margin-top:5px;"><a href="javascript:" data-toggle="tooltip" data-title="如果要使用转账、提现功能,则必须使用公钥证书"> <i class="fa fa-info-circle"></i> 公钥和公钥证书说明</a> <a href="https://opensupport.alipay.com/support/helpcenter/207/201602471154" target="_blank"><i class="fa fa-question-circle"></i> 如何获取支付宝公钥证书?</a></div>  
274 - </div>  
275 - <div class="col-sm-4"></div>  
276 - </div>  
277 - </td>  
278 - </tr>  
279 - <tr>  
280 - <td>应用公钥证书路径(app_cert_public_key)</td>  
281 - <td>  
282 - <div class="row">  
283 - <div class="col-sm-8 col-xs-12">  
284 - <div class="input-group">  
285 - <input id="c-app_cert_public_key" class="form-control" size="50" name="row[alipay][app_cert_public_key]" type="text" value="{$item.value.app_cert_public_key|default=''|htmlentities}">  
286 - <div class="input-group-addon no-border no-padding">  
287 - <span><button type="button" id="faupload-app_cert_public_key" class="btn btn-danger faupload" data-url="epay/upload" data-multipart='{"certname":"app_cert_public_key"}' data-mimetype="crt" data-input-id="c-app_cert_public_key" data-multiple="false"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>  
288 - </div>  
289 - <span class="msg-box n-right" for="c-app_cert_public_key"></span>  
290 - </div>  
291 - <div style="margin-top:5px;"><a href="https://opensupport.alipay.com/support/helpcenter/207/201602469554" target="_blank"><i class="fa fa-question-circle"></i> 如何获取应用公钥证书?</a></div>  
292 - </div>  
293 - <div class="col-sm-4"></div>  
294 - </div>  
295 - </td>  
296 - </tr>  
297 - <tr>  
298 - <td>支付宝根证书路径(alipay_root_cert)</td>  
299 - <td>  
300 - <div class="row">  
301 - <div class="col-sm-8 col-xs-12">  
302 - <div class="input-group">  
303 - <input id="c-alipay_root_cert" class="form-control" size="50" name="row[alipay][alipay_root_cert]" type="text" value="{$item.value.alipay_root_cert|default=''|htmlentities}">  
304 - <div class="input-group-addon no-border no-padding">  
305 - <span><button type="button" id="faupload-alipay_root_cert" class="btn btn-danger faupload" data-url="epay/upload" data-multipart='{"certname":"alipay_root_cert"}' data-mimetype="crt" data-input-id="c-alipay_root_cert" data-multiple="false"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>  
306 - </div>  
307 - <span class="msg-box n-right" for="c-alipay_root_cert"></span>  
308 - </div>  
309 - <div style="margin-top:5px;"><a href="https://opensupport.alipay.com/support/helpcenter/207/201602469554" target="_blank"><i class="fa fa-question-circle"></i> 如何获取支付宝证书?</a></div>  
310 - </div>  
311 - <div class="col-sm-4"></div>  
312 - </div>  
313 - </td>  
314 - </tr>  
315 -  
316 - <tr>  
317 - <td>记录日志</td>  
318 - <td>  
319 - <div class="row">  
320 - <div class="col-sm-8 col-xs-12">  
321 - {:Form::radios('row[alipay][log]',['1'=>'开启','0'=>'关闭'],$item.value.log)}  
322 - </div>  
323 - <div class="col-sm-4"></div>  
324 - </div>  
325 - </td>  
326 - </tr>  
327 -  
328 - <tr>  
329 - <td>PC端使用扫码支付</td>  
330 - <td>  
331 - <div class="row">  
332 - <div class="col-sm-8 col-xs-12">  
333 - {:Form::radios('row[alipay][scanpay]',['1'=>'开启','0'=>'关闭'],$item.value.scanpay??0)}  
334 - </div>  
335 - <div class="col-sm-4"></div>  
336 - </div>  
337 - </td>  
338 - </tr>  
339 - </tbody>  
340 - </table>  
341 - </div>  
342 - {/if}  
343 - {/foreach}  
344 - <div class="form-group layer-footer">  
345 - <label class="control-label col-xs-12 col-sm-2"></label>  
346 - <div class="col-xs-12 col-sm-8">  
347 - <button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>  
348 - <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>  
349 - </div>  
350 - </div>  
351 - </div>  
352 - </div>  
353 - </div>  
354 -</form>  
355 -<script>  
356 - document.querySelectorAll("input[name='row[wechat][mode]']").forEach(function (i, j) {  
357 - i.addEventListener("click", function () {  
358 - document.querySelectorAll("#wechat table tr[data-type]").forEach(function (m, n) {  
359 - m.classList.add("hidden");  
360 - });  
361 - document.querySelectorAll("#wechat table tr[data-type='" + this.value + "']").forEach(function (m, n) {  
362 - m.classList.remove("hidden");  
363 - });  
364 - });  
365 - });  
366 -</script>  
1 -<?php  
2 -  
3 -return [  
4 - [  
5 - 'name' => 'wechat',  
6 - 'title' => '微信',  
7 - 'type' => 'array',  
8 - 'content' => [],  
9 - 'value' => [  
10 - 'appid' => '',  
11 - 'app_id' => '',  
12 - 'app_secret' => '',  
13 - 'miniapp_id' => 'wx3fb93805fc3f459d',  
14 - 'mch_id' => '1619193130',  
15 - 'key' => 'chengyigou0123456789012345678901',  
16 - 'mode' => 'normal',  
17 - 'sub_mch_id' => '',  
18 - 'sub_appid' => '',  
19 - 'sub_app_id' => '',  
20 - 'sub_miniapp_id' => '',  
21 - 'notify_url' => '/addons/epay/api/notifyx/type/wechat',  
22 - 'cert_client' => '/addons/epay/certs/apiclient_cert.pem',  
23 - 'cert_key' => '/addons/epay/certs/apiclient_key.pem',  
24 - 'log' => '1',  
25 - ],  
26 - 'rule' => '',  
27 - 'msg' => '',  
28 - 'tip' => '微信参数配置',  
29 - 'ok' => '',  
30 - 'extend' => '',  
31 - ],  
32 - [  
33 - 'name' => 'alipay',  
34 - 'title' => '支付宝',  
35 - 'type' => 'array',  
36 - 'content' => [],  
37 - 'value' => [  
38 - 'app_id' => '',  
39 - 'mode' => 'normal',  
40 - 'notify_url' => '/addons/epay/api/notifyx/type/alipay',  
41 - 'return_url' => '/addons/epay/api/returnx/type/alipay',  
42 - 'private_key' => '',  
43 - 'ali_public_key' => '',  
44 - 'app_cert_public_key' => '',  
45 - 'alipay_root_cert' => '',  
46 - 'log' => '1',  
47 - 'scanpay' => '0',  
48 - ],  
49 - 'rule' => 'required',  
50 - 'msg' => '',  
51 - 'tip' => '支付宝参数配置',  
52 - 'ok' => '',  
53 - 'extend' => '',  
54 - ],  
55 - [  
56 - 'name' => '__tips__',  
57 - 'title' => '温馨提示',  
58 - 'type' => 'array',  
59 - 'content' => [],  
60 - 'value' => '请注意微信支付证书路径位于/addons/epay/certs目录下,请替换成你自己的证书<br>appid:APP的appid<br>app_id:公众号的appid<br>app_secret:公众号的secret<br>miniapp_id:小程序ID<br>mch_id:微信商户ID<br>key:微信商户支付的密钥',  
61 - 'rule' => '',  
62 - 'msg' => '',  
63 - 'tip' => '微信参数配置',  
64 - 'ok' => '',  
65 - 'extend' => '',  
66 - ],  
67 -];  
1 -<?php  
2 -  
3 -namespace addons\epay\controller;  
4 -  
5 -use addons\epay\library\QRCode;  
6 -use addons\epay\library\Service;  
7 -use addons\epay\library\Wechat;  
8 -use addons\third\model\Third;  
9 -use app\common\library\Auth;  
10 -use think\addons\Controller;  
11 -use think\Response;  
12 -use think\Session;  
13 -use Yansongda\Pay\Exceptions\GatewayException;  
14 -use Yansongda\Pay\Pay;  
15 -  
16 -/**  
17 - * API接口控制器  
18 - *  
19 - * @package addons\epay\controller  
20 - */  
21 -class Api extends Controller  
22 -{  
23 -  
24 - protected $layout = 'default';  
25 - protected $config = [];  
26 -  
27 - /**  
28 - * 默认方法  
29 - */  
30 - public function index()  
31 - {  
32 - return;  
33 - }  
34 -  
35 - /**  
36 - * 外部提交  
37 - */  
38 - public function submit()  
39 - {  
40 - $this->request->filter('trim');  
41 - $out_trade_no = $this->request->request("out_trade_no");  
42 - $title = $this->request->request("title");  
43 - $amount = $this->request->request('amount');  
44 - $type = $this->request->request('type');  
45 - $method = $this->request->request('method', 'web');  
46 - $openid = $this->request->request('openid', '');  
47 - $auth_code = $this->request->request('auth_code', '');  
48 - $notifyurl = $this->request->request('notifyurl', '');  
49 - $returnurl = $this->request->request('returnurl', '');  
50 -  
51 - if (!$amount || $amount < 0) {  
52 - $this->error("支付金额必须大于0");  
53 - }  
54 -  
55 - if (!$type || !in_array($type, ['alipay', 'wechat'])) {  
56 - $this->error("支付类型错误");  
57 - }  
58 -  
59 - $params = [  
60 - 'type' => $type,  
61 - 'out_trade_no' => $out_trade_no,  
62 - 'title' => $title,  
63 - 'amount' => $amount,  
64 - 'method' => $method,  
65 - 'openid' => $openid,  
66 - 'auth_code' => $auth_code,  
67 - 'notifyurl' => $notifyurl,  
68 - 'returnurl' => $returnurl,  
69 - ];  
70 - return Service::submitOrder($params);  
71 - }  
72 -  
73 - /**  
74 - * 微信支付(公众号支付&PC扫码支付)  
75 - * @return string  
76 - */  
77 - public function wechat()  
78 - {  
79 - $config = Service::getConfig('wechat');  
80 -  
81 - $isWechat = stripos($this->request->server('HTTP_USER_AGENT'), 'MicroMessenger') !== false;  
82 - $isMobile = $this->request->isMobile();  
83 - $this->view->assign("isWechat", $isWechat);  
84 - $this->view->assign("isMobile", $isMobile);  
85 -  
86 - //发起PC支付(Scan支付)(PC扫码模式)  
87 - if ($this->request->isAjax()) {  
88 - $pay = Pay::wechat($config);  
89 - $orderid = $this->request->post("orderid");  
90 - try {  
91 - $result = $pay->find($orderid);  
92 - if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {  
93 - $this->success("", "", ['status' => $result['trade_state']]);  
94 - } else {  
95 - $this->error("查询失败");  
96 - }  
97 - } catch (GatewayException $e) {  
98 - $this->error("查询失败");  
99 - }  
100 - }  
101 -  
102 - $orderData = Session::get("wechatorderdata");  
103 - if (!$orderData) {  
104 - $this->error("请求参数错误");  
105 - }  
106 - if ($isWechat) {  
107 - //发起公众号(jsapi支付),openid必须  
108 -  
109 - //如果没有openid,则自动去获取openid  
110 - if (!isset($orderData['openid']) || !$orderData['openid']) {  
111 - $orderData['openid'] = Service::getOpenid();  
112 - }  
113 -  
114 - $orderData['method'] = 'mp';  
115 - $type = 'jsapi';  
116 - $payData = Service::submitOrder($orderData);  
117 - if (!isset($payData['paySign'])) {  
118 - $this->error("创建订单失败,请返回重试", "");  
119 - }  
120 - } else {  
121 - $orderData['method'] = 'scan';  
122 - $type = 'pc';  
123 - $payData = Service::submitOrder($orderData);  
124 - if (!isset($payData['code_url'])) {  
125 - $this->error("创建订单失败,请返回重试", "");  
126 - }  
127 - }  
128 - $this->view->assign("orderData", $orderData);  
129 - $this->view->assign("payData", $payData);  
130 - $this->view->assign("type", $type);  
131 -  
132 - $this->view->assign("title", "微信支付");  
133 - return $this->view->fetch();  
134 - }  
135 -  
136 - /**  
137 - * 支付宝支付(PC扫码支付)  
138 - * @return string  
139 - */  
140 - public function alipay()  
141 - {  
142 - $config = Service::getConfig('alipay');  
143 -  
144 - $isWechat = stripos($this->request->server('HTTP_USER_AGENT'), 'MicroMessenger') !== false;  
145 - $isMobile = $this->request->isMobile();  
146 - $this->view->assign("isWechat", $isWechat);  
147 - $this->view->assign("isMobile", $isMobile);  
148 -  
149 - if ($this->request->isAjax()) {  
150 - $orderid = $this->request->post("orderid");  
151 - $pay = Pay::alipay($config);  
152 - try {  
153 - $result = $pay->find($orderid);  
154 - if ($result['code'] == '10000' && $result['trade_status'] == 'TRADE_SUCCESS') {  
155 - $this->success("", "", ['status' => $result['trade_status']]);  
156 - } else {  
157 - $this->error("查询失败");  
158 - }  
159 - } catch (GatewayException $e) {  
160 - $this->error("查询失败");  
161 - }  
162 - }  
163 -  
164 - //发起PC支付(Scan支付)(PC扫码模式)  
165 - $orderData = Session::get("alipayorderdata");  
166 - if (!$orderData) {  
167 - $this->error("请求参数错误");  
168 - }  
169 -  
170 - $orderData['method'] = 'scan';  
171 - $payData = Service::submitOrder($orderData);  
172 - if (!isset($payData['qr_code'])) {  
173 - $this->error("创建订单失败,请返回重试");  
174 - }  
175 -  
176 - $type = 'pc';  
177 - $this->view->assign("orderData", $orderData);  
178 - $this->view->assign("payData", $payData);  
179 - $this->view->assign("type", $type);  
180 - $this->view->assign("title", "支付宝支付");  
181 - return $this->view->fetch();  
182 - }  
183 -  
184 - /**  
185 - * 支付成功回调  
186 - */  
187 - public function notifyx()  
188 - {  
189 - $type = $this->request->param('type');  
190 - if (!Service::checkNotify($type)) {  
191 - echo '签名错误';  
192 - return;  
193 - }  
194 -  
195 - //你可以在这里你的业务处理逻辑,比如处理你的订单状态、给会员加余额等等功能  
196 - //下面这句必须要执行,且在此之前不能有任何输出  
197 - echo "success";  
198 - return;  
199 - }  
200 -  
201 - /**  
202 - * 支付成功返回  
203 - */  
204 - public function returnx()  
205 - {  
206 - $type = $this->request->param('type');  
207 - if (Service::checkReturn($type)) {  
208 - echo '签名错误';  
209 - return;  
210 - }  
211 -  
212 - //你可以在这里定义你的提示信息,但切记不可在此编写逻辑  
213 - $this->success("恭喜你!支付成功!", addon_url("epay/index/index"));  
214 -  
215 - return;  
216 - }  
217 -  
218 - /**  
219 - * 生成二维码  
220 - */  
221 - public function qrcode()  
222 - {  
223 - $text = $this->request->get('text', 'hello world');  
224 -  
225 - //如果有安装二维码插件,则调用插件的生成方法  
226 - if (class_exists("\addons\qrcode\library\Service") && get_addon_info('qrcode')['state']) {  
227 - $qrCode = \addons\qrcode\library\Service::qrcode(['text' => $text]);  
228 - $response = Response::create()->header("Content-Type", "image/png");  
229 -  
230 - header('Content-Type: ' . $qrCode->getContentType());  
231 - $response->content($qrCode->writeString());  
232 - return $response;  
233 - } else {  
234 - $qr = QRCode::getMinimumQRCode($text);  
235 - $im = $qr->createImage(8, 5);  
236 - header("Content-type: image/png");  
237 - imagepng($im);  
238 - imagedestroy($im);  
239 - return;  
240 - }  
241 - }  
242 -  
243 -}  
1 -<?php  
2 -  
3 -namespace addons\epay\controller;  
4 -  
5 -use addons\epay\library\Service;  
6 -use fast\Random;  
7 -use think\addons\Controller;  
8 -use Exception;  
9 -  
10 -/**  
11 - * 微信支付宝插件首页  
12 - *  
13 - * 此控制器仅用于开发展示说明和体验,建议自行添加一个新的控制器进行处理返回和回调事件,同时删除此控制器文件  
14 - *  
15 - * Class Index  
16 - * @package addons\epay\controller  
17 - */  
18 -class Index extends Controller  
19 -{  
20 -  
21 - protected $layout = 'default';  
22 -  
23 - protected $config = [];  
24 -  
25 - public function _initialize()  
26 - {  
27 - parent::_initialize();  
28 - if (!config("app_debug")) {  
29 - $this->error("仅在开发环境下查看");  
30 - }  
31 - }  
32 -  
33 - public function index()  
34 - {  
35 - $this->view->assign("title", "微信支付宝整合插件");  
36 - return $this->view->fetch();  
37 - }  
38 -  
39 - /**  
40 - * 体验,仅供开发测试  
41 - */  
42 - public function experience()  
43 - {  
44 - $amount = $this->request->request('amount');  
45 - $type = $this->request->request('type');  
46 - $method = $this->request->request('method');  
47 -  
48 - if (!$amount || $amount < 0) {  
49 - $this->error("支付金额必须大于0");  
50 - }  
51 -  
52 - if (!$type || !in_array($type, ['alipay', 'wechat'])) {  
53 - $this->error("支付类型不能为空");  
54 - }  
55 -  
56 - //订单号  
57 - $out_trade_no = date("YmdHis") . mt_rand(100000, 999999);  
58 -  
59 - //订单标题  
60 - $title = '测试订单';  
61 -  
62 - //回调链接  
63 - $notifyurl = $this->request->root(true) . '/addons/epay/index/notifyx/paytype/' . $type;  
64 - $returnurl = $this->request->root(true) . '/addons/epay/index/returnx/paytype/' . $type . '/out_trade_no/' . $out_trade_no;  
65 -  
66 - $response = Service::submitOrder($amount, $out_trade_no, $type, $title, $notifyurl, $returnurl, $method);  
67 -  
68 - return $response;  
69 - }  
70 -  
71 - /**  
72 - * 支付成功,仅供开发测试  
73 - */  
74 - public function notifyx()  
75 - {  
76 - $paytype = $this->request->param('paytype');  
77 - $pay = Service::checkNotify($paytype);  
78 - if (!$pay) {  
79 - echo '签名错误';  
80 - return;  
81 - }  
82 - $data = $pay->verify();  
83 - try {  
84 - $payamount = $paytype == 'alipay' ? $data['total_amount'] : $data['total_fee'] / 100;  
85 - $out_trade_no = $data['out_trade_no'];  
86 -  
87 - //你可以在此编写订单逻辑  
88 - } catch (Exception $e) {  
89 - }  
90 - echo $pay->success();  
91 - }  
92 -  
93 - /**  
94 - * 支付返回,仅供开发测试  
95 - */  
96 - public function returnx()  
97 - {  
98 - $paytype = $this->request->param('paytype');  
99 - $out_trade_no = $this->request->param('out_trade_no');  
100 - $pay = Service::checkReturn($paytype);  
101 - if (!$pay) {  
102 - $this->error('签名错误', '');  
103 - }  
104 -  
105 - //你可以在这里通过out_trade_no去验证订单状态  
106 - //但是不可以在此编写订单逻辑!!!  
107 -  
108 - $this->success("请返回网站查看支付结果", addon_url("epay/index/index"));  
109 - }  
110 -  
111 -}  
1 -name = epay  
2 -title = 微信支付宝整合  
3 -intro = 可用于快速整合微信、支付宝支付功能  
4 -author = FastAdmin  
5 -website = https://www.fastadmin.net  
6 -version = 1.2.5  
7 -state = 1  
8 -url = /addons/epay  
9 -license = regular  
10 -licenseto = 10789  
1 -<?php  
2 -  
3 -namespace addons\epay\library;  
4 -  
5 -class Collection extends \Yansongda\Supports\Collection  
6 -{  
7 -  
8 - /**  
9 - * 创建 Collection 实例  
10 - * @access public  
11 - * @param array $items 数据  
12 - * @return static  
13 - */  
14 - public static function make($items = [])  
15 - {  
16 - return new static($items);  
17 - }  
18 -}  
1 -<?php  
2 -  
3 -namespace addons\epay\library;  
4 -  
5 -use think\Exception;  
6 -  
7 -class OrderException extends Exception  
8 -{  
9 - public function __construct($message = "", $code = 0, $data = [])  
10 - {  
11 - $this->message = $message;  
12 - $this->code = $code;  
13 - $this->data = $data;  
14 - }  
15 -  
16 -}  
1 -<?php  
2 -  
3 -namespace addons\epay\library;  
4 -  
5 -//---------------------------------------------------------------  
6 -// QRCode for PHP5  
7 -//  
8 -// Copyright (c) 2009 Kazuhiko Arase  
9 -//  
10 -// URL: http://www.d-project.com/  
11 -//  
12 -// Licensed under the MIT license:  
13 -// http://www.opensource.org/licenses/mit-license.php  
14 -//  
15 -// The word "QR Code" is registered trademark of  
16 -// DENSO WAVE INCORPORATED  
17 -// http://www.denso-wave.com/qrcode/faqpatent-e.html  
18 -//  
19 -//---------------------------------------------------------------------  
20 -  
21 -//---------------------------------------------------------------  
22 -// QRCode  
23 -//---------------------------------------------------------------  
24 -  
25 -define("QR_PAD0", 0xEC);  
26 -define("QR_PAD1", 0x11);  
27 -  
28 -class QRCode  
29 -{  
30 -  
31 - var $typeNumber;  
32 -  
33 - var $modules;  
34 -  
35 - var $moduleCount;  
36 -  
37 - var $errorCorrectLevel;  
38 -  
39 - var $qrDataList;  
40 -  
41 - function __construct()  
42 - {  
43 - $this->typeNumber = 1;  
44 - $this->errorCorrectLevel = QR_ERROR_CORRECT_LEVEL_H;  
45 - $this->qrDataList = array();  
46 - }  
47 -  
48 - function getTypeNumber()  
49 - {  
50 - return $this->typeNumber;  
51 - }  
52 -  
53 - function setTypeNumber($typeNumber)  
54 - {  
55 - $this->typeNumber = $typeNumber;  
56 - }  
57 -  
58 - function getErrorCorrectLevel()  
59 - {  
60 - return $this->errorCorrectLevel;  
61 - }  
62 -  
63 - function setErrorCorrectLevel($errorCorrectLevel)  
64 - {  
65 - $this->errorCorrectLevel = $errorCorrectLevel;  
66 - }  
67 -  
68 - function addData($data, $mode = 0)  
69 - {  
70 -  
71 - if ($mode == 0) {  
72 - $mode = QRUtil::getMode($data);  
73 - }  
74 -  
75 - switch ($mode) {  
76 -  
77 - case QR_MODE_NUMBER :  
78 - $this->addDataImpl(new QRNumber($data));  
79 - break;  
80 -  
81 - case QR_MODE_ALPHA_NUM :  
82 - $this->addDataImpl(new QRAlphaNum($data));  
83 - break;  
84 -  
85 - case QR_MODE_8BIT_BYTE :  
86 - $this->addDataImpl(new QR8BitByte($data));  
87 - break;  
88 -  
89 - case QR_MODE_KANJI :  
90 - $this->addDataImpl(new QRKanji($data));  
91 - break;  
92 -  
93 - default :  
94 - trigger_error("mode:$mode", E_USER_ERROR);  
95 - }  
96 - }  
97 -  
98 - function clearData()  
99 - {  
100 - $this->qrDataList = array();  
101 - }  
102 -  
103 - function addDataImpl($qrData)  
104 - {  
105 - $this->qrDataList[] = $qrData;  
106 - }  
107 -  
108 - function getDataCount()  
109 - {  
110 - return count($this->qrDataList);  
111 - }  
112 -  
113 - function getData($index)  
114 - {  
115 - return $this->qrDataList[$index];  
116 - }  
117 -  
118 - function isDark($row, $col)  
119 - {  
120 - if ($this->modules[$row][$col] !== null) {  
121 - return $this->modules[$row][$col];  
122 - } else {  
123 - return false;  
124 - }  
125 - }  
126 -  
127 - function getModuleCount()  
128 - {  
129 - return $this->moduleCount;  
130 - }  
131 -  
132 - // used for converting fg/bg colors (e.g. #0000ff = 0x0000FF)  
133 - // added 2015.07.27 ~ DoktorJ  
134 - function hex2rgb($hex = 0x0)  
135 - {  
136 - return array(  
137 - 'r' => floor($hex / 65536),  
138 - 'g' => floor($hex / 256) % 256,  
139 - 'b' => $hex % 256  
140 - );  
141 - }  
142 -  
143 - function make()  
144 - {  
145 - $this->makeImpl(false, $this->getBestMaskPattern());  
146 - }  
147 -  
148 - function getBestMaskPattern()  
149 - {  
150 -  
151 - $minLostPoint = 0;  
152 - $pattern = 0;  
153 -  
154 - for ($i = 0; $i < 8; $i++) {  
155 -  
156 - $this->makeImpl(true, $i);  
157 -  
158 - $lostPoint = QRUtil::getLostPoint($this);  
159 -  
160 - if ($i == 0 || $minLostPoint > $lostPoint) {  
161 - $minLostPoint = $lostPoint;  
162 - $pattern = $i;  
163 - }  
164 - }  
165 -  
166 - return $pattern;  
167 - }  
168 -  
169 - function createNullArray($length)  
170 - {  
171 - $nullArray = array();  
172 - for ($i = 0; $i < $length; $i++) {  
173 - $nullArray[] = null;  
174 - }  
175 - return $nullArray;  
176 - }  
177 -  
178 - function makeImpl($test, $maskPattern)  
179 - {  
180 -  
181 - $this->moduleCount = $this->typeNumber * 4 + 17;  
182 -  
183 - $this->modules = array();  
184 - for ($i = 0; $i < $this->moduleCount; $i++) {  
185 - $this->modules[] = QRCode::createNullArray($this->moduleCount);  
186 - }  
187 -  
188 - $this->setupPositionProbePattern(0, 0);  
189 - $this->setupPositionProbePattern($this->moduleCount - 7, 0);  
190 - $this->setupPositionProbePattern(0, $this->moduleCount - 7);  
191 -  
192 - $this->setupPositionAdjustPattern();  
193 - $this->setupTimingPattern();  
194 -  
195 - $this->setupTypeInfo($test, $maskPattern);  
196 -  
197 - if ($this->typeNumber >= 7) {  
198 - $this->setupTypeNumber($test);  
199 - }  
200 -  
201 - $dataArray = $this->qrDataList;  
202 -  
203 - $data = QRCode::createData($this->typeNumber, $this->errorCorrectLevel, $dataArray);  
204 -  
205 - $this->mapData($data, $maskPattern);  
206 - }  
207 -  
208 - function mapData(&$data, $maskPattern)  
209 - {  
210 -  
211 - $inc = -1;  
212 - $row = $this->moduleCount - 1;  
213 - $bitIndex = 7;  
214 - $byteIndex = 0;  
215 -  
216 - for ($col = $this->moduleCount - 1; $col > 0; $col -= 2) {  
217 -  
218 - if ($col == 6) $col--;  
219 -  
220 - while (true) {  
221 -  
222 - for ($c = 0; $c < 2; $c++) {  
223 -  
224 - if ($this->modules[$row][$col - $c] === null) {  
225 -  
226 - $dark = false;  
227 -  
228 - if ($byteIndex < count($data)) {  
229 - $dark = ((($data[$byteIndex] >> $bitIndex) & 1) == 1);  
230 - }  
231 -  
232 - if (QRUtil::getMask($maskPattern, $row, $col - $c)) {  
233 - $dark = !$dark;  
234 - }  
235 -  
236 - $this->modules[$row][$col - $c] = $dark;  
237 - $bitIndex--;  
238 -  
239 - if ($bitIndex == -1) {  
240 - $byteIndex++;  
241 - $bitIndex = 7;  
242 - }  
243 - }  
244 - }  
245 -  
246 - $row += $inc;  
247 -  
248 - if ($row < 0 || $this->moduleCount <= $row) {  
249 - $row -= $inc;  
250 - $inc = -$inc;  
251 - break;  
252 - }  
253 - }  
254 - }  
255 - }  
256 -  
257 - function setupPositionAdjustPattern()  
258 - {  
259 -  
260 - $pos = QRUtil::getPatternPosition($this->typeNumber);  
261 -  
262 - for ($i = 0; $i < count($pos); $i++) {  
263 -  
264 - for ($j = 0; $j < count($pos); $j++) {  
265 -  
266 - $row = $pos[$i];  
267 - $col = $pos[$j];  
268 -  
269 - if ($this->modules[$row][$col] !== null) {  
270 - continue;  
271 - }  
272 -  
273 - for ($r = -2; $r <= 2; $r++) {  
274 -  
275 - for ($c = -2; $c <= 2; $c++) {  
276 - $this->modules[$row + $r][$col + $c] =  
277 - $r == -2 || $r == 2 || $c == -2 || $c == 2 || ($r == 0 && $c == 0);  
278 - }  
279 - }  
280 - }  
281 - }  
282 - }  
283 -  
284 - function setupPositionProbePattern($row, $col)  
285 - {  
286 -  
287 - for ($r = -1; $r <= 7; $r++) {  
288 -  
289 - for ($c = -1; $c <= 7; $c++) {  
290 -  
291 - if ($row + $r <= -1 || $this->moduleCount <= $row + $r  
292 - || $col + $c <= -1 || $this->moduleCount <= $col + $c) {  
293 - continue;  
294 - }  
295 -  
296 - $this->modules[$row + $r][$col + $c] =  
297 - (0 <= $r && $r <= 6 && ($c == 0 || $c == 6))  
298 - || (0 <= $c && $c <= 6 && ($r == 0 || $r == 6))  
299 - || (2 <= $r && $r <= 4 && 2 <= $c && $c <= 4);  
300 - }  
301 - }  
302 - }  
303 -  
304 - function setupTimingPattern()  
305 - {  
306 -  
307 - for ($i = 8; $i < $this->moduleCount - 8; $i++) {  
308 -  
309 - if ($this->modules[$i][6] !== null || $this->modules[6][$i] !== null) {  
310 - continue;  
311 - }  
312 -  
313 - $this->modules[$i][6] = ($i % 2 == 0);  
314 - $this->modules[6][$i] = ($i % 2 == 0);  
315 - }  
316 - }  
317 -  
318 - function setupTypeNumber($test)  
319 - {  
320 -  
321 - $bits = QRUtil::getBCHTypeNumber($this->typeNumber);  
322 -  
323 - for ($i = 0; $i < 18; $i++) {  
324 - $mod = (!$test && (($bits >> $i) & 1) == 1);  
325 - $this->modules[(int)floor($i / 3)][$i % 3 + $this->moduleCount - 8 - 3] = $mod;  
326 - $this->modules[$i % 3 + $this->moduleCount - 8 - 3][floor($i / 3)] = $mod;  
327 - }  
328 - }  
329 -  
330 - function setupTypeInfo($test, $maskPattern)  
331 - {  
332 -  
333 - $data = ($this->errorCorrectLevel << 3) | $maskPattern;  
334 - $bits = QRUtil::getBCHTypeInfo($data);  
335 -  
336 - for ($i = 0; $i < 15; $i++) {  
337 -  
338 - $mod = (!$test && (($bits >> $i) & 1) == 1);  
339 -  
340 - if ($i < 6) {  
341 - $this->modules[$i][8] = $mod;  
342 - } else if ($i < 8) {  
343 - $this->modules[$i + 1][8] = $mod;  
344 - } else {  
345 - $this->modules[$this->moduleCount - 15 + $i][8] = $mod;  
346 - }  
347 -  
348 - if ($i < 8) {  
349 - $this->modules[8][$this->moduleCount - $i - 1] = $mod;  
350 - } else if ($i < 9) {  
351 - $this->modules[8][15 - $i - 1 + 1] = $mod;  
352 - } else {  
353 - $this->modules[8][15 - $i - 1] = $mod;  
354 - }  
355 - }  
356 -  
357 - $this->modules[$this->moduleCount - 8][8] = !$test;  
358 - }  
359 -  
360 - function createData($typeNumber, $errorCorrectLevel, $dataArray)  
361 - {  
362 -  
363 - $rsBlocks = QRRSBlock::getRSBlocks($typeNumber, $errorCorrectLevel);  
364 -  
365 - $buffer = new QRBitBuffer();  
366 -  
367 - for ($i = 0; $i < count($dataArray); $i++) {  
368 - /** @var \QRData $data */  
369 - $data = $dataArray[$i];  
370 - $buffer->put($data->getMode(), 4);  
371 - $buffer->put($data->getLength(), $data->getLengthInBits($typeNumber));  
372 - $data->write($buffer);  
373 - }  
374 -  
375 - $totalDataCount = 0;  
376 - for ($i = 0; $i < count($rsBlocks); $i++) {  
377 - $totalDataCount += $rsBlocks[$i]->getDataCount();  
378 - }  
379 -  
380 - if ($buffer->getLengthInBits() > $totalDataCount * 8) {  
381 - trigger_error("code length overflow. ("  
382 - . $buffer->getLengthInBits()  
383 - . ">"  
384 - . $totalDataCount * 8  
385 - . ")", E_USER_ERROR);  
386 - }  
387 -  
388 - // end code.  
389 - if ($buffer->getLengthInBits() + 4 <= $totalDataCount * 8) {  
390 - $buffer->put(0, 4);  
391 - }  
392 -  
393 - // padding  
394 - while ($buffer->getLengthInBits() % 8 != 0) {  
395 - $buffer->putBit(false);  
396 - }  
397 -  
398 - // padding  
399 - while (true) {  
400 -  
401 - if ($buffer->getLengthInBits() >= $totalDataCount * 8) {  
402 - break;  
403 - }  
404 - $buffer->put(QR_PAD0, 8);  
405 -  
406 - if ($buffer->getLengthInBits() >= $totalDataCount * 8) {  
407 - break;  
408 - }  
409 - $buffer->put(QR_PAD1, 8);  
410 - }  
411 -  
412 - return QRCode::createBytes($buffer, $rsBlocks);  
413 - }  
414 -  
415 - /**  
416 - * @param \QRBitBuffer $buffer  
417 - * @param \QRRSBlock[] $rsBlocks  
418 - *  
419 - * @return array  
420 - */  
421 - function createBytes(&$buffer, &$rsBlocks)  
422 - {  
423 -  
424 - $offset = 0;  
425 -  
426 - $maxDcCount = 0;  
427 - $maxEcCount = 0;  
428 -  
429 - $dcdata = QRCode::createNullArray(count($rsBlocks));  
430 - $ecdata = QRCode::createNullArray(count($rsBlocks));  
431 -  
432 - $rsBlockCount = count($rsBlocks);  
433 - for ($r = 0; $r < $rsBlockCount; $r++) {  
434 -  
435 - $dcCount = $rsBlocks[$r]->getDataCount();  
436 - $ecCount = $rsBlocks[$r]->getTotalCount() - $dcCount;  
437 -  
438 - $maxDcCount = max($maxDcCount, $dcCount);  
439 - $maxEcCount = max($maxEcCount, $ecCount);  
440 -  
441 - $dcdata[$r] = QRCode::createNullArray($dcCount);  
442 - $dcDataCount = count($dcdata[$r]);  
443 - for ($i = 0; $i < $dcDataCount; $i++) {  
444 - $bdata = $buffer->getBuffer();  
445 - $dcdata[$r][$i] = 0xff & $bdata[$i + $offset];  
446 - }  
447 - $offset += $dcCount;  
448 -  
449 - $rsPoly = QRUtil::getErrorCorrectPolynomial($ecCount);  
450 - $rawPoly = new QRPolynomial($dcdata[$r], $rsPoly->getLength() - 1);  
451 -  
452 - $modPoly = $rawPoly->mod($rsPoly);  
453 - $ecdata[$r] = QRCode::createNullArray($rsPoly->getLength() - 1);  
454 -  
455 - $ecDataCount = count($ecdata[$r]);  
456 - for ($i = 0; $i < $ecDataCount; $i++) {  
457 - $modIndex = $i + $modPoly->getLength() - count($ecdata[$r]);  
458 - $ecdata[$r][$i] = ($modIndex >= 0) ? $modPoly->get($modIndex) : 0;  
459 - }  
460 - }  
461 -  
462 - $totalCodeCount = 0;  
463 - for ($i = 0; $i < $rsBlockCount; $i++) {  
464 - $totalCodeCount += $rsBlocks[$i]->getTotalCount();  
465 - }  
466 -  
467 - $data = QRCode::createNullArray($totalCodeCount);  
468 -  
469 - $index = 0;  
470 -  
471 - for ($i = 0; $i < $maxDcCount; $i++) {  
472 - for ($r = 0; $r < $rsBlockCount; $r++) {  
473 - if ($i < count($dcdata[$r])) {  
474 - $data[$index++] = $dcdata[$r][$i];  
475 - }  
476 - }  
477 - }  
478 -  
479 - for ($i = 0; $i < $maxEcCount; $i++) {  
480 - for ($r = 0; $r < $rsBlockCount; $r++) {  
481 - if ($i < count($ecdata[$r])) {  
482 - $data[$index++] = $ecdata[$r][$i];  
483 - }  
484 - }  
485 - }  
486 -  
487 - return $data;  
488 - }  
489 -  
490 - static function getMinimumQRCode($data, $errorCorrectLevel = QR_ERROR_CORRECT_LEVEL_L)  
491 - {  
492 -  
493 - $mode = QRUtil::getMode($data);  
494 -  
495 - $qr = new QRCode();  
496 - $qr->setErrorCorrectLevel($errorCorrectLevel);  
497 - $qr->addData($data, $mode);  
498 -  
499 - $qrData = $qr->getData(0);  
500 - $length = $qrData->getLength();  
501 -  
502 - for ($typeNumber = 1; $typeNumber <= 40; $typeNumber++) {  
503 - if ($length <= QRUtil::getMaxLength($typeNumber, $mode, $errorCorrectLevel)) {  
504 - $qr->setTypeNumber($typeNumber);  
505 - break;  
506 - }  
507 - }  
508 -  
509 - $qr->make();  
510 -  
511 - return $qr;  
512 - }  
513 -  
514 - // added $fg (foreground), $bg (background), and $bgtrans (use transparent bg) parameters  
515 - // also added some simple error checking on parameters  
516 - // updated 2015.07.27 ~ DoktorJ  
517 - function createImage($size = 2, $margin = 2, $fg = 0x000000, $bg = 0xFFFFFF, $bgtrans = false)  
518 - {  
519 -  
520 - // size/margin EC  
521 - if (!is_numeric($size)) $size = 2;  
522 - if (!is_numeric($margin)) $margin = 2;  
523 - if ($size < 1) $size = 1;  
524 - if ($margin < 0) $margin = 0;  
525 -  
526 - $image_size = $this->getModuleCount() * $size + $margin * 2;  
527 -  
528 - $image = imagecreatetruecolor($image_size, $image_size);  
529 -  
530 - // fg/bg EC  
531 - if ($fg < 0 || $fg > 0xFFFFFF) $fg = 0x0;  
532 - if ($bg < 0 || $bg > 0xFFFFFF) $bg = 0xFFFFFF;  
533 -  
534 - // convert hexadecimal RGB to arrays for imagecolorallocate  
535 - $fgrgb = $this->hex2rgb($fg);  
536 - $bgrgb = $this->hex2rgb($bg);  
537 -  
538 - // replace $black and $white with $fgc and $bgc  
539 - $fgc = imagecolorallocate($image, $fgrgb['r'], $fgrgb['g'], $fgrgb['b']);  
540 - $bgc = imagecolorallocate($image, $bgrgb['r'], $bgrgb['g'], $bgrgb['b']);  
541 - if ($bgtrans) imagecolortransparent($image, $bgc);  
542 -  
543 - // update $white to $bgc  
544 - imagefilledrectangle($image, 0, 0, $image_size, $image_size, $bgc);  
545 -  
546 - for ($r = 0; $r < $this->getModuleCount(); $r++) {  
547 - for ($c = 0; $c < $this->getModuleCount(); $c++) {  
548 - if ($this->isDark($r, $c)) {  
549 -  
550 - // update $black to $fgc  
551 - imagefilledrectangle($image,  
552 - $margin + $c * $size,  
553 - $margin + $r * $size,  
554 - $margin + ($c + 1) * $size - 1,  
555 - $margin + ($r + 1) * $size - 1,  
556 - $fgc);  
557 - }  
558 - }  
559 - }  
560 -  
561 - return $image;  
562 - }  
563 -  
564 - function printHTML($size = "2px")  
565 - {  
566 -  
567 - $style = "border-style:none;border-collapse:collapse;margin:0px;padding:0px;";  
568 -  
569 - print("<table style='$style'>");  
570 -  
571 - for ($r = 0; $r < $this->getModuleCount(); $r++) {  
572 -  
573 - print("<tr style='$style'>");  
574 -  
575 - for ($c = 0; $c < $this->getModuleCount(); $c++) {  
576 - $color = $this->isDark($r, $c) ? "#000000" : "#ffffff";  
577 - print("<td style='$style;width:$size;height:$size;background-color:$color'></td>");  
578 - }  
579 -  
580 - print("</tr>");  
581 - }  
582 -  
583 - print("</table>");  
584 - }  
585 -}  
586 -  
587 -//---------------------------------------------------------------  
588 -// QRUtil  
589 -//---------------------------------------------------------------  
590 -  
591 -define("QR_G15", (1 << 10) | (1 << 8) | (1 << 5)  
592 - | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0));  
593 -  
594 -define("QR_G18", (1 << 12) | (1 << 11) | (1 << 10)  
595 - | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0));  
596 -  
597 -define("QR_G15_MASK", (1 << 14) | (1 << 12) | (1 << 10)  
598 - | (1 << 4) | (1 << 1));  
599 -  
600 -class QRUtil  
601 -{  
602 -  
603 - static $QR_MAX_LENGTH = array(  
604 - array(array(41, 25, 17, 10), array(34, 20, 14, 8), array(27, 16, 11, 7), array(17, 10, 7, 4)),  
605 - array(array(77, 47, 32, 20), array(63, 38, 26, 16), array(48, 29, 20, 12), array(34, 20, 14, 8)),  
606 - array(array(127, 77, 53, 32), array(101, 61, 42, 26), array(77, 47, 32, 20), array(58, 35, 24, 15)),  
607 - array(array(187, 114, 78, 48), array(149, 90, 62, 38), array(111, 67, 46, 28), array(82, 50, 34, 21)),  
608 - array(array(255, 154, 106, 65), array(202, 122, 84, 52), array(144, 87, 60, 37), array(106, 64, 44, 27)),  
609 - array(array(322, 195, 134, 82), array(255, 154, 106, 65), array(178, 108, 74, 45), array(139, 84, 58, 36)),  
610 - array(array(370, 224, 154, 95), array(293, 178, 122, 75), array(207, 125, 86, 53), array(154, 93, 64, 39)),  
611 - array(array(461, 279, 192, 118), array(365, 221, 152, 93), array(259, 157, 108, 66), array(202, 122, 84, 52)),  
612 - array(array(552, 335, 230, 141), array(432, 262, 180, 111), array(312, 189, 130, 80), array(235, 143, 98, 60)),  
613 - array(array(652, 395, 271, 167), array(513, 311, 213, 131), array(364, 221, 151, 93), array(288, 174, 119, 74))  
614 - );  
615 -  
616 - static $QR_PATTERN_POSITION_TABLE = array(  
617 - array(),  
618 - array(6, 18),  
619 - array(6, 22),  
620 - array(6, 26),  
621 - array(6, 30),  
622 - array(6, 34),  
623 - array(6, 22, 38),  
624 - array(6, 24, 42),  
625 - array(6, 26, 46),  
626 - array(6, 28, 50),  
627 - array(6, 30, 54),  
628 - array(6, 32, 58),  
629 - array(6, 34, 62),  
630 - array(6, 26, 46, 66),  
631 - array(6, 26, 48, 70),  
632 - array(6, 26, 50, 74),  
633 - array(6, 30, 54, 78),  
634 - array(6, 30, 56, 82),  
635 - array(6, 30, 58, 86),  
636 - array(6, 34, 62, 90),  
637 - array(6, 28, 50, 72, 94),  
638 - array(6, 26, 50, 74, 98),  
639 - array(6, 30, 54, 78, 102),  
640 - array(6, 28, 54, 80, 106),  
641 - array(6, 32, 58, 84, 110),  
642 - array(6, 30, 58, 86, 114),  
643 - array(6, 34, 62, 90, 118),  
644 - array(6, 26, 50, 74, 98, 122),  
645 - array(6, 30, 54, 78, 102, 126),  
646 - array(6, 26, 52, 78, 104, 130),  
647 - array(6, 30, 56, 82, 108, 134),  
648 - array(6, 34, 60, 86, 112, 138),  
649 - array(6, 30, 58, 86, 114, 142),  
650 - array(6, 34, 62, 90, 118, 146),  
651 - array(6, 30, 54, 78, 102, 126, 150),  
652 - array(6, 24, 50, 76, 102, 128, 154),  
653 - array(6, 28, 54, 80, 106, 132, 158),  
654 - array(6, 32, 58, 84, 110, 136, 162),  
655 - array(6, 26, 54, 82, 110, 138, 166),  
656 - array(6, 30, 58, 86, 114, 142, 170)  
657 - );  
658 -  
659 - static function getPatternPosition($typeNumber)  
660 - {  
661 - return self::$QR_PATTERN_POSITION_TABLE[$typeNumber - 1];  
662 - }  
663 -  
664 - static function getMaxLength($typeNumber, $mode, $errorCorrectLevel)  
665 - {  
666 -  
667 - $t = $typeNumber - 1;  
668 - $e = 0;  
669 - $m = 0;  
670 -  
671 - switch ($errorCorrectLevel) {  
672 - case QR_ERROR_CORRECT_LEVEL_L :  
673 - $e = 0;  
674 - break;  
675 - case QR_ERROR_CORRECT_LEVEL_M :  
676 - $e = 1;  
677 - break;  
678 - case QR_ERROR_CORRECT_LEVEL_Q :  
679 - $e = 2;  
680 - break;  
681 - case QR_ERROR_CORRECT_LEVEL_H :  
682 - $e = 3;  
683 - break;  
684 - default :  
685 - trigger_error("e:$errorCorrectLevel", E_USER_ERROR);  
686 - }  
687 -  
688 - switch ($mode) {  
689 - case QR_MODE_NUMBER :  
690 - $m = 0;  
691 - break;  
692 - case QR_MODE_ALPHA_NUM :  
693 - $m = 1;  
694 - break;  
695 - case QR_MODE_8BIT_BYTE :  
696 - $m = 2;  
697 - break;  
698 - case QR_MODE_KANJI :  
699 - $m = 3;  
700 - break;  
701 - default :  
702 - trigger_error("m:$mode", E_USER_ERROR);  
703 - }  
704 -  
705 - return self::$QR_MAX_LENGTH[$t][$e][$m];  
706 - }  
707 -  
708 - static function getErrorCorrectPolynomial($errorCorrectLength)  
709 - {  
710 -  
711 - $a = new QRPolynomial(array(1));  
712 -  
713 - for ($i = 0; $i < $errorCorrectLength; $i++) {  
714 - $a = $a->multiply(new QRPolynomial(array(1, QRMath::gexp($i))));  
715 - }  
716 -  
717 - return $a;  
718 - }  
719 -  
720 - static function getMask($maskPattern, $i, $j)  
721 - {  
722 -  
723 - switch ($maskPattern) {  
724 -  
725 - case QR_MASK_PATTERN000 :  
726 - return ($i + $j) % 2 == 0;  
727 - case QR_MASK_PATTERN001 :  
728 - return $i % 2 == 0;  
729 - case QR_MASK_PATTERN010 :  
730 - return $j % 3 == 0;  
731 - case QR_MASK_PATTERN011 :  
732 - return ($i + $j) % 3 == 0;  
733 - case QR_MASK_PATTERN100 :  
734 - return (floor($i / 2) + floor($j / 3)) % 2 == 0;  
735 - case QR_MASK_PATTERN101 :  
736 - return ($i * $j) % 2 + ($i * $j) % 3 == 0;  
737 - case QR_MASK_PATTERN110 :  
738 - return (($i * $j) % 2 + ($i * $j) % 3) % 2 == 0;  
739 - case QR_MASK_PATTERN111 :  
740 - return (($i * $j) % 3 + ($i + $j) % 2) % 2 == 0;  
741 -  
742 - default :  
743 - trigger_error("mask:$maskPattern", E_USER_ERROR);  
744 - }  
745 - }  
746 -  
747 - /**  
748 - * @param \QRCode $qrCode  
749 - *  
750 - * @return float|int  
751 - */  
752 - static function getLostPoint($qrCode)  
753 - {  
754 -  
755 - $moduleCount = $qrCode->getModuleCount();  
756 -  
757 - $lostPoint = 0;  
758 -  
759 -  
760 - // LEVEL1  
761 -  
762 - for ($row = 0; $row < $moduleCount; $row++) {  
763 -  
764 - for ($col = 0; $col < $moduleCount; $col++) {  
765 -  
766 - $sameCount = 0;  
767 - $dark = $qrCode->isDark($row, $col);  
768 -  
769 - for ($r = -1; $r <= 1; $r++) {  
770 -  
771 - if ($row + $r < 0 || $moduleCount <= $row + $r) {  
772 - continue;  
773 - }  
774 -  
775 - for ($c = -1; $c <= 1; $c++) {  
776 -  
777 - if (($col + $c < 0 || $moduleCount <= $col + $c) || ($r == 0 && $c == 0)) {  
778 - continue;  
779 - }  
780 -  
781 - if ($dark == $qrCode->isDark($row + $r, $col + $c)) {  
782 - $sameCount++;  
783 - }  
784 - }  
785 - }  
786 -  
787 - if ($sameCount > 5) {  
788 - $lostPoint += (3 + $sameCount - 5);  
789 - }  
790 - }  
791 - }  
792 -  
793 - // LEVEL2  
794 -  
795 - for ($row = 0; $row < $moduleCount - 1; $row++) {  
796 - for ($col = 0; $col < $moduleCount - 1; $col++) {  
797 - $count = 0;  
798 - if ($qrCode->isDark($row, $col)) $count++;  
799 - if ($qrCode->isDark($row + 1, $col)) $count++;  
800 - if ($qrCode->isDark($row, $col + 1)) $count++;  
801 - if ($qrCode->isDark($row + 1, $col + 1)) $count++;  
802 - if ($count == 0 || $count == 4) {  
803 - $lostPoint += 3;  
804 - }  
805 - }  
806 - }  
807 -  
808 - // LEVEL3  
809 -  
810 - for ($row = 0; $row < $moduleCount; $row++) {  
811 - for ($col = 0; $col < $moduleCount - 6; $col++) {  
812 - if ($qrCode->isDark($row, $col)  
813 - && !$qrCode->isDark($row, $col + 1)  
814 - && $qrCode->isDark($row, $col + 2)  
815 - && $qrCode->isDark($row, $col + 3)  
816 - && $qrCode->isDark($row, $col + 4)  
817 - && !$qrCode->isDark($row, $col + 5)  
818 - && $qrCode->isDark($row, $col + 6)) {  
819 - $lostPoint += 40;  
820 - }  
821 - }  
822 - }  
823 -  
824 - for ($col = 0; $col < $moduleCount; $col++) {  
825 - for ($row = 0; $row < $moduleCount - 6; $row++) {  
826 - if ($qrCode->isDark($row, $col)  
827 - && !$qrCode->isDark($row + 1, $col)  
828 - && $qrCode->isDark($row + 2, $col)  
829 - && $qrCode->isDark($row + 3, $col)  
830 - && $qrCode->isDark($row + 4, $col)  
831 - && !$qrCode->isDark($row + 5, $col)  
832 - && $qrCode->isDark($row + 6, $col)) {  
833 - $lostPoint += 40;  
834 - }  
835 - }  
836 - }  
837 -  
838 - // LEVEL4  
839 -  
840 - $darkCount = 0;  
841 -  
842 - for ($col = 0; $col < $moduleCount; $col++) {  
843 - for ($row = 0; $row < $moduleCount; $row++) {  
844 - if ($qrCode->isDark($row, $col)) {  
845 - $darkCount++;  
846 - }  
847 - }  
848 - }  
849 -  
850 - $ratio = abs(100 * $darkCount / $moduleCount / $moduleCount - 50) / 5;  
851 - $lostPoint += $ratio * 10;  
852 -  
853 - return $lostPoint;  
854 - }  
855 -  
856 - static function getMode($s)  
857 - {  
858 - if (QRUtil::isAlphaNum($s)) {  
859 - if (QRUtil::isNumber($s)) {  
860 - return QR_MODE_NUMBER;  
861 - }  
862 - return QR_MODE_ALPHA_NUM;  
863 - } else if (QRUtil::isKanji($s)) {  
864 - return QR_MODE_KANJI;  
865 - } else {  
866 - return QR_MODE_8BIT_BYTE;  
867 - }  
868 - }  
869 -  
870 - static function isNumber($s)  
871 - {  
872 - for ($i = 0; $i < strlen($s); $i++) {  
873 - $c = ord($s[$i]);  
874 - if (!(QRUtil::toCharCode('0') <= $c && $c <= QRUtil::toCharCode('9'))) {  
875 - return false;  
876 - }  
877 - }  
878 - return true;  
879 - }  
880 -  
881 - static function isAlphaNum($s)  
882 - {  
883 - for ($i = 0; $i < strlen($s); $i++) {  
884 - $c = ord($s[$i]);  
885 - if (!(QRUtil::toCharCode('0') <= $c && $c <= QRUtil::toCharCode('9'))  
886 - && !(QRUtil::toCharCode('A') <= $c && $c <= QRUtil::toCharCode('Z'))  
887 - && strpos(" $%*+-./:", $s[$i]) === false) {  
888 - return false;  
889 - }  
890 - }  
891 - return true;  
892 - }  
893 -  
894 - static function isKanji($s)  
895 - {  
896 -  
897 - $data = $s;  
898 -  
899 - $i = 0;  
900 -  
901 - while ($i + 1 < strlen($data)) {  
902 -  
903 - $c = ((0xff & ord($data[$i])) << 8) | (0xff & ord($data[$i + 1]));  
904 -  
905 - if (!(0x8140 <= $c && $c <= 0x9FFC) && !(0xE040 <= $c && $c <= 0xEBBF)) {  
906 - return false;  
907 - }  
908 -  
909 - $i += 2;  
910 - }  
911 -  
912 - if ($i < strlen($data)) {  
913 - return false;  
914 - }  
915 -  
916 - return true;  
917 - }  
918 -  
919 - static function toCharCode($s)  
920 - {  
921 - return ord($s[0]);  
922 - }  
923 -  
924 - static function getBCHTypeInfo($data)  
925 - {  
926 - $d = $data << 10;  
927 - while (QRUtil::getBCHDigit($d) - QRUtil::getBCHDigit(QR_G15) >= 0) {  
928 - $d ^= (QR_G15 << (QRUtil::getBCHDigit($d) - QRUtil::getBCHDigit(QR_G15)));  
929 - }  
930 - return (($data << 10) | $d) ^ QR_G15_MASK;  
931 - }  
932 -  
933 - static function getBCHTypeNumber($data)  
934 - {  
935 - $d = $data << 12;  
936 - while (QRUtil::getBCHDigit($d) - QRUtil::getBCHDigit(QR_G18) >= 0) {  
937 - $d ^= (QR_G18 << (QRUtil::getBCHDigit($d) - QRUtil::getBCHDigit(QR_G18)));  
938 - }  
939 - return ($data << 12) | $d;  
940 - }  
941 -  
942 - static function getBCHDigit($data)  
943 - {  
944 -  
945 - $digit = 0;  
946 -  
947 - while ($data != 0) {  
948 - $digit++;  
949 - $data >>= 1;  
950 - }  
951 -  
952 - return $digit;  
953 - }  
954 -}  
955 -  
956 -//---------------------------------------------------------------  
957 -// QRRSBlock  
958 -//---------------------------------------------------------------  
959 -  
960 -class QRRSBlock  
961 -{  
962 -  
963 - var $totalCount;  
964 - var $dataCount;  
965 -  
966 - static $QR_RS_BLOCK_TABLE = array(  
967 -  
968 - // L  
969 - // M  
970 - // Q  
971 - // H  
972 -  
973 - // 1  
974 - array(1, 26, 19),  
975 - array(1, 26, 16),  
976 - array(1, 26, 13),  
977 - array(1, 26, 9),  
978 -  
979 - // 2  
980 - array(1, 44, 34),  
981 - array(1, 44, 28),  
982 - array(1, 44, 22),  
983 - array(1, 44, 16),  
984 -  
985 - // 3  
986 - array(1, 70, 55),  
987 - array(1, 70, 44),  
988 - array(2, 35, 17),  
989 - array(2, 35, 13),  
990 -  
991 - // 4  
992 - array(1, 100, 80),  
993 - array(2, 50, 32),  
994 - array(2, 50, 24),  
995 - array(4, 25, 9),  
996 -  
997 - // 5  
998 - array(1, 134, 108),  
999 - array(2, 67, 43),  
1000 - array(2, 33, 15, 2, 34, 16),  
1001 - array(2, 33, 11, 2, 34, 12),  
1002 -  
1003 - // 6  
1004 - array(2, 86, 68),  
1005 - array(4, 43, 27),  
1006 - array(4, 43, 19),  
1007 - array(4, 43, 15),  
1008 -  
1009 - // 7  
1010 - array(2, 98, 78),  
1011 - array(4, 49, 31),  
1012 - array(2, 32, 14, 4, 33, 15),  
1013 - array(4, 39, 13, 1, 40, 14),  
1014 -  
1015 - // 8  
1016 - array(2, 121, 97),  
1017 - array(2, 60, 38, 2, 61, 39),  
1018 - array(4, 40, 18, 2, 41, 19),  
1019 - array(4, 40, 14, 2, 41, 15),  
1020 -  
1021 - // 9  
1022 - array(2, 146, 116),  
1023 - array(3, 58, 36, 2, 59, 37),  
1024 - array(4, 36, 16, 4, 37, 17),  
1025 - array(4, 36, 12, 4, 37, 13),  
1026 -  
1027 - // 10  
1028 - array(2, 86, 68, 2, 87, 69),  
1029 - array(4, 69, 43, 1, 70, 44),  
1030 - array(6, 43, 19, 2, 44, 20),  
1031 - array(6, 43, 15, 2, 44, 16),  
1032 -  
1033 - // 11  
1034 - array(4, 101, 81),  
1035 - array(1, 80, 50, 4, 81, 51),  
1036 - array(4, 50, 22, 4, 51, 23),  
1037 - array(3, 36, 12, 8, 37, 13),  
1038 -  
1039 - // 12  
1040 - array(2, 116, 92, 2, 117, 93),  
1041 - array(6, 58, 36, 2, 59, 37),  
1042 - array(4, 46, 20, 6, 47, 21),  
1043 - array(7, 42, 14, 4, 43, 15),  
1044 -  
1045 - // 13  
1046 - array(4, 133, 107),  
1047 - array(8, 59, 37, 1, 60, 38),  
1048 - array(8, 44, 20, 4, 45, 21),  
1049 - array(12, 33, 11, 4, 34, 12),  
1050 -  
1051 - // 14  
1052 - array(3, 145, 115, 1, 146, 116),  
1053 - array(4, 64, 40, 5, 65, 41),  
1054 - array(11, 36, 16, 5, 37, 17),  
1055 - array(11, 36, 12, 5, 37, 13),  
1056 -  
1057 - // 15  
1058 - array(5, 109, 87, 1, 110, 88),  
1059 - array(5, 65, 41, 5, 66, 42),  
1060 - array(5, 54, 24, 7, 55, 25),  
1061 - array(11, 36, 12, 7, 37, 13),  
1062 -  
1063 - // 16  
1064 - array(5, 122, 98, 1, 123, 99),  
1065 - array(7, 73, 45, 3, 74, 46),  
1066 - array(15, 43, 19, 2, 44, 20),  
1067 - array(3, 45, 15, 13, 46, 16),  
1068 -  
1069 - // 17  
1070 - array(1, 135, 107, 5, 136, 108),  
1071 - array(10, 74, 46, 1, 75, 47),  
1072 - array(1, 50, 22, 15, 51, 23),  
1073 - array(2, 42, 14, 17, 43, 15),  
1074 -  
1075 - // 18  
1076 - array(5, 150, 120, 1, 151, 121),  
1077 - array(9, 69, 43, 4, 70, 44),  
1078 - array(17, 50, 22, 1, 51, 23),  
1079 - array(2, 42, 14, 19, 43, 15),  
1080 -  
1081 - // 19  
1082 - array(3, 141, 113, 4, 142, 114),  
1083 - array(3, 70, 44, 11, 71, 45),  
1084 - array(17, 47, 21, 4, 48, 22),  
1085 - array(9, 39, 13, 16, 40, 14),  
1086 -  
1087 - // 20  
1088 - array(3, 135, 107, 5, 136, 108),  
1089 - array(3, 67, 41, 13, 68, 42),  
1090 - array(15, 54, 24, 5, 55, 25),  
1091 - array(15, 43, 15, 10, 44, 16),  
1092 -  
1093 - // 21  
1094 - array(4, 144, 116, 4, 145, 117),  
1095 - array(17, 68, 42),  
1096 - array(17, 50, 22, 6, 51, 23),  
1097 - array(19, 46, 16, 6, 47, 17),  
1098 -  
1099 - // 22  
1100 - array(2, 139, 111, 7, 140, 112),  
1101 - array(17, 74, 46),  
1102 - array(7, 54, 24, 16, 55, 25),  
1103 - array(34, 37, 13),  
1104 -  
1105 - // 23  
1106 - array(4, 151, 121, 5, 152, 122),  
1107 - array(4, 75, 47, 14, 76, 48),  
1108 - array(11, 54, 24, 14, 55, 25),  
1109 - array(16, 45, 15, 14, 46, 16),  
1110 -  
1111 - // 24  
1112 - array(6, 147, 117, 4, 148, 118),  
1113 - array(6, 73, 45, 14, 74, 46),  
1114 - array(11, 54, 24, 16, 55, 25),  
1115 - array(30, 46, 16, 2, 47, 17),  
1116 -  
1117 - // 25  
1118 - array(8, 132, 106, 4, 133, 107),  
1119 - array(8, 75, 47, 13, 76, 48),  
1120 - array(7, 54, 24, 22, 55, 25),  
1121 - array(22, 45, 15, 13, 46, 16),  
1122 -  
1123 - // 26  
1124 - array(10, 142, 114, 2, 143, 115),  
1125 - array(19, 74, 46, 4, 75, 47),  
1126 - array(28, 50, 22, 6, 51, 23),  
1127 - array(33, 46, 16, 4, 47, 17),  
1128 -  
1129 - // 27  
1130 - array(8, 152, 122, 4, 153, 123),  
1131 - array(22, 73, 45, 3, 74, 46),  
1132 - array(8, 53, 23, 26, 54, 24),  
1133 - array(12, 45, 15, 28, 46, 16),  
1134 -  
1135 - // 28  
1136 - array(3, 147, 117, 10, 148, 118),  
1137 - array(3, 73, 45, 23, 74, 46),  
1138 - array(4, 54, 24, 31, 55, 25),  
1139 - array(11, 45, 15, 31, 46, 16),  
1140 -  
1141 - // 29  
1142 - array(7, 146, 116, 7, 147, 117),  
1143 - array(21, 73, 45, 7, 74, 46),  
1144 - array(1, 53, 23, 37, 54, 24),  
1145 - array(19, 45, 15, 26, 46, 16),  
1146 -  
1147 - // 30  
1148 - array(5, 145, 115, 10, 146, 116),  
1149 - array(19, 75, 47, 10, 76, 48),  
1150 - array(15, 54, 24, 25, 55, 25),  
1151 - array(23, 45, 15, 25, 46, 16),  
1152 -  
1153 - // 31  
1154 - array(13, 145, 115, 3, 146, 116),  
1155 - array(2, 74, 46, 29, 75, 47),  
1156 - array(42, 54, 24, 1, 55, 25),  
1157 - array(23, 45, 15, 28, 46, 16),  
1158 -  
1159 - // 32  
1160 - array(17, 145, 115),  
1161 - array(10, 74, 46, 23, 75, 47),  
1162 - array(10, 54, 24, 35, 55, 25),  
1163 - array(19, 45, 15, 35, 46, 16),  
1164 -  
1165 - // 33  
1166 - array(17, 145, 115, 1, 146, 116),  
1167 - array(14, 74, 46, 21, 75, 47),  
1168 - array(29, 54, 24, 19, 55, 25),  
1169 - array(11, 45, 15, 46, 46, 16),  
1170 -  
1171 - // 34  
1172 - array(13, 145, 115, 6, 146, 116),  
1173 - array(14, 74, 46, 23, 75, 47),  
1174 - array(44, 54, 24, 7, 55, 25),  
1175 - array(59, 46, 16, 1, 47, 17),  
1176 -  
1177 - // 35  
1178 - array(12, 151, 121, 7, 152, 122),  
1179 - array(12, 75, 47, 26, 76, 48),  
1180 - array(39, 54, 24, 14, 55, 25),  
1181 - array(22, 45, 15, 41, 46, 16),  
1182 -  
1183 - // 36  
1184 - array(6, 151, 121, 14, 152, 122),  
1185 - array(6, 75, 47, 34, 76, 48),  
1186 - array(46, 54, 24, 10, 55, 25),  
1187 - array(2, 45, 15, 64, 46, 16),  
1188 -  
1189 - // 37  
1190 - array(17, 152, 122, 4, 153, 123),  
1191 - array(29, 74, 46, 14, 75, 47),  
1192 - array(49, 54, 24, 10, 55, 25),  
1193 - array(24, 45, 15, 46, 46, 16),  
1194 -  
1195 - // 38  
1196 - array(4, 152, 122, 18, 153, 123),  
1197 - array(13, 74, 46, 32, 75, 47),  
1198 - array(48, 54, 24, 14, 55, 25),  
1199 - array(42, 45, 15, 32, 46, 16),  
1200 -  
1201 - // 39  
1202 - array(20, 147, 117, 4, 148, 118),  
1203 - array(40, 75, 47, 7, 76, 48),  
1204 - array(43, 54, 24, 22, 55, 25),  
1205 - array(10, 45, 15, 67, 46, 16),  
1206 -  
1207 - // 40  
1208 - array(19, 148, 118, 6, 149, 119),  
1209 - array(18, 75, 47, 31, 76, 48),  
1210 - array(34, 54, 24, 34, 55, 25),  
1211 - array(20, 45, 15, 61, 46, 16)  
1212 -  
1213 - );  
1214 -  
1215 - function __construct($totalCount, $dataCount)  
1216 - {  
1217 - $this->totalCount = $totalCount;  
1218 - $this->dataCount = $dataCount;  
1219 - }  
1220 -  
1221 - function getDataCount()  
1222 - {  
1223 - return $this->dataCount;  
1224 - }  
1225 -  
1226 - function getTotalCount()  
1227 - {  
1228 - return $this->totalCount;  
1229 - }  
1230 -  
1231 - static function getRSBlocks($typeNumber, $errorCorrectLevel)  
1232 - {  
1233 -  
1234 - $rsBlock = QRRSBlock::getRsBlockTable($typeNumber, $errorCorrectLevel);  
1235 - $length = count($rsBlock) / 3;  
1236 -  
1237 - $list = array();  
1238 -  
1239 - for ($i = 0; $i < $length; $i++) {  
1240 -  
1241 - $count = $rsBlock[$i * 3 + 0];  
1242 - $totalCount = $rsBlock[$i * 3 + 1];  
1243 - $dataCount = $rsBlock[$i * 3 + 2];  
1244 -  
1245 - for ($j = 0; $j < $count; $j++) {  
1246 - $list[] = new QRRSBlock($totalCount, $dataCount);  
1247 - }  
1248 - }  
1249 -  
1250 - return $list;  
1251 - }  
1252 -  
1253 - static function getRsBlockTable($typeNumber, $errorCorrectLevel)  
1254 - {  
1255 -  
1256 - switch ($errorCorrectLevel) {  
1257 - case QR_ERROR_CORRECT_LEVEL_L :  
1258 - return self::$QR_RS_BLOCK_TABLE[($typeNumber - 1) * 4 + 0];  
1259 - case QR_ERROR_CORRECT_LEVEL_M :  
1260 - return self::$QR_RS_BLOCK_TABLE[($typeNumber - 1) * 4 + 1];  
1261 - case QR_ERROR_CORRECT_LEVEL_Q :  
1262 - return self::$QR_RS_BLOCK_TABLE[($typeNumber - 1) * 4 + 2];  
1263 - case QR_ERROR_CORRECT_LEVEL_H :  
1264 - return self::$QR_RS_BLOCK_TABLE[($typeNumber - 1) * 4 + 3];  
1265 - default :  
1266 - trigger_error("tn:$typeNumber/ecl:$errorCorrectLevel", E_USER_ERROR);  
1267 - }  
1268 - }  
1269 -}  
1270 -  
1271 -//---------------------------------------------------------------  
1272 -// QRNumber  
1273 -//---------------------------------------------------------------  
1274 -  
1275 -class QRNumber extends QRData  
1276 -{  
1277 -  
1278 - function __construct($data)  
1279 - {  
1280 - parent::__construct(QR_MODE_NUMBER, $data);  
1281 - }  
1282 -  
1283 - function write(&$buffer)  
1284 - {  
1285 -  
1286 - $data = $this->getData();  
1287 -  
1288 - $i = 0;  
1289 -  
1290 - while ($i + 2 < strlen($data)) {  
1291 - $num = QRNumber::parseInt(substr($data, $i, 3));  
1292 - $buffer->put($num, 10);  
1293 - $i += 3;  
1294 - }  
1295 -  
1296 - if ($i < strlen($data)) {  
1297 -  
1298 - if (strlen($data) - $i == 1) {  
1299 - $num = QRNumber::parseInt(substr($data, $i, $i + 1));  
1300 - $buffer->put($num, 4);  
1301 - } else if (strlen($data) - $i == 2) {  
1302 - $num = QRNumber::parseInt(substr($data, $i, $i + 2));  
1303 - $buffer->put($num, 7);  
1304 - }  
1305 - }  
1306 - }  
1307 -  
1308 - static function parseInt($s)  
1309 - {  
1310 -  
1311 - $num = 0;  
1312 - for ($i = 0; $i < strlen($s); $i++) {  
1313 - $num = $num * 10 + QRNumber::parseIntAt(ord($s[$i]));  
1314 - }  
1315 - return $num;  
1316 - }  
1317 -  
1318 - static function parseIntAt($c)  
1319 - {  
1320 -  
1321 - if (QRUtil::toCharCode('0') <= $c && $c <= QRUtil::toCharCode('9')) {  
1322 - return $c - QRUtil::toCharCode('0');  
1323 - }  
1324 -  
1325 - trigger_error("illegal char : $c", E_USER_ERROR);  
1326 - }  
1327 -}  
1328 -  
1329 -//---------------------------------------------------------------  
1330 -// QRKanji  
1331 -//---------------------------------------------------------------  
1332 -  
1333 -class QRKanji extends QRData  
1334 -{  
1335 -  
1336 - function __construct($data)  
1337 - {  
1338 - parent::__construct(QR_MODE_KANJI, $data);  
1339 - }  
1340 -  
1341 - function write(&$buffer)  
1342 - {  
1343 -  
1344 - $data = $this->getData();  
1345 -  
1346 - $i = 0;  
1347 -  
1348 - while ($i + 1 < strlen($data)) {  
1349 -  
1350 - $c = ((0xff & ord($data[$i])) << 8) | (0xff & ord($data[$i + 1]));  
1351 -  
1352 - if (0x8140 <= $c && $c <= 0x9FFC) {  
1353 - $c -= 0x8140;  
1354 - } else if (0xE040 <= $c && $c <= 0xEBBF) {  
1355 - $c -= 0xC140;  
1356 - } else {  
1357 - trigger_error("illegal char at " . ($i + 1) . "/$c", E_USER_ERROR);  
1358 - }  
1359 -  
1360 - $c = (($c >> 8) & 0xff) * 0xC0 + ($c & 0xff);  
1361 -  
1362 - $buffer->put($c, 13);  
1363 -  
1364 - $i += 2;  
1365 - }  
1366 -  
1367 - if ($i < strlen($data)) {  
1368 - trigger_error("illegal char at " . ($i + 1), E_USER_ERROR);  
1369 - }  
1370 - }  
1371 -  
1372 - function getLength()  
1373 - {  
1374 - return floor(strlen($this->getData()) / 2);  
1375 - }  
1376 -}  
1377 -  
1378 -//---------------------------------------------------------------  
1379 -// QRAlphaNum  
1380 -//---------------------------------------------------------------  
1381 -  
1382 -class QRAlphaNum extends QRData  
1383 -{  
1384 -  
1385 - function __construct($data)  
1386 - {  
1387 - parent::__construct(QR_MODE_ALPHA_NUM, $data);  
1388 - }  
1389 -  
1390 - function write(&$buffer)  
1391 - {  
1392 -  
1393 - $i = 0;  
1394 - $c = $this->getData();  
1395 -  
1396 - while ($i + 1 < strlen($c)) {  
1397 - $buffer->put(QRAlphaNum::getCode(ord($c[$i])) * 45  
1398 - + QRAlphaNum::getCode(ord($c[$i + 1])), 11);  
1399 - $i += 2;  
1400 - }  
1401 -  
1402 - if ($i < strlen($c)) {  
1403 - $buffer->put(QRAlphaNum::getCode(ord($c[$i])), 6);  
1404 - }  
1405 - }  
1406 -  
1407 - static function getCode($c)  
1408 - {  
1409 -  
1410 - if (QRUtil::toCharCode('0') <= $c  
1411 - && $c <= QRUtil::toCharCode('9')) {  
1412 - return $c - QRUtil::toCharCode('0');  
1413 - } else if (QRUtil::toCharCode('A') <= $c  
1414 - && $c <= QRUtil::toCharCode('Z')) {  
1415 - return $c - QRUtil::toCharCode('A') + 10;  
1416 - } else {  
1417 - switch ($c) {  
1418 - case QRUtil::toCharCode(' ') :  
1419 - return 36;  
1420 - case QRUtil::toCharCode('$') :  
1421 - return 37;  
1422 - case QRUtil::toCharCode('%') :  
1423 - return 38;  
1424 - case QRUtil::toCharCode('*') :  
1425 - return 39;  
1426 - case QRUtil::toCharCode('+') :  
1427 - return 40;  
1428 - case QRUtil::toCharCode('-') :  
1429 - return 41;  
1430 - case QRUtil::toCharCode('.') :  
1431 - return 42;  
1432 - case QRUtil::toCharCode('/') :  
1433 - return 43;  
1434 - case QRUtil::toCharCode(':') :  
1435 - return 44;  
1436 - default :  
1437 - trigger_error("illegal char : $c", E_USER_ERROR);  
1438 - }  
1439 - }  
1440 -  
1441 - }  
1442 -}  
1443 -  
1444 -//---------------------------------------------------------------  
1445 -// QR8BitByte  
1446 -//---------------------------------------------------------------  
1447 -  
1448 -class QR8BitByte extends QRData  
1449 -{  
1450 -  
1451 - function __construct($data)  
1452 - {  
1453 - parent::__construct(QR_MODE_8BIT_BYTE, $data);  
1454 - }  
1455 -  
1456 - function write(&$buffer)  
1457 - {  
1458 -  
1459 - $data = $this->getData();  
1460 - for ($i = 0; $i < strlen($data); $i++) {  
1461 - $buffer->put(ord($data[$i]), 8);  
1462 - }  
1463 - }  
1464 -  
1465 -}  
1466 -  
1467 -//---------------------------------------------------------------  
1468 -// QRData  
1469 -//---------------------------------------------------------------  
1470 -  
1471 -abstract class QRData  
1472 -{  
1473 -  
1474 - var $mode;  
1475 -  
1476 - var $data;  
1477 -  
1478 - function __construct($mode, $data)  
1479 - {  
1480 - $this->mode = $mode;  
1481 - $this->data = $data;  
1482 - }  
1483 -  
1484 - function getMode()  
1485 - {  
1486 - return $this->mode;  
1487 - }  
1488 -  
1489 - function getData()  
1490 - {  
1491 - return $this->data;  
1492 - }  
1493 -  
1494 - /**  
1495 - * @return int  
1496 - */  
1497 - function getLength()  
1498 - {  
1499 - return strlen($this->getData());  
1500 - }  
1501 -  
1502 - /**  
1503 - * @param \QRBitBuffer $buffer  
1504 - */  
1505 - abstract function write(&$buffer);  
1506 -  
1507 - function getLengthInBits($type)  
1508 - {  
1509 -  
1510 - if (1 <= $type && $type < 10) {  
1511 -  
1512 - // 1 - 9  
1513 -  
1514 - switch ($this->mode) {  
1515 - case QR_MODE_NUMBER :  
1516 - return 10;  
1517 - case QR_MODE_ALPHA_NUM :  
1518 - return 9;  
1519 - case QR_MODE_8BIT_BYTE :  
1520 - return 8;  
1521 - case QR_MODE_KANJI :  
1522 - return 8;  
1523 - default :  
1524 - trigger_error("mode:$this->mode", E_USER_ERROR);  
1525 - }  
1526 -  
1527 - } else if ($type < 27) {  
1528 -  
1529 - // 10 - 26  
1530 -  
1531 - switch ($this->mode) {  
1532 - case QR_MODE_NUMBER :  
1533 - return 12;  
1534 - case QR_MODE_ALPHA_NUM :  
1535 - return 11;  
1536 - case QR_MODE_8BIT_BYTE :  
1537 - return 16;  
1538 - case QR_MODE_KANJI :  
1539 - return 10;  
1540 - default :  
1541 - trigger_error("mode:$this->mode", E_USER_ERROR);  
1542 - }  
1543 -  
1544 - } else if ($type < 41) {  
1545 -  
1546 - // 27 - 40  
1547 -  
1548 - switch ($this->mode) {  
1549 - case QR_MODE_NUMBER :  
1550 - return 14;  
1551 - case QR_MODE_ALPHA_NUM :  
1552 - return 13;  
1553 - case QR_MODE_8BIT_BYTE :  
1554 - return 16;  
1555 - case QR_MODE_KANJI :  
1556 - return 12;  
1557 - default :  
1558 - trigger_error("mode:$this->mode", E_USER_ERROR);  
1559 - }  
1560 -  
1561 - } else {  
1562 - trigger_error("mode:$this->mode", E_USER_ERROR);  
1563 - }  
1564 - }  
1565 -  
1566 -}  
1567 -  
1568 -//---------------------------------------------------------------  
1569 -// QRMath  
1570 -//---------------------------------------------------------------  
1571 -  
1572 -class QRMath  
1573 -{  
1574 -  
1575 - static $QR_MATH_EXP_TABLE = null;  
1576 - static $QR_MATH_LOG_TABLE = null;  
1577 -  
1578 - static function init()  
1579 - {  
1580 -  
1581 - self::$QR_MATH_EXP_TABLE = QRMath::createNumArray(256);  
1582 -  
1583 - for ($i = 0; $i < 8; $i++) {  
1584 - self::$QR_MATH_EXP_TABLE[$i] = 1 << $i;  
1585 - }  
1586 -  
1587 - for ($i = 8; $i < 256; $i++) {  
1588 - self::$QR_MATH_EXP_TABLE[$i] = self::$QR_MATH_EXP_TABLE[$i - 4]  
1589 - ^ self::$QR_MATH_EXP_TABLE[$i - 5]  
1590 - ^ self::$QR_MATH_EXP_TABLE[$i - 6]  
1591 - ^ self::$QR_MATH_EXP_TABLE[$i - 8];  
1592 - }  
1593 -  
1594 - self::$QR_MATH_LOG_TABLE = QRMath::createNumArray(256);  
1595 -  
1596 - for ($i = 0; $i < 255; $i++) {  
1597 - self::$QR_MATH_LOG_TABLE[self::$QR_MATH_EXP_TABLE[$i]] = $i;  
1598 - }  
1599 - }  
1600 -  
1601 - static function createNumArray($length)  
1602 - {  
1603 - $num_array = array();  
1604 - for ($i = 0; $i < $length; $i++) {  
1605 - $num_array[] = 0;  
1606 - }  
1607 - return $num_array;  
1608 - }  
1609 -  
1610 - static function glog($n)  
1611 - {  
1612 -  
1613 - if ($n < 1) {  
1614 - trigger_error("log($n)", E_USER_ERROR);  
1615 - }  
1616 -  
1617 - return self::$QR_MATH_LOG_TABLE[$n];  
1618 - }  
1619 -  
1620 - static function gexp($n)  
1621 - {  
1622 -  
1623 - while ($n < 0) {  
1624 - $n += 255;  
1625 - }  
1626 -  
1627 - while ($n >= 256) {  
1628 - $n -= 255;  
1629 - }  
1630 -  
1631 - return self::$QR_MATH_EXP_TABLE[$n];  
1632 - }  
1633 -}  
1634 -  
1635 -// init static table  
1636 -QRMath::init();  
1637 -  
1638 -//---------------------------------------------------------------  
1639 -// QRPolynomial  
1640 -//---------------------------------------------------------------  
1641 -  
1642 -class QRPolynomial  
1643 -{  
1644 -  
1645 - var $num;  
1646 -  
1647 - function __construct($num, $shift = 0)  
1648 - {  
1649 -  
1650 - $offset = 0;  
1651 -  
1652 - while ($offset < count($num) && $num[$offset] == 0) {  
1653 - $offset++;  
1654 - }  
1655 -  
1656 - $this->num = QRMath::createNumArray(count($num) - $offset + $shift);  
1657 - for ($i = 0; $i < count($num) - $offset; $i++) {  
1658 - $this->num[$i] = $num[$i + $offset];  
1659 - }  
1660 - }  
1661 -  
1662 - function get($index)  
1663 - {  
1664 - return $this->num[$index];  
1665 - }  
1666 -  
1667 - function getLength()  
1668 - {  
1669 - return count($this->num);  
1670 - }  
1671 -  
1672 - // PHP5  
1673 - function __toString()  
1674 - {  
1675 - return $this->toString();  
1676 - }  
1677 -  
1678 - function toString()  
1679 - {  
1680 -  
1681 - $buffer = "";  
1682 -  
1683 - for ($i = 0; $i < $this->getLength(); $i++) {  
1684 - if ($i > 0) {  
1685 - $buffer .= ",";  
1686 - }  
1687 - $buffer .= $this->get($i);  
1688 - }  
1689 -  
1690 - return $buffer;  
1691 - }  
1692 -  
1693 - function toLogString()  
1694 - {  
1695 -  
1696 - $buffer = "";  
1697 -  
1698 - for ($i = 0; $i < $this->getLength(); $i++) {  
1699 - if ($i > 0) {  
1700 - $buffer .= ",";  
1701 - }  
1702 - $buffer .= QRMath::glog($this->get($i));  
1703 - }  
1704 -  
1705 - return $buffer;  
1706 - }  
1707 -  
1708 - /**  
1709 - * @param \QRPolynomial $e  
1710 - *  
1711 - * @return \QRPolynomial  
1712 - */  
1713 - function multiply($e)  
1714 - {  
1715 -  
1716 - $num = QRMath::createNumArray($this->getLength() + $e->getLength() - 1);  
1717 -  
1718 - for ($i = 0; $i < $this->getLength(); $i++) {  
1719 - $vi = QRMath::glog($this->get($i));  
1720 -  
1721 - for ($j = 0; $j < $e->getLength(); $j++) {  
1722 - $num[$i + $j] ^= QRMath::gexp($vi + QRMath::glog($e->get($j)));  
1723 - }  
1724 - }  
1725 -  
1726 - return new QRPolynomial($num);  
1727 - }  
1728 -  
1729 - /**  
1730 - * @param \QRPolynomial $e  
1731 - *  
1732 - * @return $this|\QRPolynomial  
1733 - */  
1734 - function mod($e)  
1735 - {  
1736 -  
1737 - if ($this->getLength() - $e->getLength() < 0) {  
1738 - return $this;  
1739 - }  
1740 -  
1741 - $ratio = QRMath::glog($this->get(0)) - QRMath::glog($e->get(0));  
1742 -  
1743 - $num = QRMath::createNumArray($this->getLength());  
1744 - for ($i = 0; $i < $this->getLength(); $i++) {  
1745 - $num[$i] = $this->get($i);  
1746 - }  
1747 -  
1748 - for ($i = 0; $i < $e->getLength(); $i++) {  
1749 - $num[$i] ^= QRMath::gexp(QRMath::glog($e->get($i)) + $ratio);  
1750 - }  
1751 -  
1752 - $newPolynomial = new QRPolynomial($num);  
1753 - return $newPolynomial->mod($e);  
1754 - }  
1755 -}  
1756 -  
1757 -//---------------------------------------------------------------  
1758 -// Mode  
1759 -//---------------------------------------------------------------  
1760 -  
1761 -define("QR_MODE_NUMBER", 1 << 0);  
1762 -define("QR_MODE_ALPHA_NUM", 1 << 1);  
1763 -define("QR_MODE_8BIT_BYTE", 1 << 2);  
1764 -define("QR_MODE_KANJI", 1 << 3);  
1765 -  
1766 -//---------------------------------------------------------------  
1767 -// MaskPattern  
1768 -//---------------------------------------------------------------  
1769 -  
1770 -define("QR_MASK_PATTERN000", 0);  
1771 -define("QR_MASK_PATTERN001", 1);  
1772 -define("QR_MASK_PATTERN010", 2);  
1773 -define("QR_MASK_PATTERN011", 3);  
1774 -define("QR_MASK_PATTERN100", 4);  
1775 -define("QR_MASK_PATTERN101", 5);  
1776 -define("QR_MASK_PATTERN110", 6);  
1777 -define("QR_MASK_PATTERN111", 7);  
1778 -  
1779 -//---------------------------------------------------------------  
1780 -// ErrorCorrectLevel  
1781 -  
1782 -// 7%.  
1783 -define("QR_ERROR_CORRECT_LEVEL_L", 1);  
1784 -// 15%.  
1785 -define("QR_ERROR_CORRECT_LEVEL_M", 0);  
1786 -// 25%.  
1787 -define("QR_ERROR_CORRECT_LEVEL_Q", 3);  
1788 -// 30%.  
1789 -define("QR_ERROR_CORRECT_LEVEL_H", 2);  
1790 -  
1791 -  
1792 -//---------------------------------------------------------------  
1793 -// QRBitBuffer  
1794 -//---------------------------------------------------------------  
1795 -  
1796 -class QRBitBuffer  
1797 -{  
1798 -  
1799 - var $buffer;  
1800 - var $length;  
1801 -  
1802 - function __construct()  
1803 - {  
1804 - $this->buffer = array();  
1805 - $this->length = 0;  
1806 - }  
1807 -  
1808 - function getBuffer()  
1809 - {  
1810 - return $this->buffer;  
1811 - }  
1812 -  
1813 - function getLengthInBits()  
1814 - {  
1815 - return $this->length;  
1816 - }  
1817 -  
1818 - function __toString()  
1819 - {  
1820 - $buffer = "";  
1821 - for ($i = 0; $i < $this->getLengthInBits(); $i++) {  
1822 - $buffer .= $this->get($i) ? '1' : '0';  
1823 - }  
1824 - return $buffer;  
1825 - }  
1826 -  
1827 - function get($index)  
1828 - {  
1829 - $bufIndex = (int)floor($index / 8);  
1830 - return (($this->buffer[$bufIndex] >> (7 - $index % 8)) & 1) == 1;  
1831 - }  
1832 -  
1833 - function put($num, $length)  
1834 - {  
1835 -  
1836 - for ($i = 0; $i < $length; $i++) {  
1837 - $this->putBit((($num >> ($length - $i - 1)) & 1) == 1);  
1838 - }  
1839 - }  
1840 -  
1841 - function putBit($bit)  
1842 - {  
1843 -  
1844 - $bufIndex = (int)floor($this->length / 8);  
1845 - if (count($this->buffer) <= $bufIndex) {  
1846 - $this->buffer[] = 0;  
1847 - }  
1848 -  
1849 - if ($bit) {  
1850 - $this->buffer[$bufIndex] |= (0x80 >> ($this->length % 8));  
1851 - }  
1852 -  
1853 - $this->length++;  
1854 - }  
1855 -}  
1856 -  
1 -<?php  
2 -  
3 -namespace addons\epay\library;  
4 -  
5 -class RedirectResponse extends \Symfony\Component\HttpFoundation\RedirectResponse implements \JsonSerializable, \Serializable  
6 -{  
7 - public function __toString()  
8 - {  
9 - return $this->getContent();  
10 - }  
11 -  
12 - public function setTargetUrl($url)  
13 - {  
14 - if ('' === ($url ?? '')) {  
15 - throw new \InvalidArgumentException('无法跳转到空页面');  
16 - }  
17 -  
18 - $this->targetUrl = $url;  
19 -  
20 - $this->setContent(  
21 - sprintf('<!DOCTYPE html>  
22 -<html>  
23 - <head>  
24 - <meta charset="UTF-8" />  
25 - <meta http-equiv="refresh" content="0;url=\'%1$s\'" />  
26 -  
27 - <title>正在跳转支付 %1$s</title>  
28 - </head>  
29 - <body>  
30 - <div id="redirect" style="display:none;">正在跳转支付 <a href="%1$s">%1$s</a></div>  
31 - <script type="text/javascript">  
32 - setTimeout(function(){  
33 - document.getElementById("redirect").style.display = "block";  
34 - }, 1000);  
35 - </script>  
36 - </body>  
37 -</html>', htmlspecialchars($url, \ENT_QUOTES, 'UTF-8')));  
38 -  
39 - $this->headers->set('Location', $url);  
40 -  
41 - return $this;  
42 - }  
43 -  
44 - public function jsonSerialize()  
45 - {  
46 - return $this->getContent();  
47 - }  
48 -  
49 - public function serialize()  
50 - {  
51 - return serialize($this->content);  
52 - }  
53 -  
54 - public function unserialize($serialized)  
55 - {  
56 - return $this->content = unserialize($serialized);  
57 - }  
58 -}  
1 -<?php  
2 -  
3 -namespace addons\epay\library;  
4 -  
5 -class Response extends \Symfony\Component\HttpFoundation\Response implements \JsonSerializable, \Serializable  
6 -{  
7 - public function __toString()  
8 - {  
9 - return $this->getContent();  
10 - }  
11 -  
12 - public function jsonSerialize()  
13 - {  
14 - return $this->getContent();  
15 - }  
16 -  
17 - public function serialize()  
18 - {  
19 - return serialize($this->content);  
20 - }  
21 -  
22 - public function unserialize($serialized)  
23 - {  
24 - return $this->content = unserialize($serialized);  
25 - }  
26 -}  
1 -<?php  
2 -  
3 -namespace addons\epay\library;  
4 -  
5 -use addons\third\model\Third;  
6 -use app\common\library\Auth;  
7 -use Exception;  
8 -use think\Session;  
9 -use Yansongda\Pay\Pay;  
10 -use Yansongda\Supports\Str;  
11 -  
12 -/**  
13 - * 订单服务类  
14 - *  
15 - * @package addons\epay\library  
16 - */  
17 -class Service  
18 -{  
19 -  
20 - /**  
21 - * 提交订单  
22 - * @param array|float $amount 订单金额  
23 - * @param string $orderid 订单号  
24 - * @param string $type 支付类型,可选alipay或wechat  
25 - * @param string $title 订单标题  
26 - * @param string $notifyurl 通知回调URL  
27 - * @param string $returnurl 跳转返回URL  
28 - * @param string $method 支付方法  
29 - * @return Response|RedirectResponse|Collection  
30 - * @throws Exception  
31 - */  
32 - public static function submitOrder($amount, $orderid = null, $type = null, $title = null, $notifyurl = null, $returnurl = null, $method = null, $openid = '')  
33 - {  
34 - if (!is_array($amount)) {  
35 - $params = [  
36 - 'amount' => $amount,  
37 - 'orderid' => $orderid,  
38 - 'type' => $type,  
39 - 'title' => $title,  
40 - 'notifyurl' => $notifyurl,  
41 - 'returnurl' => $returnurl,  
42 - 'method' => $method,  
43 - 'openid' => $openid,  
44 - ];  
45 - } else {  
46 - $params = $amount;  
47 - }  
48 - $type = isset($params['type']) && in_array($params['type'], ['alipay', 'wechat']) ? $params['type'] : 'wechat';  
49 - $method = isset($params['method']) ? $params['method'] : 'web';  
50 - $orderid = isset($params['orderid']) ? $params['orderid'] : date("YmdHis") . mt_rand(100000, 999999);  
51 - $amount = isset($params['amount']) ? $params['amount'] : 1;  
52 - $title = isset($params['title']) ? $params['title'] : "支付";  
53 - $auth_code = isset($params['auth_code']) ? $params['auth_code'] : '';  
54 - $openid = isset($params['openid']) ? $params['openid'] : '';  
55 -  
56 - $request = request();  
57 - $notifyurl = isset($params['notifyurl']) ? $params['notifyurl'] : $request->root(true) . '/addons/epay/index/' . $type . 'notify';  
58 - $returnurl = isset($params['returnurl']) ? $params['returnurl'] : $request->root(true) . '/addons/epay/index/' . $type . 'return/out_trade_no/' . $orderid;  
59 - $html = '';  
60 - $config = Service::getConfig($type);  
61 - $config['notify_url'] = $notifyurl;  
62 - $config['return_url'] = $returnurl;  
63 - $isWechat = strpos($request->server('HTTP_USER_AGENT'), 'MicroMessenger') !== false;  
64 -  
65 - $result = null;  
66 - if ($type == 'alipay') {  
67 - //如果是PC支付,判断当前环境,进行跳转  
68 - if ($method == 'web') {  
69 - //如果是微信环境或后台配置PC使用扫码支付  
70 - if ($isWechat || $config['scanpay']) {  
71 - Session::set("alipayorderdata", $params);  
72 - $url = addon_url('epay/api/alipay', [], true, true);  
73 - return RedirectResponse::create($url);  
74 - } elseif ($request->isMobile()) {  
75 - $method = 'wap';  
76 - }  
77 - }  
78 - //创建支付对象  
79 - $pay = Pay::alipay($config);  
80 - $params = [  
81 - 'out_trade_no' => $orderid,//你的订单号  
82 - 'total_amount' => $amount,//单位元  
83 - 'subject' => $title,  
84 - ];  
85 -  
86 - switch ($method) {  
87 - case 'web':  
88 - //电脑支付  
89 - $result = $pay->web($params);  
90 - break;  
91 - case 'wap':  
92 - //手机网页支付  
93 - $result = $pay->wap($params);  
94 - break;  
95 - case 'app':  
96 - //APP支付  
97 - $result = $pay->app($params);  
98 - break;  
99 - case 'scan':  
100 - //扫码支付  
101 - $result = $pay->scan($params);  
102 - break;  
103 - case 'pos':  
104 - //刷卡支付必须要有auth_code  
105 - $params['auth_code'] = $auth_code;  
106 - $result = $pay->pos($params);  
107 - break;  
108 - default:  
109 - }  
110 - } else {  
111 - //如果是PC支付,判断当前环境,进行跳转  
112 - if ($method == 'web') {  
113 - //如果是移动端,但不是微信环境  
114 - if ($request->isMobile() && !$isWechat) {  
115 - $method = 'wap';  
116 - } else {  
117 - Session::set("wechatorderdata", $params);  
118 - $url = addon_url('epay/api/wechat', [], true, true);  
119 - return RedirectResponse::create($url);  
120 - }  
121 - }  
122 -  
123 - //创建支付对象  
124 - $pay = Pay::wechat($config);  
125 - $params = [  
126 - 'out_trade_no' => $orderid,//你的订单号  
127 - 'body' => $title,  
128 - 'total_fee' => $amount * 100, //单位分  
129 - ];  
130 - switch ($method) {  
131 - //case 'web':  
132 - // //电脑支付,跳转到自定义展示页面(FastAdmin独有)  
133 - // $result = $pay->web($params);  
134 - // break;  
135 - case 'mp':  
136 - //公众号支付  
137 - //公众号支付必须有openid  
138 - $params['openid'] = $openid;  
139 - $result = $pay->mp($params);  
140 - break;  
141 - case 'wap':  
142 - //手机网页支付,跳转  
143 - $params['spbill_create_ip'] = $request->ip(0, false);  
144 - $result = $pay->wap($params);  
145 - break;  
146 - case 'app':  
147 - //APP支付,直接返回字符串  
148 - $result = $pay->app($params);  
149 - break;  
150 - case 'scan':  
151 - //扫码支付,直接返回字符串  
152 - $result = $pay->scan($params);  
153 - break;  
154 - case 'pos':  
155 - //刷卡支付,直接返回字符串  
156 - //刷卡支付必须要有auth_code  
157 - $params['auth_code'] = $auth_code;  
158 - $result = $pay->pos($params);  
159 - break;  
160 - case 'miniapp':  
161 - //小程序支付,直接返回字符串  
162 - //小程序支付必须要有openid  
163 - $params['openid'] = $openid;  
164 - $result = $pay->miniapp($params);  
165 - break;  
166 - default:  
167 - }  
168 - }  
169 -  
170 - //使用重写的Response类、RedirectResponse、Collection类  
171 - if ($result instanceof \Symfony\Component\HttpFoundation\RedirectResponse) {  
172 - $result = RedirectResponse::create($result->getTargetUrl());  
173 - } elseif ($result instanceof \Symfony\Component\HttpFoundation\Response) {  
174 - $result = Response::create($result->getContent());  
175 - } elseif ($result instanceof \Yansongda\Supports\Collection) {  
176 - $result = Collection::make($result->all());  
177 - }  
178 -  
179 - return $result;  
180 - }  
181 -  
182 - /**  
183 - * 验证回调是否成功  
184 - * @param string $type 支付类型  
185 - * @param array $config 配置信息  
186 - * @return bool|\Yansongda\Pay\Gateways\Alipay|\Yansongda\Pay\Gateways\Wechat  
187 - */  
188 - public static function checkNotify($type, $config = [])  
189 - {  
190 - $type = strtolower($type);  
191 - if (!in_array($type, ['wechat', 'alipay'])) {  
192 - return false;  
193 - }  
194 - try {  
195 - $config = self::getConfig($type);  
196 - $pay = $type == 'wechat' ? Pay::wechat($config) : Pay::alipay($config);  
197 - $data = $pay->verify();  
198 -  
199 - if ($type == 'alipay') {  
200 - if (in_array($data['trade_status'], ['TRADE_SUCCESS', 'TRADE_FINISHED'])) {  
201 - return $pay;  
202 - }  
203 - } else {  
204 - return $pay;  
205 - }  
206 - } catch (Exception $e) {  
207 - return false;  
208 - }  
209 -  
210 - return false;  
211 - }  
212 -  
213 - /**  
214 - * 验证返回是否成功,请勿用于判断是否支付成功的逻辑验证  
215 - * 已弃用  
216 - *  
217 - * @param string $type 支付类型  
218 - * @param array $config 配置信息  
219 - * @return bool  
220 - * @deprecated 已弃用,请勿用于逻辑验证  
221 - */  
222 - public static function checkReturn($type, $config = [])  
223 - {  
224 - //由于PC及移动端无法获取请求的参数信息,取消return验证,均返回true  
225 - return true;  
226 - }  
227 -  
228 - /**  
229 - * 获取配置  
230 - * @param string $type 支付类型  
231 - * @return array|mixed  
232 - */  
233 - public static function getConfig($type = 'wechat')  
234 - {  
235 - $config = get_addon_config('epay');  
236 - $config = isset($config[$type]) ? $config[$type] : $config['wechat'];  
237 - if ($config['log']) {  
238 - $config['log'] = [  
239 - 'file' => LOG_PATH . 'epaylogs' . DS . $type . '-' . date("Y-m-d") . '.log',  
240 - 'level' => 'debug'  
241 - ];  
242 - }  
243 - if (isset($config['cert_client']) && substr($config['cert_client'], 0, 8) == '/addons/') {  
244 - $config['cert_client'] = ROOT_PATH . str_replace('/', DS, substr($config['cert_client'], 1));  
245 - }  
246 - if (isset($config['cert_key']) && substr($config['cert_key'], 0, 8) == '/addons/') {  
247 - $config['cert_key'] = ROOT_PATH . str_replace('/', DS, substr($config['cert_key'], 1));  
248 - }  
249 - if (isset($config['app_cert_public_key']) && substr($config['app_cert_public_key'], 0, 8) == '/addons/') {  
250 - $config['app_cert_public_key'] = ROOT_PATH . str_replace('/', DS, substr($config['app_cert_public_key'], 1));  
251 - }  
252 - if (isset($config['alipay_root_cert']) && substr($config['alipay_root_cert'], 0, 8) == '/addons/') {  
253 - $config['alipay_root_cert'] = ROOT_PATH . str_replace('/', DS, substr($config['alipay_root_cert'], 1));  
254 - }  
255 - if (isset($config['ali_public_key']) && (Str::endsWith($config['ali_public_key'], '.crt') || Str::endsWith($config['ali_public_key'], '.pem'))) {  
256 - $config['ali_public_key'] = ROOT_PATH . str_replace('/', DS, substr($config['ali_public_key'], 1));  
257 - }  
258 - // 可选  
259 - $config['http'] = [  
260 - 'timeout' => 10,  
261 - 'connect_timeout' => 10,  
262 - // 更多配置项请参考 [Guzzle](https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html)  
263 - ];  
264 -  
265 - $config['notify_url'] = empty($config['notify_url']) ? addon_url('epay/api/notifyx', [], false) . '/type/' . $type : $config['notify_url'];  
266 - $config['notify_url'] = !preg_match("/^(http:\/\/|https:\/\/)/i", $config['notify_url']) ? request()->root(true) . $config['notify_url'] : $config['notify_url'];  
267 - $config['return_url'] = empty($config['return_url']) ? addon_url('epay/api/returnx', [], false) . '/type/' . $type : $config['return_url'];  
268 - $config['return_url'] = !preg_match("/^(http:\/\/|https:\/\/)/i", $config['return_url']) ? request()->root(true) . $config['return_url'] : $config['return_url'];  
269 - return $config;  
270 - }  
271 -  
272 - /**  
273 - * 获取微信Openid  
274 - *  
275 - * @return mixed|string  
276 - */  
277 - public static function getOpenid()  
278 - {  
279 - $config = self::getConfig('wechat');  
280 - $openid = '';  
281 - $auth = Auth::instance();  
282 - if ($auth->isLogin()) {  
283 - $third = get_addon_info('third');  
284 - if ($third && $third['state']) {  
285 - $thirdInfo = Third::where('user_id', $auth->id)->where('platform', 'wechat')->where('apptype', 'mp')->find();  
286 - $openid = $thirdInfo ? $thirdInfo['openid'] : '';  
287 - }  
288 - }  
289 - if (!$openid) {  
290 - $openid = Session::get("openid");  
291 -  
292 - //如果未传openid,则去读取openid  
293 - if (!$openid) {  
294 - $wechat = new Wechat($config['app_id'], $config['app_secret']);  
295 - $openid = $wechat->getOpenid();  
296 - }  
297 - }  
298 - return $openid;  
299 - }  
300 -  
301 -}  
1 -<?php  
2 -  
3 -namespace addons\epay\library;  
4 -  
5 -use fast\Http;  
6 -use think\Cache;  
7 -use think\Session;  
8 -  
9 -/**  
10 - * 微信授权  
11 - *  
12 - */  
13 -class Wechat  
14 -{  
15 - private $app_id = '';  
16 - private $app_secret = '';  
17 - private $scope = 'snsapi_userinfo';  
18 -  
19 - public function __construct($app_id, $app_secret)  
20 - {  
21 - $this->app_id = $app_id;  
22 - $this->app_secret = $app_secret;  
23 - }  
24 -  
25 - /**  
26 - * 获取微信授权链接  
27 - *  
28 - * @return string  
29 - */  
30 - public function getAuthorizeUrl()  
31 - {  
32 - $redirect_uri = addon_url('epay/api/wechat', [], true, true);  
33 - $redirect_uri = urlencode($redirect_uri);  
34 - $state = \fast\Random::alnum();  
35 - Session::set('state', $state);  
36 - return "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$this->app_id}&redirect_uri={$redirect_uri}&response_type=code&scope={$this->scope}&state={$state}#wechat_redirect";  
37 - }  
38 -  
39 - /**  
40 - * 获取微信openid  
41 - *  
42 - * @return mixed|string  
43 - */  
44 - public function getOpenid()  
45 - {  
46 - $openid = Session::get('openid');  
47 - if (!$openid) {  
48 - if (!isset($_GET['code'])) {  
49 - $url = $this->getAuthorizeUrl();  
50 -  
51 - Header("Location: $url");  
52 - exit();  
53 - } else {  
54 - $state = Session::get('state');  
55 - if ($state == $_GET['state']) {  
56 - $code = $_GET['code'];  
57 - $token = $this->getAccessToken($code);  
58 - if (!isset($token['openid']) && isset($token['errmsg'])) {  
59 - exception($token['errmsg']);  
60 - }  
61 - $openid = isset($token['openid']) ? $token['openid'] : '';  
62 - if ($openid) {  
63 - Session::set("openid", $openid);  
64 - }  
65 - }  
66 - }  
67 - }  
68 - return $openid;  
69 - }  
70 -  
71 - /**  
72 - * 获取授权token网页授权  
73 - *  
74 - * @param string $code  
75 - * @return mixed|string  
76 - */  
77 - public function getAccessToken($code = '')  
78 - {  
79 - $params = [  
80 - 'appid' => $this->app_id,  
81 - 'secret' => $this->app_secret,  
82 - 'code' => $code,  
83 - 'grant_type' => 'authorization_code'  
84 - ];  
85 - $ret = Http::sendRequest('https://api.weixin.qq.com/sns/oauth2/access_token', $params, 'GET');  
86 - if ($ret['ret']) {  
87 - $ar = json_decode($ret['msg'], true);  
88 - return $ar;  
89 - }  
90 - return [];  
91 - }  
92 -  
93 - public function getJsticket($code = '')  
94 - {  
95 - $jsticket = Session::get('jsticket');  
96 - if (!$jsticket) {  
97 - $token = $this->getAccessToken($code);  
98 - $params = [  
99 - 'access_token' => 'token',  
100 - 'type' => 'jsapi',  
101 - ];  
102 - $ret = Http::sendRequest('https://api.weixin.qq.com/cgi-bin/ticket/getticket', $params, 'GET');  
103 - if ($ret['ret']) {  
104 - $ar = json_decode($ret['msg'], true);  
105 - return $ar;  
106 - }  
107 - }  
108 - return $jsticket;  
109 - }  
110 -}  
1 -<?php  
2 -  
3 -namespace Yansongda\Pay\Contracts;  
4 -  
5 -use Symfony\Component\HttpFoundation\Response;  
6 -use Yansongda\Supports\Collection;  
7 -  
8 -interface GatewayApplicationInterface  
9 -{  
10 - /**  
11 - * To pay.  
12 - *  
13 - * @author yansongda <me@yansonga.cn>  
14 - *  
15 - * @param string $gateway  
16 - * @param array $params  
17 - *  
18 - * @return Collection|Response  
19 - */  
20 - public function pay($gateway, $params);  
21 -  
22 - /**  
23 - * Query an order.  
24 - *  
25 - * @author yansongda <me@yansongda.cn>  
26 - *  
27 - * @param string|array $order  
28 - *  
29 - * @return Collection  
30 - */  
31 - public function find($order, string $type);  
32 -  
33 - /**  
34 - * Refund an order.  
35 - *  
36 - * @author yansongda <me@yansongda.cn>  
37 - *  
38 - * @return Collection  
39 - */  
40 - public function refund(array $order);  
41 -  
42 - /**  
43 - * Cancel an order.  
44 - *  
45 - * @author yansongda <me@yansongda.cn>  
46 - *  
47 - * @param string|array $order  
48 - *  
49 - * @return Collection  
50 - */  
51 - public function cancel($order);  
52 -  
53 - /**  
54 - * Close an order.  
55 - *  
56 - * @author yansongda <me@yansongda.cn>  
57 - *  
58 - * @param string|array $order  
59 - *  
60 - * @return Collection  
61 - */  
62 - public function close($order);  
63 -  
64 - /**  
65 - * Verify a request.  
66 - *  
67 - * @author yansongda <me@yansongda.cn>  
68 - *  
69 - * @param string|array|null $content  
70 - *  
71 - * @return Collection  
72 - */  
73 - public function verify($content, bool $refund);  
74 -  
75 - /**  
76 - * Echo success to server.  
77 - *  
78 - * @author yansongda <me@yansongda.cn>  
79 - *  
80 - * @return Response  
81 - */  
82 - public function success();  
83 -}