Browse Source

添加 PayBeaver 支付方式 (#112)

Co-authored-by: tossakankan <tossakankan>
tossakankan 4 years ago
parent
commit
9d642a2fba

+ 5 - 0
app/Http/Controllers/Admin/SystemController.php

@@ -107,6 +107,11 @@ class SystemController extends Controller
                         return Response::json(['status' => 'fail', 'message' => '请先设置【Stripe】必要参数']);
                     }
                     break;
+                case 'paybeaver':
+                    if (! sysConfig('paybeaver_app_id') || ! sysConfig('paybeaver_app_secret')) {
+                        return Response::json(['status' => 'fail', 'message' => '请先设置【PayBeaver】必要参数']);
+                    }
+                    break;
                 default:
                     return Response::json(['status' => 'fail', 'message' => '未知支付渠道']);
             }

+ 110 - 0
app/Http/Controllers/Gateway/PayBeaver.php

@@ -0,0 +1,110 @@
+<?php
+
+/**
+ * Created by PayBeaver <merchant.paybeaver.com>
+ * Version: 2020-12-06
+ */
+
+namespace App\Http\Controllers\Gateway;
+
+use App\Models\Payment;
+use Log;
+use Auth;
+use Http;
+use Illuminate\Http\JsonResponse;
+use Illuminate\Http\Request;
+use Response;
+
+class PayBeaver extends AbstractPayment
+{
+    private $appId;
+    private $appSecret;
+    private $url = 'https://api.paybeaver.com/api/v1/developer';
+
+    public function __construct($appId, $appSecret)
+    {
+        $this->appId = $appId;
+        $this->appSecret = $appSecret;
+    }
+
+    public function purchase($request): JsonResponse
+    {
+        $payment = $this->creatNewPayment(Auth::id(), $request->input('id'), $request->input('amount'));
+
+        $result = $this->createOrder([
+            'app_id' => $this->appId,
+            'merchant_order_id' => $payment->trade_no,
+            'price_amount' => $payment->amount * 100,
+            'notify_url' => route('payment.notify', ['method' => 'paybeaver']),
+            'return_url' => route('invoice'),
+        ]);
+
+        if (isset($result['message'])) {
+            Log::warning('创建订单错误:'.$result['message']);
+            return Response::json(['status' => 'fail', 'message' => '创建订单失败:'.$result['message']]);
+        }
+
+        if (!isset($result['data']) || !isset($result['data']['pay_url'])) {
+            Log::warning('创建订单错误:未知错误');
+            return Response::json(['status' => 'fail', 'message' => '创建订单失败:未知错误']);
+        }
+
+        $payment->update(['url' => $result['data']['pay_url']]);
+        return Response::json(['status' => 'success', 'url' => $result['data']['pay_url'], 'message' => '创建订单成功!']);
+    }
+
+    public function notify($request): void
+    {
+        if (!$this->paybeaverVerify($request->post())) {
+            exit(json_encode(['status' => 400]));
+        }
+
+        $tradeNo = $request->input(['merchant_order_id']);
+        $payment = Payment::whereTradeNo($tradeNo)->first();
+        if ($payment) {
+            $ret = $payment->order->update(['status' => 2]);
+            if ($ret) {
+                exit(json_encode(['status' => 200]));
+            }
+        }
+
+        exit(json_encode(['status' => 500]));
+    }
+
+    protected function createOrder($params)
+    {
+        $params['sign'] = $this->sign($params);
+        return $this->request('/orders', $params);
+    }
+
+    protected function paybeaverVerify($params)
+    {
+        // Log::warning('got sign ' . $params['sign']);
+        // Log::warning('calc sign ' . $this->sign($params));
+        return hash_equals($params['sign'], $this->sign($params));
+    }
+
+    protected function sign($params)
+    {
+        // Log::warning('paybeaver app secret: ' . $this->appSecret);
+        // Log::warning('query: ' . http_build_query($params) . $this->appSecret);
+        if (isset($params['sign'])) unset($params['sign']);
+        ksort($params);
+        reset($params);
+        return strtolower(md5(http_build_query($params) . $this->appSecret));
+    }
+
+    protected function request($path, $data) {
+        $curl = curl_init();
+        curl_setopt($curl, CURLOPT_URL, "{$this->url}{$path}");
+        curl_setopt($curl, CURLOPT_POST, 1);
+        curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
+        curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
+        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 json_decode($data, true);
+    }
+}

+ 3 - 0
app/Http/Controllers/PaymentController.php

@@ -11,6 +11,7 @@ use App\Http\Controllers\Gateway\Local;
 use App\Http\Controllers\Gateway\PayJs;
 use App\Http\Controllers\Gateway\PayPal;
 use App\Http\Controllers\Gateway\Stripe;
+use App\Http\Controllers\Gateway\PayBeaver;
 use App\Models\Coupon;
 use App\Models\Goods;
 use App\Models\Order;
@@ -60,6 +61,8 @@ class PaymentController extends Controller
                 return new EPay();
             case 'stripe':
                 return new Stripe();
+            case 'paybeaver':
+                return new PayBeaver(sysConfig('paybeaver_app_id'), sysConfig('paybeaver_app_secret'));
             default:
                 Log::warning('未知支付:'.self::$method);
 

+ 9 - 0
app/Models/Order.php

@@ -168,6 +168,9 @@ class Order extends Model
             case 6:
                 $pay_type_label = 'Stripe';
                 break;
+            case 7:
+                $pay_type_label = 'PayBeaver';
+                break;
             default:
                 $pay_type_label = '';
         }
