├── Reward ├── .gitignore ├── LICENSE ├── full_table.sql ├── Plugin.php ├── lib │ ├── Payjs.php │ └── AlipayF2F.php ├── js │ └── app.js └── Action.php ├── mix-manifest.json ├── webpack.mix.js ├── README.md ├── src ├── app.css ├── http.js └── app.js └── package.json /Reward/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /mix-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "/js/app.js": "/js/app.js" 3 | } -------------------------------------------------------------------------------- /webpack.mix.js: -------------------------------------------------------------------------------- 1 | let mix = require('laravel-mix'); 2 | 3 | /* 4 | |-------------------------------------------------------------------------- 5 | | Mix Asset Management 6 | |-------------------------------------------------------------------------- 7 | | 8 | | Mix provides a clean, fluent API for defining some Webpack build steps 9 | | for your Laravel application. By default, we are compiling the Sass 10 | | file for your application, as well as bundling up your JS files. 11 | | 12 | */ 13 | 14 | mix.setPublicPath('./') 15 | .js('src/app.js', 'Reward/js/') 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Reward 2 | 3 | Reward是一个打赏插件,简单来说 就是那种有钱的土豪大佬看上我写的白水文,随手就点一下打赏,然后我就收到了这笔钱。 4 | 5 | 6 | demo: 7 | https://yubanmei.com/archives/27/ 8 | 9 | ### 如何安装 10 | 11 | 下载项目,将Reward文件夹放到./usr/plugins/这个地方即可,请不要更改文件夹名称,会导致找不到文件。 12 | 然后到typecho后台启用即可 13 | 14 | ### 更改JavaScript 15 | ``` 16 | npm i 17 | npm run watch 18 | ``` 19 | 20 | 注意事项 21 | 22 | - 设置正确的时区 23 | 24 | 实现功能 25 | 26 | - 自定义完全后的消息 27 | - 插件设置项都是后台的,不需要更改源码 28 | - 轮询逻辑完备,也不会有人这么蛋疼给伪造吧 29 | - 可选是否验证ssl 30 | - 可选多个二维码生成api 31 | - 支持payjs渠道 32 | - 支持支付宝当面付渠道 33 | - 无冲突依赖,完全原生js 34 | - 引用sweetalert,实现美美哒 35 | 36 | 37 | 引用项目 38 | 39 | https://github.com/t4t5/sweetalert 40 | https://github.com/musnow/alipayf2f 41 | https://github.com/musnow/payjs 42 | 43 | 44 | # License 许可证 45 | Open sourced under the MIT license. 46 | 47 | 根据 MIT 许可证开源。 -------------------------------------------------------------------------------- /src/app.css: -------------------------------------------------------------------------------- 1 | .swal-footer{ 2 | text-align: center; 3 | } 4 | #plugin-total{ 5 | width: 220px!important; 6 | margin: 0px auto; 7 | -webkit-appearance: none; 8 | background-color: #fff; 9 | border: none; 10 | font-size: 14px; 11 | display: block; 12 | box-sizing: border-box; 13 | width: 100%; 14 | border: 1px solid rgba(0,0,0,.14); 15 | padding: 10px 13px; 16 | border-radius: 2px; 17 | transition: border-color .2s; 18 | } 19 | #plugin-total:focus{ 20 | outline: none; 21 | border-color: #6db8ff; 22 | } 23 | #plugin-render{ 24 | background-color: #a3dd82; 25 | box-shadow: 0 2px 8px 0 rgba(0,0,0,0.07); 26 | border-radius: 4px; 27 | border: none; 28 | color: #fff; 29 | font-size: 15px; 30 | color: #fff; 31 | padding: 9px 18px; 32 | } 33 | #plugin-render:hover{ 34 | background-color: #98d973; 35 | } 36 | 37 | #plugin{ 38 | margin: 20px auto; 39 | width: 66px; 40 | display: block; 41 | position: relative; 42 | z-index: 2; 43 | } -------------------------------------------------------------------------------- /src/http.js: -------------------------------------------------------------------------------- 1 | export default { 2 | get(url){ 3 | return this.request(url) 4 | }, 5 | post(url,value = null){ 6 | return this.request(url,'post',value) 7 | }, 8 | request(url, method = 'get',value = null) { 9 | return new Promise(function (resolve, reject) { 10 | var xhr = new XMLHttpRequest(); 11 | xhr.open(method, url); 12 | xhr.onload = function () { 13 | if (this.status >= 200 && this.status < 300) { 14 | resolve(JSON.parse(xhr.response)); 15 | } else { 16 | reject({ 17 | status: this.status, 18 | statusText: xhr.statusText 19 | }) 20 | } 21 | } 22 | xhr.onerror = function () { 23 | reject({ 24 | status: this.status, 25 | statusText: xhr.statusText 26 | }) 27 | } 28 | xhr.send(value) 29 | }) 30 | } 31 | } -------------------------------------------------------------------------------- /Reward/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 musnow 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rewardforpayjs", 3 | "version": "1.0.0", 4 | "description": "reward Plugin", 5 | "author": "musnow", 6 | "license": "MIT", 7 | "dependencies": { 8 | "sweetalert": "^2.1.0", 9 | "sweetalert2": "^7.22.2" 10 | }, 11 | "devDependencies": { 12 | "cross-env": "^5.1.6", 13 | "laravel-mix": "^2.1.11" 14 | }, 15 | "scripts": { 16 | "dev": "cross-env NODE_ENV=development webpack --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", 17 | "watch": "cross-env NODE_ENV=development webpack --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", 18 | "hot": "cross-env NODE_ENV=development webpack-dev-server --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js", 19 | "prod": "cross-env NODE_ENV=production webpack --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", 20 | "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Reward/full_table.sql: -------------------------------------------------------------------------------- 1 | SET FOREIGN_KEY_CHECKS=0; 2 | 3 | -- ---------------------------- 4 | -- Table structure for typecho_order 5 | -- ---------------------------- 6 | DROP TABLE IF EXISTS `typecho_order`; 7 | CREATE TABLE `typecho_order` ( 8 | `id` int(11) NOT NULL AUTO_INCREMENT, 9 | `user_id` int(11) DEFAULT '0', 10 | `type` varchar(255) DEFAULT '1', 11 | `unique_id` varchar(255) DEFAULT NULL, 12 | `status` int(255) DEFAULT '0', 13 | `content` varchar(255) DEFAULT NULL, 14 | `order_total` varchar(255) DEFAULT NULL, 15 | `money` varchar(255) DEFAULT NULL, 16 | `created_at` int(11) DEFAULT NULL, 17 | PRIMARY KEY (`id`) 18 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 19 | 20 | -- ---------------------------- 21 | -- Table structure for typecho_order_alipay 22 | -- ---------------------------- 23 | DROP TABLE IF EXISTS `typecho_order_alipay`; 24 | CREATE TABLE `typecho_order_alipay` ( 25 | `id` int(11) NOT NULL AUTO_INCREMENT, 26 | `out_trade_no` varchar(255) DEFAULT NULL, 27 | `buyer_logon_id` varchar(255) DEFAULT NULL, 28 | `trade_status` varchar(255) DEFAULT NULL, 29 | `total_amount` varchar(255) DEFAULT NULL, 30 | `receipt_amount` varchar(255) DEFAULT NULL, 31 | `buyer_pay_amount` varchar(255) DEFAULT NULL, 32 | `notify_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, 33 | `notify_id` varchar(255) DEFAULT NULL, 34 | `json_file` text, 35 | PRIMARY KEY (`id`), 36 | KEY `id` (`id`,`out_trade_no`(191),`trade_status`(191)) USING BTREE 37 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 38 | 39 | -- ---------------------------- 40 | -- Table structure for typecho_order_wxpay 41 | -- ---------------------------- 42 | DROP TABLE IF EXISTS `typecho_order_wxpay`; 43 | CREATE TABLE `typecho_order_wxpay` ( 44 | `id` int(11) NOT NULL AUTO_INCREMENT, 45 | `time_end` datetime DEFAULT NULL, 46 | `return_code` int(255) DEFAULT NULL, 47 | `total_fee` int(255) DEFAULT NULL, 48 | `out_trade_no` varchar(255) DEFAULT NULL, 49 | `payjs_order_id` varchar(255) DEFAULT NULL, 50 | `attach` varchar(255) DEFAULT '', 51 | `transaction_id` varchar(255) DEFAULT NULL, 52 | `openid` varchar(255) DEFAULT NULL, 53 | `mchid` varchar(255) DEFAULT '', 54 | `sign` varchar(255) DEFAULT NULL, 55 | `json_file` text, 56 | PRIMARY KEY (`id`) 57 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 58 | 59 | -------------------------------------------------------------------------------- /src/app.js: -------------------------------------------------------------------------------- 1 | import './app.css' 2 | import http from "./http"; 3 | 4 | 5 | let btn = document.getElementById("plugin-render") 6 | let reqUrl = '/reward/query' 7 | let resUrl = '/reward/order' 8 | let checkOrderStatus 9 | let total = document.createElement("input"); 10 | total.setAttribute("id","plugin-total"); 11 | total.type = "text"; 12 | total.placeholder = "单位是元,币种为人民币"; 13 | total.value = 9.9; 14 | 15 | if (btn) { 16 | btn.addEventListener('click', function () { 17 | swal({ 18 | title: "打赏", 19 | text: "感谢支持,请输入金额,然后点击下一步", 20 | icon: "success", 21 | buttons: { 22 | alipay: { 23 | text: "支付宝", 24 | }, 25 | wxpay: { 26 | text: "扫微信", 27 | }, 28 | }, 29 | content: total, 30 | }) 31 | .then(willDelete => { 32 | if (willDelete && total.value) { 33 | http.get(reqUrl + '?total=' + total.value + '&type=' + willDelete) 34 | .then(response => { 35 | if (response.code == 'success') { 36 | swal({ 37 | title: response.data.title, 38 | text: '拿出小手机扫一扫', 39 | icon: response.data.url, 40 | buttons: { 41 | close: { 42 | text: "关闭", 43 | }, 44 | }, 45 | closeOnEsc: false, 46 | closeOnClickOutside: false, 47 | }) 48 | .then(res =>{ 49 | if (res == 'close'){ 50 | clearTimeout(checkOrderStatus) 51 | setTimeout("location.reload()", 5000) 52 | } 53 | }) 54 | 55 | 56 | checkOrderStatus = setInterval(function () { 57 | http.get(resUrl + '?id=' + response.data.id + '&type=' + willDelete) 58 | .then(response => { 59 | if (response.code == 'success') { 60 | clearTimeout(checkOrderStatus) 61 | setTimeout("location.reload()", 5000) 62 | swal({ 63 | title: "Good job!", 64 | text: response.data.msg, 65 | icon: "success", 66 | }) 67 | } 68 | }) 69 | }, 3000) 70 | } 71 | }) 72 | } else { 73 | swal("取消打赏","嘤嘤嘤,为什么选择放弃","error") 74 | } 75 | }) 76 | }) 77 | } 78 | -------------------------------------------------------------------------------- /Reward/Plugin.php: -------------------------------------------------------------------------------- 1 | footer = array('Reward_Plugin', 'footer'); 19 | Typecho_Plugin::factory('Widget_Archive')->singleHandle = array('Reward_Plugin','render'); 20 | 21 | //增加路由 22 | Helper::addRoute("reward_alipay_notify","/reward/alipay/notify","Reward_Action",'reward_alipay_notify'); 23 | Helper::addRoute("reward_payjs_notify","/reward/payjs/notify","Reward_Action",'reward_payjs_notify'); 24 | Helper::addRoute("reward_order","/reward/order","Reward_Action",'reward_order'); 25 | Helper::addRoute("reward_query","/reward/query","Reward_Action",'reward_query'); 26 | 27 | //写入数据库架构 28 | $db = Typecho_Db::get(); 29 | /** 初始化数据库结构 */ 30 | $scripts = file_get_contents ('usr/plugins/Reward/full_table.sql'); 31 | $scripts = str_replace('typecho_',$db->getPrefix(), $scripts); 32 | $scripts = explode(';', $scripts); 33 | foreach ($scripts as $script) { 34 | $script = trim($script); 35 | if ($script) { 36 | $db->query($script, Typecho_Db::WRITE); 37 | } 38 | } 39 | 40 | return _t("插件已启用"); 41 | } 42 | /* 个人用户的配置方法 */ 43 | public static function personalConfig(Typecho_Widget_Helper_Form $form){} 44 | /* 插件配置方法 */ 45 | public static function config(Typecho_Widget_Helper_Form $form){ 46 | 47 | $notify_wxpay_url = Helper::options()->siteUrl . 'reward/payjs/notify'; 48 | $notify_alipay_url = Helper::options()->siteUrl . 'reward/alipay/notify'; 49 | $settings = [ 50 | new Typecho_Widget_Helper_Form_Element_Text('reward_payjs_id', NULL, '', _t('payjs商户号')), 51 | new Typecho_Widget_Helper_Form_Element_Text('reward_payjs_key', NULL, '', _t('payjs接口通信密钥')), 52 | new Typecho_Widget_Helper_Form_Element_Text('reward_payjs_notify_url', NULL, $notify_wxpay_url, _t('payjs接口回调地址'),_t('没有特殊需求请不要更改')), 53 | 54 | new Typecho_Widget_Helper_Form_Element_Text('reward_alipay_id', NULL, '', _t('支付宝APPID')), 55 | new Typecho_Widget_Helper_Form_Element_Text('reward_alipay_private_key', NULL, '', _t('支付宝RSA2(SHA256)应用密钥'),_t('就是你自己生成的rsa密钥')), 56 | new Typecho_Widget_Helper_Form_Element_Text('reward_alipay_public_key', NULL, '', _t('支付宝RSA2(SHA256)公钥'),_t('支付宝公钥,支付宝公钥,支付宝公钥')), 57 | new Typecho_Widget_Helper_Form_Element_Text('reward_alipay_notify_url', NULL, $notify_alipay_url, _t('支付宝接口回调地址'),_t('没有特殊需求请不要更改')), 58 | 59 | new Typecho_Widget_Helper_Form_Element_Text('success_msg', NULL, '感谢大佬的打赏,定当尽心尽力更新文章', _t('充值成功时,返回信息'),_t('不要随便关闭插件,会导致数据库数据清空,已经存在数据的请先备份数据库')), 60 | 61 | new Typecho_Widget_Helper_Form_Element_Checkbox( 62 | 'reward_ssl', 63 | array(true => _t('验证ssl证书')), 64 | array(true), 65 | _t('是否验证ssl证书')), 66 | 67 | new Typecho_Widget_Helper_Form_Element_Radio( 68 | 'recode_type', 69 | array( 70 | 1 => _t('iClick'), 71 | 2 => _t('快站'), 72 | 3 => _t('QR Code Generator'), 73 | ), 74 | 1, 75 | _t('二维码生成方式')), 76 | ]; 77 | 78 | foreach ($settings as $key){ 79 | $form->addInput($key); 80 | } 81 | } 82 | 83 | /** 84 | * 禁用插件方法,如果禁用失败,直接抛出异常 85 | * 86 | * @static 87 | * @access public 88 | * @return void 89 | * @throws Typecho_Plugin_Exception 90 | */ 91 | public static function deactivate() 92 | { 93 | Helper::removeRoute("reward_order"); 94 | Helper::removeRoute("reward_query"); 95 | Helper::removeRoute("reward_alipay_notify"); 96 | Helper::removeRoute("reward_payjs_notify"); 97 | return _t("插件已禁用"); 98 | } 99 | 100 | //插入页面尾部 101 | public static function footer(){ 102 | echo ''; 103 | echo ''; 104 | } 105 | 106 | //插入打赏代码 107 | public static function render($archive){ 108 | //不能使用缩进,会解析空格和tab,支持markdown语法 109 | $rewardhtml = ' 110 |

