From be6b10df6e10f04a7199ed3e4f774ce99762f4e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=85=94=E5=A7=AC=E6=A1=91?= Date: Mon, 20 Apr 2020 13:55:14 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20=E9=BA=BB=E7=93=9C?= =?UTF-8?q?=E5=AE=9D=20=E6=94=AF=E4=BB=98=E6=B8=A0=E9=81=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Components/Helpers.php | 2 +- app/Http/Controllers/AdminController.php | 7 +- app/Http/Controllers/Gateway/AopF2F.php | 2 + app/Http/Controllers/Gateway/BitpayX.php | 148 ++++++++++++++++++ app/Http/Controllers/Gateway/CodePay.php | 2 +- app/Http/Controllers/PaymentController.php | 11 +- public/assets/images/bitcoin.svg | 78 +++++++++ resources/views/admin/system.blade.php | 32 ++++ resources/views/user/buy.blade.php | 6 +- .../views/user/components/purchase.blade.php | 3 + resources/views/user/services.blade.php | 8 +- sql/db.sql | 10 +- sql/mod/20200420.sql | 2 + 13 files changed, 296 insertions(+), 15 deletions(-) create mode 100644 app/Http/Controllers/Gateway/BitpayX.php create mode 100644 public/assets/images/bitcoin.svg create mode 100644 sql/mod/20200420.sql diff --git a/app/Components/Helpers.php b/app/Components/Helpers.php index 5c8a36b6..3ed11ca0 100644 --- a/app/Components/Helpers.php +++ b/app/Components/Helpers.php @@ -105,7 +105,7 @@ class Helpers $data[$vo->name] = $vo->value; } - $data['is_onlinePay'] = ($data['is_AliPay'] || $data['is_QQPay'] || $data['is_WeChatPay'])? : 0; + $data['is_onlinePay'] = ($data['is_AliPay'] || $data['is_QQPay'] || $data['is_WeChatPay'] || $data['is_otherPay'])? : 0; return $data; } diff --git a/app/Http/Controllers/AdminController.php b/app/Http/Controllers/AdminController.php index 6b7ad6be..6283c1ce 100644 --- a/app/Http/Controllers/AdminController.php +++ b/app/Http/Controllers/AdminController.php @@ -1991,7 +1991,7 @@ EOF; } // 支付设置判断 - if(in_array($name, ['is_AliPay', 'is_QQPay', 'is_WeChatPay']) && $value != ''){ + if(in_array($name, ['is_AliPay', 'is_QQPay', 'is_WeChatPay', 'is_otherPay']) && $value != ''){ switch($value){ case 'f2fpay': if(!self::$systemConfig['f2fpay_app_id'] || !self::$systemConfig['f2fpay_private_key'] || !self::$systemConfig['f2fpay_public_key']){ @@ -2008,6 +2008,11 @@ EOF; return Response::json(['status' => 'fail', 'message' => '请先设置【PayJs】必要参数']); } break; + case 'bitpayx': + if(!self::$systemConfig['bitpayx']){ + return Response::json(['status' => 'fail', 'message' => '请先设置【麻瓜宝】必要参数']); + } + break; default: return Response::json(['status' => 'fail', 'message' => '未知支付渠道']); break; diff --git a/app/Http/Controllers/Gateway/AopF2F.php b/app/Http/Controllers/Gateway/AopF2F.php index fbdf4749..e800911a 100644 --- a/app/Http/Controllers/Gateway/AopF2F.php +++ b/app/Http/Controllers/Gateway/AopF2F.php @@ -5,6 +5,7 @@ namespace App\Http\Controllers\Gateway; use App\Http\Models\Payment; use Auth; use Exception; +use Log; use Omnipay\Alipay\Responses\AopCompletePurchaseResponse; use Omnipay\Alipay\Responses\AopTradePreCreateResponse; use Omnipay\Omnipay; @@ -67,6 +68,7 @@ class AopF2F extends AbstractPayment exit('success'); } }catch(Exception $e){ + Log::error('支付宝当面付 '.$e); exit('fail'); } } diff --git a/app/Http/Controllers/Gateway/BitpayX.php b/app/Http/Controllers/Gateway/BitpayX.php new file mode 100644 index 00000000..3006bce2 --- /dev/null +++ b/app/Http/Controllers/Gateway/BitpayX.php @@ -0,0 +1,148 @@ +bitpayGatewayUri .= 'orders'; + curl_setopt($curl, CURLOPT_URL, $this->bitpayGatewayUri); + curl_setopt($curl, CURLOPT_POST, 1); + $data_string = json_encode($data); + curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string); + }elseif($type === 'query'){ + $this->bitpayGatewayUri .= 'orders/merchant_order_id/status?id='.$data['merchant_order_id']; + curl_setopt($curl, CURLOPT_URL, $this->bitpayGatewayUri); + curl_setopt($curl, CURLOPT_HTTPGET, 1); + } + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); + curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); + $data = curl_exec($curl); + curl_close($curl); + + return $data; + } + + /** + * @param Request $request + * + * @return mixed + */ + public function purchase(Request $request) + { + $payment = new Payment(); + $payment->sn = self::generateGuid(); + $payment->user_id = Auth::user()->id; + $payment->oid = $request->input('oid'); + $payment->amount = $request->input('amount'); + $payment->save(); + + $data = [ + 'merchant_order_id' => $payment->sn, + 'price_amount' => (float)$request->input('amount'), + 'price_currency' => 'CNY', + 'pay_currency' => $request->input('type') == 1? 'ALIPAY' : 'WECHAT', + 'title' => '支付单号:'.$payment->sn, + 'description' => parent::$systemConfig['subject_name']? : parent::$systemConfig['website_name'], + 'callback_url' => (parent::$systemConfig['website_callback_url']? : parent::$systemConfig['website_url']).'/payment/notify', + 'success_url' => parent::$systemConfig['website_url'].'/invoices', + 'cancel_url' => parent::$systemConfig['website_url'], + 'token' => $this->sign($this->prepareSignId($payment->sn)), + + ]; + + $result = json_decode($this->mprequest($data), TRUE); + + + if($result['status'] === 200 || $result['status'] === 201){ + $result['payment_url'] .= '&lang=zh'; + + return Response::json(['status' => 'success', 'url' => $result['payment_url'] .= '&lang=zh', 'message' => '创建订单成功!']); + } + + return Response::json(['status' => 'fail', 'data' => $result, 'message' => '创建订单失败!']); + } + + public function sign($data) + { + return strtolower(md5(md5($data).parent::$systemConfig['bitpay_secret'])); + } + + public function prepareSignId($tradeno) + { + $data_sign = [ + 'merchant_order_id' => $tradeno, + 'secret' => parent::$systemConfig['bitpay_secret'], + 'type' => 'FIAT', + ]; + ksort($data_sign); + + return http_build_query($data_sign); + } + + public function notify(Request $request) + { + $inputString = file_get_contents('php://input', 'r'); + $inputStripped = str_replace(["\r", "\n", "\t", "\v"], '', $inputString); + $inputJSON = json_decode($inputStripped, TRUE); //convert JSON into array + $data = []; + if($inputJSON !== NULL){ + $data = [ + 'status' => $inputJSON['status'], + 'order_id' => $inputJSON['order_id'], + 'merchant_order_id' => $inputJSON['merchant_order_id'], + 'price_amount' => $inputJSON['price_amount'], + 'price_currency' => $inputJSON['price_currency'], + 'created_at_t' => $inputJSON['created_at_t'], + ]; + } + // 准备待签名数据 + $str_to_sign = $this->prepareSignId($inputJSON['merchant_order_id']); + $resultVerify = $this->verify($str_to_sign, $inputJSON['token']); + $isPaid = $data !== NULL && $data['status'] !== NULL && $data['status'] === 'PAID'; + + if($resultVerify && $isPaid){ + $this->postPayment($inputJSON['merchant_order_id'], 'BitPayX'); + $return = []; + $return['status'] = 200; + echo json_encode($return); + }else{ + $return = []; + $return['status'] = 400; + echo json_encode($return); + } + exit(); + } + + public function verify($data, $signature) + { + $mySign = $this->sign($data); + + return $mySign === $signature; + } + + public function getReturnHTML(Request $request) + { + // TODO: Implement getReturnHTML() method. + } + + public function getPurchaseHTML() + { + // TODO: Implement getPurchaseHTML() method. + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Gateway/CodePay.php b/app/Http/Controllers/Gateway/CodePay.php index 0914a08b..0e60e61d 100644 --- a/app/Http/Controllers/Gateway/CodePay.php +++ b/app/Http/Controllers/Gateway/CodePay.php @@ -21,7 +21,7 @@ class CodePay extends AbstractPayment $data = [ 'id' => parent::$systemConfig['codepay_id'], 'pay_id' => $payment->sn, - 'type' => $request->input('method'),//1支付宝支付 2QQ钱包 3微信支付 + 'type' => $request->input('type'),//1支付宝支付 2QQ钱包 3微信支付 'price' => $payment->amount, 'page' => 4, 'outTime' => 900, diff --git a/app/Http/Controllers/PaymentController.php b/app/Http/Controllers/PaymentController.php index 5f08f07c..86b88559 100644 --- a/app/Http/Controllers/PaymentController.php +++ b/app/Http/Controllers/PaymentController.php @@ -4,6 +4,7 @@ namespace App\Http\Controllers; use App\Components\Helpers; use App\Http\Controllers\Gateway\AopF2F; +use App\Http\Controllers\Gateway\BitpayX; use App\Http\Controllers\Gateway\CodePay; use App\Http\Controllers\Gateway\PayJs; use App\Http\Models\Coupon; @@ -36,6 +37,8 @@ class PaymentController extends Controller return new Codepay(); case 'payjs': return new PayJs(); + case 'bitpayx': + return new BitpayX(); default: return NULL; } @@ -69,7 +72,7 @@ class PaymentController extends Controller } // 创建支付订单 - public function purchase(Request $request) + public static function purchase(Request $request) { $goods_id = $request->input('goods_id'); $coupon_sn = $request->input('coupon_sn'); @@ -173,16 +176,16 @@ class PaymentController extends Controller User::query()->where('id', Auth::user()->id)->decrement('balance', $amount*100); // 记录余额操作日志 - $this->addUserBalanceLog(Auth::user()->id, $order->oid, Auth::user()->balance, Auth::user()->balance-$amount, -1*$amount, '购买商品:'.$goods->name); + (new Controller)->addUserBalanceLog(Auth::user()->id, $order->oid, Auth::user()->balance, Auth::user()->balance-$amount, -1*$amount, '购买商品:'.$goods->name); $order = Order::query()->where('oid', $orderSn)->first(); $order->status = 2; $order->save(); User::query()->where('id', $order->user_id)->increment('balance', $order->amount*100); // 余额变动记录日志 - $this->addUserBalanceLog($order->user_id, $order->oid, $order->user->balance, $order->user->balance+$order->amount, $order->amount, '用户在线充值'); + (new Controller)->addUserBalanceLog($order->user_id, $order->oid, $order->user->balance, $order->user->balance+$order->amount, $order->amount, '用户在线充值'); }else{ - $request->merge(['oid' => $order->oid, 'amount' => $amount]); + $request->merge(['oid' => $order->oid, 'amount' => $amount, 'type' => $request->input('pay_type')]); return self::getClient()->purchase($request); } diff --git a/public/assets/images/bitcoin.svg b/public/assets/images/bitcoin.svg new file mode 100644 index 00000000..11af6f7a --- /dev/null +++ b/public/assets/images/bitcoin.svg @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/views/admin/system.blade.php b/resources/views/admin/system.blade.php index 2036d014..8a70c0f7 100644 --- a/resources/views/admin/system.blade.php +++ b/resources/views/admin/system.blade.php @@ -1017,6 +1017,15 @@ +
+
+ + +
+
@@ -1151,6 +1160,28 @@
+
+
+
+ +
+ 请到 麻瓜宝 MugglePay 申请账号 +
+
+
+
+
+ +
+
+ + +
+
+ 在本页中获取后台服务器的秘钥 +
+
+
@@ -1183,6 +1214,7 @@ $('#is_AliPay').selectpicker('val', '{{$is_AliPay}}'); $('#is_QQPay').selectpicker('val', '{{$is_QQPay}}'); $('#is_WeChatPay').selectpicker('val', '{{$is_WeChatPay}}'); + $('#is_otherPay').selectpicker('val', '{{$is_otherPay}}'); }); // 系统设置更新 diff --git a/resources/views/user/buy.blade.php b/resources/views/user/buy.blade.php index ac06262a..7e0c7e36 100644 --- a/resources/views/user/buy.blade.php +++ b/resources/views/user/buy.blade.php @@ -157,7 +157,11 @@ swal.fire({title: ret.message, type: 'success', timer: 1000, showConfirmButton: false}) .then(() => window.location.href = '/invoices') } - window.location.href = '/payment/' + ret.data; + if (ret.data) { + window.location.href = '/payment/' + ret.data; + } else if (ret.url) { + window.location.href = ret.url; + } } else if (ret.status === 'info') { swal.fire({title: ret.title, text: ret.message, type: 'question'}); } else { diff --git a/resources/views/user/components/purchase.blade.php b/resources/views/user/components/purchase.blade.php index e5fac959..f39c1063 100644 --- a/resources/views/user/components/purchase.blade.php +++ b/resources/views/user/components/purchase.blade.php @@ -6,4 +6,7 @@ @endif @if(\App\Components\Helpers::systemConfig()['is_WeChatPay']) ' +@endif +@if(\App\Components\Helpers::systemConfig()['is_otherPay']) + ' @endif \ No newline at end of file diff --git a/resources/views/user/services.blade.php b/resources/views/user/services.blade.php index 77073512..f980faec 100644 --- a/resources/views/user/services.blade.php +++ b/resources/views/user/services.blade.php @@ -243,9 +243,13 @@ success: function (ret) { if (ret.status === 'fail') { return false; - }else{ + } else { $("#charge_msg").show().html(ret.message); - window.location.href = '/payment/' + ret.data; + if (ret.data) { + window.location.href = '/payment/' + ret.data; + } else if (ret.url) { + window.location.href = ret.url; + } } }, error: function () { diff --git a/sql/db.sql b/sql/db.sql index 8b71d4bb..31f04f05 100644 --- a/sql/db.sql +++ b/sql/db.sql @@ -372,15 +372,15 @@ insert into `config` VALUES ('74', 'node_daily_report', 0); insert into `config` VALUES ('75', 'mix_subscribe', 0); insert into `config` VALUES ('76', 'rand_subscribe', 0); insert into `config` VALUES ('77', 'is_custom_subscribe', 0); -insert into `config` VALUES ('78', 'is_AliPay', 0); -insert into `config` VALUES ('79', 'is_QQ', 0); -insert into `config` VALUES ('80', 'is_WeChat', 0); -insert into `config` VALUES ('81', 'alipay_key', ''); +insert into `config` VALUES ('78', 'is_AliPay', ''); +insert into `config` VALUES ('79', 'is_QQ', ''); +insert into `config` VALUES ('80', 'is_WeChat', ''); +insert into `config` VALUES ('81', 'is_otherPay', ''); insert into `config` VALUES ('82', 'alipay_private_key', ''); insert into `config` VALUES ('83', 'alipay_public_key', ''); insert into `config` VALUES ('84', 'alipay_transport', 'http'); insert into `config` VALUES ('85', 'alipay_currency', 'USD'); -insert into `config` VALUES ('86', 'is_f2fpay', 0); +insert into `config` VALUES ('86', 'bitpay_secret', ''); insert into `config` VALUES ('87', 'f2fpay_app_id', ''); insert into `config` VALUES ('88', 'f2fpay_private_key', ''); insert into `config` VALUES ('89', 'f2fpay_public_key', ''); diff --git a/sql/mod/20200420.sql b/sql/mod/20200420.sql new file mode 100644 index 00000000..5af21d53 --- /dev/null +++ b/sql/mod/20200420.sql @@ -0,0 +1,2 @@ +update `config` SET `name` = 'is_otherPay', `value` = '' where `config`.`id` = 81; +update `config` SET `name` = 'bitpay_secret', `value` = '' where `config`.`id` = 86; \ No newline at end of file