@@ -196,6 +199,9 @@ class Order extends Model
             case 6:
                 $pay_type_icon = $base_path.'stripe.png';
                 break;
+            case 7:
+                $pay_type_icon = $base_path.'coin.png';
+                break;
             case 0:
             case 4:
             default:
@@ -233,6 +239,9 @@ class Order extends Model
             case 'stripe':
                 $pay_way_label = 'Stripe';
                 break;
+            case 'paybeaver':
+                $pay_way_label = '海狸支付';
+                break;
             default:
                 $pay_way_label = '未知';
         }

+ 34 - 0
database/migrations/2021_01_04_172833_add-paybeaver-payment.php

@@ -0,0 +1,34 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use App\Models\Config;
+
+class AddPaybeaverPayment extends Migration
+{
+    protected $configs = [
+        'paybeaver_app_id',
+        'paybeaver_app_secret',
+    ];
+
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        foreach ($this->configs as $config) {
+            Config::insert(['name' => $config]);
+        }
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Config::destroy($this->configs);
+    }
+}

+ 41 - 0
resources/views/admin/config/system.blade.php

@@ -1215,6 +1215,7 @@
                                                 <option value="f2fpay">F2F</option>
                                                 <option value="codepay">码支付</option>
                                                 <option value="epay">易支付</option>
+                                                <option value="paybeaver">海狸支付</option>
                                             </select>
                                         </div>
                                         <div class="form-group col-lg-6">
@@ -1234,6 +1235,7 @@
                                                 <option value="codepay">码支付</option>
                                                 <option value="payjs">PayJS</option>
                                                 <option value="epay">易支付</option>
+                                                <option value="paybeaver">海狸支付</option>
                                             </select>
                                         </div>
                                         <div class="form-group col-lg-6">
@@ -1567,6 +1569,41 @@
                                         </div>
                                     </div>
                                 </div>
+                                <div class="tab-pane" id="paybeaver" role="tabpanel">
+                                    <div class="row">
+                                        <div class="form-group col-lg-6 d-flex">
+                                            <label class="col-md-3 col-form-label">海狸支付 PayBeaver</label>
+                                            <div class="col-md-7">
+                                                请到<a href="https://merchant.paybeaver.com/?aff_code=" target="_blank">海狸支付 PayBeaver</a>申请账号
+                                            </div>
+                                        </div>
+                                        <div class="form-group col-lg-6 d-flex"></div>
+                                        <div class="form-group col-lg-6 d-flex">
+                                            <label class="col-md-3 col-form-label" for="paybeaver_app_id">App ID</label>
+                                            <div class="col-md-7">
+                                                <div class="input-group">
+                                                    <input type="text" class="form-control" id="paybeaver_app_id" value="{{$paybeaver_app_id}}"/>
+                                                    <span class="input-group-append">
+                                                            <button class="btn btn-primary" type="button" onclick="update('paybeaver_app_id')">修改</button>
+                                                        </span>
+                                                </div>
+                                                <span class="text-help"><a href="https://merchant.paybeaver.com/" target="_blank">商户中心</a> -&gt; 开发者 -&gt; App ID</span>
+                                            </div>
+                                        </div>
+                                        <div class="form-group col-lg-6 d-flex">
+                                            <label class="col-md-3 col-form-label" for="paybeaver_app_secret">App Secret</label>
+                                            <div class="col-md-7">
+                                                <div class="input-group">
+                                                    <input type="text" class="form-control" id="paybeaver_app_secret" value="{{$paybeaver_app_secret}}"/>
+                                                    <span class="input-group-append">
+                                                            <button class="btn btn-primary" type="button" onclick="update('paybeaver_app_secret')">修改</button>
+                                                        </span>
+                                                </div>
+                                                <span class="text-help"><a href="https://merchant.paybeaver.com/" target="_blank">商户中心</a> -&gt; 开发者 -&gt; App Secret</span>
+                                            </div>
+                                        </div>
+                                    </div>
+                                </div>
                             </div>
                             <ul class="nav nav-tabs nav-tabs-bottom nav-tabs-line dropup" role="tablist">
                                 <li class="nav-item">
@@ -1593,6 +1630,9 @@
                                 <li class="nav-item">
                                     <a class="nav-link" data-toggle="tab" href="#Stripe" aria-controls="Stripe" role="tab">Stripe</a>
                                 </li>
+                                <li class="nav-item">
+                                    <a class="nav-link" data-toggle="tab" href="#paybeaver" aria-controls="PayBeaver" role="tab">PayBeaver</a>
+                                </li>
                                 <li class="nav-item dropdown" style="display: none;">
                                     <a class="dropdown-toggle nav-link" data-toggle="dropdown" href="#" aria-expanded="false" aria-haspopup="true">菜单</a>
                                     <div class="dropdown-menu" role="menu">
@@ -1604,6 +1644,7 @@
                                         <a class="dropdown-item" data-toggle="tab" href="#MugglePay" aria-controls="MugglePay" role="tab">MugglePay</a>
                                         <a class="dropdown-item" data-toggle="tab" href="#PayPal" aria-controls="PayPal" role="tab">PayPal</a>
                                         <a class="dropdown-item" data-toggle="tab" href="#Stripe" aria-controls="Stripe" role="tab">Stripe</a>
+                                        <a class="dropdown-item" data-toggle="tab" href="#paybeaver" aria-controls="PayBeaver" role="tab">PayBeaver</a>
                                     </div>
                                 </li>
                             </ul>