111 | 112 |

113 | '; 114 | $archive->text .= $rewardhtml; 115 | } 116 | } -------------------------------------------------------------------------------- /Reward/lib/Payjs.php: -------------------------------------------------------------------------------- 1 | $val) { 23 | if (isset($key)) { 24 | $this->$key = $val; 25 | } 26 | } 27 | } 28 | 29 | /* 30 | * 扫码支付 31 | * @return json 32 | */ 33 | public function qrPay($data = []) 34 | { 35 | return $this->merge('native', [ 36 | 'total_fee' => $data['TotalFee'], 37 | 'body' => $data['Body'], 38 | 'attach' => @$data['Attach'], 39 | 'out_trade_no' => $data['outTradeNo'] 40 | ]); 41 | } 42 | 43 | /* 44 | * 收银台支付 45 | * @return mixed 46 | */ 47 | public function Cashier($data = []) 48 | { 49 | return $this->merge('cashier', [ 50 | 'total_fee' => $data['TotalFee'], 51 | 'body' => $data['Body'], 52 | 'attach' => @$data['Attach'], 53 | 'out_trade_no' => $data['outTradeNo'], 54 | 'callback_url' => @$data['callbackUrl'] 55 | ]); 56 | } 57 | 58 | /* 59 | * 订单查询 60 | * @return mixed 61 | */ 62 | public function Query($data = []) 63 | { 64 | return $this->merge('check', [ 65 | 'payjs_order_id' => $data['PayjsOrderId'] 66 | ]); 67 | } 68 | 69 | /* 70 | * 关闭订单 71 | * @return json 72 | */ 73 | public function Close($data = []) 74 | { 75 | return $this->merge('close', [ 76 | 'payjs_order_id' => $data['PayjsOrderId'] 77 | ]); 78 | } 79 | 80 | /* 81 | * 获取用户资料 82 | * @return json 83 | */ 84 | public function User($data = []) 85 | { 86 | return $this->merge('user', [ 87 | 'openid' => $data['openid'] 88 | ]); 89 | } 90 | 91 | /* 92 | * 获取商户资料 93 | * @return json 94 | */ 95 | public function Info() 96 | { 97 | return $this->merge('info'); 98 | } 99 | 100 | /* 101 | * 验证notify数据 102 | * @return Boolean 103 | */ 104 | public function Checking($data = array()) 105 | { 106 | $beSign = $data['sign']; 107 | unset($data['sign']); 108 | if ($this->Sign($data) == $beSign) { 109 | return true; 110 | } else { 111 | return false; 112 | } 113 | } 114 | 115 | /* 116 | * 数据签名 117 | * @return string 118 | */ 119 | protected function Sign(array $data) 120 | { 121 | ksort($data); 122 | return strtoupper(md5(urldecode(http_build_query($data)) . '&key=' . $this->MerchantKey)); 123 | } 124 | 125 | /* 126 | * 预处理数据 127 | * @return mixed 128 | */ 129 | protected function merge($method, $data = []) 130 | { 131 | if ($this->AutoSign) { 132 | if (!array_key_exists('payjs_order_id', $data)) { 133 | $data['mchid'] = $this->MerchantID; 134 | if (!empty($this->NotifyURL)) { 135 | $data['notify_url'] = $this->NotifyURL; 136 | } 137 | if (is_null(@$data['attach'])) { 138 | unset($data['attach']); 139 | } 140 | } 141 | $data['sign'] = $this->Sign($data); 142 | } 143 | return $this->Curl($method, $data); 144 | } 145 | 146 | /* 147 | * curl 148 | * @return mixed 149 | */ 150 | protected function Curl($method, $data, $options = array()) 151 | { 152 | $url = $this->requestUrl . $method; 153 | $ch = curl_init(); 154 | curl_setopt($ch, CURLOPT_URL, $url); 155 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 156 | curl_setopt($ch, CURLOPT_BINARYTRANSFER, true); 157 | curl_setopt($ch, CURLOPT_POSTFIELDS, $data); 158 | if (!empty($options)) { 159 | curl_setopt_array($ch, $options); 160 | } 161 | if (!$this->ssl) { 162 | //https请求 不验证证书和host 163 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 164 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); 165 | } 166 | $cexecute = curl_exec($ch); 167 | curl_close($ch); 168 | if ($cexecute) { 169 | if ($this->ToObject) { 170 | return json_decode($cexecute); 171 | } else { 172 | return $cexecute; 173 | } 174 | } else { 175 | return false; 176 | } 177 | } 178 | } -------------------------------------------------------------------------------- /Reward/js/app.js: -------------------------------------------------------------------------------- 1 | !function(t){var e={};function n(r){if(e[r])return e[r].exports;var o=e[r]={i:r,l:!1,exports:{}};return t[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:r})},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="/",n(n.s=0)}([function(t,e,n){t.exports=n(1)},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});n(2);var r={get:function(t){return this.request(t)},post:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;return this.request(t,"post",e)},request:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"get",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;return new Promise(function(r,o){var i=new XMLHttpRequest;i.open(e,t),i.onload=function(){this.status>=200&&this.status<300?r(JSON.parse(i.response)):o({status:this.status,statusText:i.statusText})},i.onerror=function(){o({status:this.status,statusText:i.statusText})},i.send(n)})}},o=document.getElementById("plugin-render"),i=void 0,s=document.createElement("input");s.setAttribute("id","plugin-total"),s.type="text",s.placeholder="单位是元,币种为人民币",s.value=9.9,o&&o.addEventListener("click",function(){swal({title:"打赏",text:"感谢支持,请输入金额,然后点击下一步",icon:"success",buttons:{alipay:{text:"支付宝"},wxpay:{text:"扫微信"}},content:s}).then(function(t){t&&s.value?r.get("/reward/query?total="+s.value+"&type="+t).then(function(e){"success"==e.code&&(swal({title:e.data.title,text:"拿出小手机扫一扫",icon:e.data.url,buttons:{close:{text:"关闭"}},closeOnEsc:!1,closeOnClickOutside:!1}).then(function(t){"close"==t&&(clearTimeout(i),setTimeout("location.reload()",5e3))}),i=setInterval(function(){r.get("/reward/order?id="+e.data.id+"&type="+t).then(function(t){"success"==t.code&&(clearTimeout(i),setTimeout("location.reload()",5e3),swal({title:"Good job!",text:t.data.msg,icon:"success"}))})},3e3))}):swal("取消打赏","嘤嘤嘤,为什么选择放弃","error")})})},function(t,e,n){var r=n(3);"string"==typeof r&&(r=[[t.i,r,""]]);var o={transform:void 0};n(5)(r,o);r.locals&&(t.exports=r.locals)},function(t,e,n){(t.exports=n(4)(!1)).push([t.i,".swal-footer{text-align:center}#plugin-total{width:220px!important;margin:0 auto;-webkit-appearance:none;background-color:#fff;border:none;font-size:14px;display:block;box-sizing:border-box;width:100%;border:1px solid rgba(0,0,0,.14);padding:10px 13px;border-radius:2px;transition:border-color .2s}#plugin-total:focus{outline:none;border-color:#6db8ff}#plugin-render{background-color:#a3dd82;box-shadow:0 2px 8px 0 rgba(0,0,0,.07);border-radius:4px;border:none;font-size:15px;color:#fff;padding:9px 18px}#plugin-render:hover{background-color:#98d973}#plugin{margin:20px auto;width:66px;display:block;position:relative;z-index:2}",""])},function(t,e){t.exports=function(t){var e=[];return e.toString=function(){return this.map(function(e){var n=function(t,e){var n=t[1]||"",r=t[3];if(!r)return n;if(e&&"function"==typeof btoa){var o=(s=r,"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(s))))+" */"),i=r.sources.map(function(t){return"/*# sourceURL="+r.sourceRoot+t+" */"});return[n].concat(i).concat([o]).join("\n")}var s;return[n].join("\n")}(e,t);return e[2]?"@media "+e[2]+"{"+n+"}":n}).join("")},e.i=function(t,n){"string"==typeof t&&(t=[[null,t,""]]);for(var r={},o=0;o=0&&l.splice(e,1)}function b(t){var e=document.createElement("style");return t.attrs.type="text/css",g(e,t.attrs),h(t,e),e}function g(t,e){Object.keys(e).forEach(function(n){t.setAttribute(n,e[n])})}function x(t,e){var n,r,o,i;if(e.transform&&t.css){if(!(i=e.transform(t.css)))return function(){};t.css=i}if(e.singleton){var s=c++;n=u||(u=b(e)),r=w.bind(null,n,s,!1),o=w.bind(null,n,s,!0)}else t.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(n=function(t){var e=document.createElement("link");return t.attrs.type="text/css",t.attrs.rel="stylesheet",g(e,t.attrs),h(t,e),e}(e),r=function(t,e,n){var r=n.css,o=n.sourceMap,i=void 0===e.convertToAbsoluteUrls&&o;(e.convertToAbsoluteUrls||i)&&(r=f(r));o&&(r+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(o))))+" */");var s=new Blob([r],{type:"text/css"}),a=t.href;t.href=URL.createObjectURL(s),a&&URL.revokeObjectURL(a)}.bind(null,n,e),o=function(){v(n),n.href&&URL.revokeObjectURL(n.href)}):(n=b(e),r=function(t,e){var n=e.css,r=e.media;r&&t.setAttribute("media",r);if(t.styleSheet)t.styleSheet.cssText=n;else{for(;t.firstChild;)t.removeChild(t.firstChild);t.appendChild(document.createTextNode(n))}}.bind(null,n),o=function(){v(n)});return r(t),function(e){if(e){if(e.css===t.css&&e.media===t.media&&e.sourceMap===t.sourceMap)return;r(t=e)}else o()}}t.exports=function(t,e){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");(e=e||{}).attrs="object"==typeof e.attrs?e.attrs:{},e.singleton||(e.singleton=s()),e.insertInto||(e.insertInto="head"),e.insertAt||(e.insertAt="bottom");var n=d(t,e);return p(n,e),function(t){for(var r=[],o=0;oplugin('Reward'); 19 | $this->payjsinit($con); 20 | $this->alipayf2finit($con); 21 | $this->db = Typecho_Db::get(); 22 | } 23 | 24 | //初始化payjs 25 | public function payjsinit($con) 26 | { 27 | if (!empty(@$con->reward_ssl[0])) { 28 | $ssl = true; 29 | } else { 30 | $ssl = false; 31 | } 32 | $config = [ 33 | 'MerchantID' => $con->reward_payjs_id, 34 | 'MerchantKey' => $con->reward_payjs_key, 35 | 'NotifyURL' => $con->reward_payjs_notify_url, 36 | 'ssl' => $ssl, 37 | ]; 38 | return $this->payjs = new Payjs($config); 39 | } 40 | 41 | //初始化支付宝当面付 42 | public function alipayf2finit($con) 43 | { 44 | if (!empty(@$con->reward_ssl[0])) { 45 | $ssl = true; 46 | } else { 47 | $ssl = false; 48 | } 49 | $config = [ 50 | 'appId' => $con->reward_alipay_id, 51 | 'rsaPrivateKey' => $con->reward_alipay_private_key, 52 | 'alipayPublicKey' => $con->reward_alipay_public_key, 53 | 'notifyUrl' => $con->reward_alipay_notify_url, 54 | 'ssl' => $ssl, 55 | ]; 56 | return $this->alipay = new AlipayF2F($config); 57 | } 58 | 59 | //轮询逻辑 60 | public function reward_order() 61 | { 62 | $_id = @$_GET['id']; 63 | $_type = @$_GET['type']; 64 | if (empty($_id) || empty($_type)) { 65 | exit('参数不正确'); 66 | } 67 | 68 | switch ($_type){ 69 | case 'wxpay': 70 | $order = $this->db->fetchRow( 71 | $this->db->select() 72 | ->from('table.order_wxpay') 73 | ->where('out_trade_no = ?', $_id) 74 | ->where('return_code = ?', 1) 75 | ->limit(1) 76 | ); 77 | break; 78 | case 'alipay': 79 | $order = $this->db->fetchRow( 80 | $this->db->select() 81 | ->from('table.order_alipay') 82 | ->where('out_trade_no = ?', $_id) 83 | ->where('trade_status = ?', 'TRADE_SUCCESS') 84 | ->limit(1) 85 | ); 86 | break; 87 | } 88 | $olddata = json_decode(@$order['json_file'], true); 89 | 90 | if (!empty($order)) { 91 | switch ($_type) { 92 | case 'alipay': 93 | $status = $this->alipay->rsaCheck($olddata); 94 | break; 95 | case 'wxpay': 96 | $status = $this->payjs->Checking($olddata); 97 | break; 98 | default: 99 | $status = false; 100 | break; 101 | } 102 | 103 | if ($status) { 104 | 105 | $this->db->query( 106 | $this->db->update('table.order') 107 | ->rows(['status' => 1]) 108 | ->where('unique_id = ?', $_id) 109 | ); 110 | 111 | echo json_encode([ 112 | 'code' => 'success', 113 | 'data' => [ 114 | 'msg' => Helper::options()->plugin('Reward')->success_msg 115 | ], 116 | ]); 117 | } else { 118 | echo json_encode([ 119 | 'code' => 'error', 120 | ]); 121 | } 122 | 123 | } else { 124 | echo json_encode([ 125 | 'code' => 'wait', 126 | ]); 127 | } 128 | 129 | 130 | } 131 | 132 | //生成二维码 133 | public function reward_query() 134 | { 135 | $total = @$_GET['total']; 136 | $_type = @$_GET['type']; 137 | if (empty($total) || empty($_type)) { 138 | exit('参数不正确'); 139 | } 140 | 141 | $unique_id = $this->genRandomChar(); 142 | 143 | switch ($_type) { 144 | case 'alipay': 145 | $ret = $this->alipay->qrPay([ 146 | 'outTradeNo' => $unique_id, 147 | 'totalFee' => $total, 148 | 'orderName' => 'Reward article', 149 | ]); 150 | if (@$ret['alipay_trade_precreate_response']['code'] != 10000) { 151 | $status = false; 152 | } else { 153 | $status = true; 154 | $title = '支付宝扫码'; 155 | $qrtmp = $this->getQRcodeURL($ret['alipay_trade_precreate_response']['qr_code']); 156 | $qrcode_url = $qrtmp; 157 | } 158 | break; 159 | case 'wxpay': 160 | $_total = $total * 100; 161 | $ret = $this->payjs->qrPay([ 162 | 'TotalFee' => $_total, 163 | 'Body' => 'Reward article', 164 | 'outTradeNo' => $unique_id, 165 | ]); 166 | if ($ret->return_code == 1) { 167 | $status = true; 168 | $title = '微信扫码'; 169 | $qrcode_url = $ret->qrcode; 170 | } else { 171 | $status = false; 172 | } 173 | break; 174 | 175 | default: 176 | $status = false; 177 | echo json_encode([ 178 | 'code' => 'error', 179 | ]); 180 | break; 181 | } 182 | 183 | 184 | if ($status) { 185 | 186 | $arr = [ 187 | "unique_id" => $unique_id, 188 | "type" => $_type, 189 | "content" => '得到大佬打赏,¥' . $total, 190 | "order_total" => $total, 191 | "created_at" => time(), 192 | ]; 193 | 194 | $this->db->query($this->db->insert('table.order')->rows($arr)); 195 | 196 | echo json_encode([ 197 | 'code' => 'success', 198 | 'data' => [ 199 | 'id' => $unique_id, 200 | 'url' => $qrcode_url, 201 | 'title' => $title, 202 | ], 203 | ]); 204 | } else { 205 | echo json_encode([ 206 | 'code' => 'error', 207 | 'msg' => '生成二维码错误', 208 | ]); 209 | } 210 | } 211 | 212 | public function reward_alipay_notify() 213 | { 214 | if (!empty(@$_REQUEST['notify_id'])) { 215 | $arr = [ 216 | 'out_trade_no' => @$_REQUEST['out_trade_no'], 217 | 'buyer_logon_id' => @$_REQUEST['buyer_logon_id'], 218 | 'trade_status' => @$_REQUEST['trade_status'], 219 | 'total_amount' => @$_REQUEST['total_amount'], 220 | 'receipt_amount' => @$_REQUEST['receipt_amount'], 221 | 'buyer_pay_amount' => @$_REQUEST['buyer_pay_amount'], 222 | 'notify_time' => @$_REQUEST['notify_time'], 223 | 'notify_id' => @$_REQUEST['notify_id'], 224 | 'json_file' => json_encode($_REQUEST), 225 | ]; 226 | $this->db->query($this->db->insert('table.order_alipay')->rows($arr)); 227 | } 228 | echo 'success'; 229 | } 230 | 231 | public function reward_payjs_notify() 232 | { 233 | if (!empty(@$_REQUEST['return_code'])) { 234 | $arr = [ 235 | 'time_end' => @$_REQUEST['time_end'], 236 | 'return_code' => @$_REQUEST['return_code'], 237 | 'total_fee' => @$_REQUEST['total_fee'], 238 | 'out_trade_no' => @$_REQUEST['out_trade_no'], 239 | 'payjs_order_id' => @$_REQUEST['payjs_order_id'], 240 | 'attach' => @$_REQUEST['attach'], 241 | 'transaction_id' => @$_REQUEST['transaction_id'], 242 | 'openid' => @$_REQUEST['openid'], 243 | 'mchid' => @$_REQUEST['mchid'], 244 | 'sign' => @$_REQUEST['sign'], 245 | 'json_file' => json_encode($_REQUEST), 246 | ]; 247 | $this->db->query($this->db->insert('table.order_wxpay')->rows($arr)); 248 | } 249 | echo 'success'; 250 | } 251 | 252 | 253 | //使用二维码api 254 | public function getQRcodeURL($str) 255 | { 256 | $type = Helper::options()->plugin('Reward')->recode_type; 257 | $size = 300; 258 | switch ($type) { 259 | case 1: 260 | return 'http://bshare.optimix.asia/barCode?site=weixin&url=' . $str; 261 | break; 262 | case 2: 263 | return 'https://www.kuaizhan.com/common/encode-png?large=true&data=' . $str; 264 | break; 265 | case 3: 266 | return 'https://api.qrserver.com/v1/create-qr-code/?size=' . $size . 'x' . $size . '&data=' . $str; 267 | break; 268 | default: 269 | return 'http://bshare.optimix.asia/barCode?site=weixin&url=' . $str; 270 | break; 271 | } 272 | } 273 | 274 | //生成随机数 275 | public function genRandomChar($length = 8) 276 | { 277 | if (version_compare(PHP_VERSION, '7.0.0', '<')) { 278 | $random = random(pow(10, ($length - 1)), pow(10, $length) - 1); 279 | } else { 280 | $random = random_int(pow(10, ($length - 1)), pow(10, $length) - 1); 281 | } 282 | return date("YmdHis", time()) . $random; 283 | } 284 | 285 | } -------------------------------------------------------------------------------- /Reward/lib/AlipayF2F.php: -------------------------------------------------------------------------------- 1 | $val) { 18 | if (isset($key)) { 19 | $this->$key = $val; 20 | } 21 | } 22 | } 23 | 24 | /* 25 | * 扫码支付 26 | * 收银员通过收银台或商户后台调用支付宝接口,生成二维码后,展示给用户,由用户扫描二维码完成订单支付。 27 | */ 28 | public function qrPay($data = array()) 29 | { 30 | $request = [ 31 | 'type' => 'alipay.trade.precreate', 32 | 'reqs' => [ 33 | 'out_trade_no' => $data['outTradeNo'], //订单号,需要保证唯一 34 | 'total_amount' => $data['totalFee'], //单位 元 35 | 'subject' => $data['orderName'], //订单标题 36 | ] 37 | ]; 38 | $result = $this->curlPost($this->merge($request)); 39 | return json_decode($result, true); 40 | } 41 | 42 | /* 43 | * 条码支付 44 | * 收银员使用扫码设备读取用户手机支付宝“付款码”/声波获取设备(如麦克风)读取用户手机支付宝的声波信息后,将二维码或条码信息/声波信息通过本接口上送至支付宝发起支付。 45 | */ 46 | public function barPay($data = array()) 47 | { 48 | $request = [ 49 | 'type' => 'alipay.trade.pay', 50 | 'reqs' => [ 51 | 'out_trade_no' => $data['outTradeNo'], //商户订单号,需要保证不重复 52 | 'scene' => 'bar_code', //条码支付固定传入bar_code 53 | 'auth_code' => $data['authCode'], //用户付款码,25~30开头的长度为16~24位的数字,实际字符串长度以开发者获取的付款码长度为准 54 | 'total_amount' => $data['totalFee'], //商户订单号,需要保证不重复;单位 元 55 | 'subject' => $data['orderName'], //订单标题 56 | 'store_id' => 'DEDEMAO_001', //商户门店编号 57 | 'timeout_express' => '2m', //交易超时时间 58 | ] 59 | ]; 60 | $result = $this->curlPost($this->merge($request)); 61 | return json_decode($result, true); 62 | } 63 | 64 | /* 65 | * 查询订单 66 | * 该接口提供所有支付宝支付订单的查询,商户可以通过该接口主动查询订单状态,完成下一步的业务逻辑。 需要调用查询接口的情况: 当商户后台、网络、服务器等出现异常,商户系统最终未接收到支付通知; 调用支付接口后,返回系统错误或未知交易状态情况; 调用alipay.trade.pay,返回INPROCESS的状态; 调用alipay.trade.cancel之前,需确认支付状态; 67 | */ 68 | public function query($data = array()) 69 | { 70 | $request = [ 71 | 'type' => 'alipay.trade.query', 72 | 'reqs' => [ 73 | 'out_trade_no' => @$data['outTradeNo'], //商户订单号,需要保证不重复 74 | 'trade_no' => @$data['tradeNo'], //商户订单号,需要保证不重复 75 | ] 76 | ]; 77 | $result = $this->curlPost($this->merge($request)); 78 | return $result; 79 | } 80 | 81 | /* 82 | * 交易撤销 83 | * 支付交易返回失败或支付系统超时,调用该接口撤销交易。如果此订单用户支付失败,支付宝系统会将此订单关闭;如果用户支付成功,支付宝系统会将此订单资金退还给用户。 注意:只有发生支付系统超时或者支付结果未知时可调用撤销,其他正常支付的单如需实现相同功能请调用申请退款API。提交支付交易后调用【查询订单API】,没有明确的支付结果再调用【撤销订单API】。 84 | */ 85 | public function cancel($data = array()) 86 | { 87 | $request = [ 88 | 'type' => 'alipay.trade.cancel', 89 | 'reqs' => [ 90 | 'out_trade_no' => @$data['outTradeNo'], //商户订单号,需要保证不重复 91 | 'trade_no' => @$data['tradeNo'], //商户订单号,需要保证不重复 92 | ] 93 | ]; 94 | $result = $this->curlPost($this->merge($request)); 95 | return $result; 96 | } 97 | 98 | /* 99 | * 交易退款 100 | * 当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家,支付宝将在收到退款请求并且验证成功之后,按照退款规则将支付款按原路退到买家帐号上。 交易超过约定时间(签约时设置的可退款时间)的订单无法进行退款 支付宝退款支持单笔交易分多次退款,多次退款需要提交原支付订单的商户订单号和设置不同的退款单号。一笔退款失败后重新提交,要采用原来的退款单号。总退款金额不能超过用户实际支付金额 101 | */ 102 | public function refund($data = array()) 103 | { 104 | $request = [ 105 | 'type' => 'alipay.trade.refund', 106 | 'reqs' => [ 107 | 'out_trade_no' => @$data['outTradeNo'], //商户订单号,需要保证不重复 108 | 'trade_no' => @$data['tradeNo'], //支付宝订单号,不能和out_trade_no同时为空 109 | 'refund_amount' => $data['refundAmount'], //需要退款的金额,该金额不能大于订单金额,单位为元,支持两位小数 110 | 'refund_reason' => $data['refundReason'], //退款的原因说明 111 | ] 112 | ]; 113 | $result = $this->curlPost($this->merge($request)); 114 | return $result; 115 | } 116 | 117 | /* 118 | * 下载账单 119 | * 为方便商户快速查账,支持商户通过本接口获取商户离线账单下载地址 120 | */ 121 | public function billDownload($data = array()) 122 | { 123 | $request = [ 124 | 'type' => 'alipay.data.dataservice.bill.downloadurl.query', 125 | 'reqs' => [ 126 | 'bill_type' => $data['billType'], //账单类型,商户通过接口或商户经开放平台授权后其所属服务商通过接口可以获取以下账单类型:trade、signcustomer;trade指商户基于支付宝交易收单的业务账单;signcustomer是指基于商户支付宝余额收入及支出等资金变动的帐务账单; 127 | 'bill_date' => $data['billDate'], //账单时间:日账单格式为yyyy-MM-dd,月账单格式为yyyy-MM。 128 | ] 129 | ]; 130 | $result = $this->curlPost($this->merge($request, false)); 131 | return $result; 132 | } 133 | 134 | //合并请求参数 135 | public function merge($request, $notify = true) 136 | { 137 | $data = [ 138 | //公共参数 139 | 'app_id' => $this->appId, // 140 | 'method' => $request['type'], //接口名称 141 | 'format' => 'JSON', 142 | 'charset' => $this->charset, 143 | 'sign_type' => $this->sign_type, 144 | 'timestamp' => date('Y-m-d H:i:s'), 145 | 'version' => '1.0', 146 | 'notify_url' => $this->notifyUrl, 147 | 'biz_content' => json_encode($request['reqs']), 148 | ]; 149 | if (is_null($this->notifyUrl) || $notify = false) { 150 | unset($data['notify_url']); 151 | } 152 | $data['sign'] = $this->generateSign($data, $this->sign_type); 153 | return $data; 154 | } 155 | 156 | //验证签名 157 | public function rsaCheck($params) 158 | { 159 | $sign = $params['sign']; 160 | $signType = $params['sign_type']; 161 | unset($params['sign_type']); 162 | unset($params['sign']); 163 | return $this->verify($this->getSignContent($params), $sign, $signType); 164 | } 165 | 166 | function verify($data, $sign, $signType = 'RSA') 167 | { 168 | $pubKey = $this->alipayPublicKey; 169 | $res = "-----BEGIN PUBLIC KEY-----\n" . 170 | wordwrap($pubKey, 64, "\n", true) . 171 | "\n-----END PUBLIC KEY-----"; 172 | ($res) or die('支付宝RSA公钥错误。请检查公钥文件格式是否正确'); 173 | //调用openssl内置方法验签,返回bool值 174 | if ("RSA2" == $signType) { 175 | $result = (bool)openssl_verify($data, base64_decode($sign), $res, version_compare(PHP_VERSION, '5.4.0', '<') ? SHA256 : OPENSSL_ALGO_SHA256); 176 | } else { 177 | $result = (bool)openssl_verify($data, base64_decode($sign), $res); 178 | } 179 | return $result; 180 | } 181 | 182 | //生成签名 183 | public function generateSign($params, $signType = "RSA") 184 | { 185 | return $this->sign($this->getSignContent($params), $signType); 186 | } 187 | 188 | protected function sign($data, $signType = "RSA") 189 | { 190 | $priKey = $this->rsaPrivateKey; 191 | $res = "-----BEGIN RSA PRIVATE KEY-----\n" . 192 | wordwrap($priKey, 64, "\n", true) . 193 | "\n-----END RSA PRIVATE KEY-----"; 194 | ($res) or die('您使用的私钥格式错误,请检查RSA私钥配置'); 195 | if ("RSA2" == $signType) { 196 | openssl_sign($data, $sign, $res, version_compare(PHP_VERSION, '5.4.0', '<') ? SHA256 : OPENSSL_ALGO_SHA256); //OPENSSL_ALGO_SHA256是php5.4.8以上版本才支持 197 | } else { 198 | openssl_sign($data, $sign, $res); 199 | } 200 | $sign = base64_encode($sign); 201 | return $sign; 202 | } 203 | 204 | /** 205 | * 校验$value是否非空 206 | * if not set ,return true; 207 | * if is null , return true; 208 | **/ 209 | protected function checkEmpty($value) 210 | { 211 | if (!isset($value)) 212 | return true; 213 | if ($value === null) 214 | return true; 215 | if (trim($value) === "") 216 | return true; 217 | return false; 218 | } 219 | 220 | public function getSignContent($params) 221 | { 222 | ksort($params); 223 | $stringToBeSigned = ""; 224 | $i = 0; 225 | foreach ($params as $k => $v) { 226 | if (false === $this->checkEmpty($v) && "@" != substr($v, 0, 1)) { 227 | // 转换成目标字符集 228 | $v = $this->characet($v, $this->charset); 229 | if ($i == 0) { 230 | $stringToBeSigned .= "$k" . "=" . "$v"; 231 | } else { 232 | $stringToBeSigned .= "&" . "$k" . "=" . "$v"; 233 | } 234 | $i++; 235 | } 236 | } 237 | unset ($k, $v); 238 | return $stringToBeSigned; 239 | } 240 | 241 | /** 242 | * 转换字符集编码 243 | * @param $data 244 | * @param $targetCharset 245 | * @return string 246 | */ 247 | function characet($data, $targetCharset) 248 | { 249 | if (!empty($data)) { 250 | $fileType = $this->charset; 251 | if (strcasecmp($fileType, $targetCharset) != 0) { 252 | $data = mb_convert_encoding($data, $targetCharset, $fileType); 253 | //$data = iconv($fileType, $targetCharset.'//IGNORE', $data); 254 | } 255 | } 256 | return $data; 257 | } 258 | 259 | public function curlPost($postData = '', $options = array()) 260 | { 261 | if (is_array($postData)) { 262 | $postData = http_build_query($postData); 263 | } 264 | $ch = curl_init(); 265 | curl_setopt($ch, CURLOPT_URL, $this->requestUrl); 266 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 267 | curl_setopt($ch, CURLOPT_POST, 1); 268 | curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); 269 | curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL允许执行的最长秒数 270 | if (!empty($options)) { 271 | curl_setopt_array($ch, $options); 272 | } 273 | if (!$this->ssl) { 274 | //https请求 不验证证书和host 275 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 276 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); 277 | } 278 | $data = curl_exec($ch); 279 | curl_close($ch); 280 | return $data; 281 | } 282 | } --------------------------------------------------------------------------------