first commit

This commit is contained in:
2026-04-15 20:16:52 +08:00
commit 8f45044411
1172 changed files with 329978 additions and 0 deletions
+54
View File
@@ -0,0 +1,54 @@
<?php
/**
* The file was created by Assimon.
*
* @author assimon<ashang@utf8.hk>
* @copyright assimon<ashang@utf8.hk>
* @link http://utf8.hk/
*/
namespace App\Http\Controllers;
class BaseController extends Controller
{
/**
* 渲染模板
*
* @param string $tpl 模板名称
* @param array $data 数据
* @param array $pageTitle 页面标题
*
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
*
* @author assimon<ashang@utf8.hk>
* @copyright assimon<ashang@utf8.hk>
* @link http://utf8.hk/
*/
protected function render(string $tpl, $data = [], string $pageTitle = '')
{
$layout = dujiaoka_config_get('template', 'unicorn');
$tplPath = $layout . '/' .$tpl;
return view($tplPath, $data)->with('page_title', $pageTitle);
}
/**
* 错误提示
*
* @param string $content 提示内容
* @param string $jumpUri 跳转url
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
*
* @author assimon<ashang@utf8.hk>
* @copyright assimon<ashang@utf8.hk>
* @link http://utf8.hk/
*/
protected function err(string $content, $jumpUri = '')
{
$layout = dujiaoka_config_get('template', 'unicorn');
$tplPath = $layout . '/errors/error';
return view($tplPath, ['title' => __('dujiaoka.error_title'), 'content' => $content, 'url' => $jumpUri])
->with('page_title', __('dujiaoka.error_title'));
}
}
+13
View File
@@ -0,0 +1,13 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}
@@ -0,0 +1,189 @@
<?php
namespace App\Http\Controllers\Home;
use App\Exceptions\RuleValidationException;
use App\Http\Controllers\BaseController;
use App\Models\Pay;
use Germey\Geetest\Geetest;
use Illuminate\Database\DatabaseServiceProvider;
use Illuminate\Database\QueryException;
use Illuminate\Encryption\Encrypter;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;
class HomeController extends BaseController
{
/**
* 商品服务层.
* @var \App\Service\PayService
*/
private $goodsService;
/**
* 支付服务层
* @var \App\Service\PayService
*/
private $payService;
public function __construct()
{
$this->goodsService = app('Service\GoodsService');
$this->payService = app('Service\PayService');
}
/**
* 首页.
*
* @param Request $request
*
* @author assimon<ashang@utf8.hk>
* @copyright assimon<ashang@utf8.hk>
* @link http://utf8.hk/
*/
public function index(Request $request)
{
$goods = $this->goodsService->withGroup();
return $this->render('static_pages/home', ['data' => $goods], __('dujiaoka.page-title.home'));
}
/**
* 商品详情
*
* @param int $id
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
*
* @author assimon<ashang@utf8.hk>
* @copyright assimon<ashang@utf8.hk>
* @link http://utf8.hk/
*/
public function buy(int $id)
{
try {
$goods = $this->goodsService->detail($id);
$this->goodsService->validatorGoodsStatus($goods);
// 有没有优惠码可以展示
if (count($goods->coupon)) {
$goods->open_coupon = 1;
}
$formatGoods = $this->goodsService->format($goods);
// 加载支付方式.
$client = Pay::PAY_CLIENT_PC;
if (app('Jenssegers\Agent')->isMobile()) {
$client = Pay::PAY_CLIENT_MOBILE;
}
$formatGoods->payways = $this->payService->pays($client);
return $this->render('static_pages/buy', $formatGoods, $formatGoods->gd_name);
} catch (RuleValidationException $ruleValidationException) {
return $this->err($ruleValidationException->getMessage());
}
}
/**
* 极验行为验证
*
* @param Request $request
*
* @author assimon<ashang@utf8.hk>
* @copyright assimon<ashang@utf8.hk>
* @link http://utf8.hk/
*/
public function geetest(Request $request)
{
$data = [
'user_id' => @Auth::user()?@Auth::user()->id:'UnLoginUser',
'client_type' => 'web',
'ip_address' => \Illuminate\Support\Facades\Request::ip()
];
$status = Geetest::preProcess($data);
session()->put('gtserver', $status);
session()->put('user_id', $data['user_id']);
return Geetest::getResponseStr();
}
/**
* 安装页面
*
* @param Request $request
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
*
* @author assimon<ashang@utf8.hk>
* @copyright assimon<ashang@utf8.hk>
* @link http://utf8.hk/
*/
public function install(Request $request)
{
return view('common/install');
}
/**
* 执行安装
*
* @param Request $request
*
* @author assimon<ashang@utf8.hk>
* @copyright assimon<ashang@utf8.hk>
* @link http://utf8.hk/
*/
public function doInstall(Request $request)
{
try {
$dbConfig = config('database');
$mysqlDB = [
'host' => $request->input('db_host'),
'port' => $request->input('db_port'),
'database' => $request->input('db_database'),
'username' => $request->input('db_username'),
'password' => $request->input('db_password'),
];
$dbConfig['connections']['mysql'] = array_merge($dbConfig['connections']['mysql'], $mysqlDB);
// Redis
$redisDB = [
'host' => $request->input('redis_host'),
'password' => $request->input('redis_password', 'null'),
'port' => $request->input('redis_port'),
];
$dbConfig['redis']['default'] = array_merge($dbConfig['redis']['default'], $redisDB);
config(['database' => $dbConfig]);
DB::purge();
// db测试
DB::connection()->select('select 1 limit 1');
// redis测试
Redis::set('dujiaoka_com', 'ok');
Redis::get('dujiaoka_com');
// 获得文件模板
$envExamplePath = base_path() . DIRECTORY_SEPARATOR . '.env.example';
$envPath = base_path() . DIRECTORY_SEPARATOR . '.env';
$installLock = base_path() . DIRECTORY_SEPARATOR . 'install.lock';
$installSql = database_path() . DIRECTORY_SEPARATOR . 'sql' . DIRECTORY_SEPARATOR . 'install.sql';
$envTemp = file_get_contents($envExamplePath);
$postData = $request->all();
// 临时写入key
$postData['app_key'] = 'base64:' . base64_encode(
Encrypter::generateKey(config('app.cipher'))
);
foreach ($postData as $key => $item) {
$envTemp = str_replace('{' . $key . '}', $item, $envTemp);
}
// 写入配置
file_put_contents($envPath, $envTemp);
// 导入sql
DB::unprepared(file_get_contents($installSql));
// 写入安装锁
file_put_contents($installLock, 'install ok');
return 'success';
} catch (\RedisException $exception) {
return 'Redis配置错误 :' . $exception->getMessage();
} catch (QueryException $exception) {
return '数据库配置错误 :' . $exception->getMessage();
} catch (\Exception $exception) {
return $exception->getMessage();
}
}
}
@@ -0,0 +1,259 @@
<?php
namespace App\Http\Controllers\Home;
use App\Exceptions\RuleValidationException;
use App\Http\Controllers\BaseController;
use App\Models\Order;
use App\Service\OrderProcessService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cookie;
use Illuminate\Support\Facades\DB;
/**
* 订单控制器
*
* Class OrderController
* @package App\Http\Controllers\Home
* @author: Assimon
* @email: Ashang@utf8.hk
* @blog: https://utf8.hk
* Date: 2021/5/30
*/
class OrderController extends BaseController
{
/**
* 订单服务层
* @var \App\Service\OrderService
*/
private $orderService;
/**
* 订单处理层.
* @var OrderProcessService
*/
private $orderProcessService;
public function __construct()
{
$this->orderService = app('Service\OrderService');
$this->orderProcessService = app('Service\OrderProcessService');
}
/**
* 创建订单
*
* @param Request $request
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
* @throws \Illuminate\Validation\ValidationException
*
* @author assimon<ashang@utf8.hk>
* @copyright assimon<ashang@utf8.hk>
* @link http://utf8.hk/
*/
public function createOrder(Request $request)
{
DB::beginTransaction();
try {
$this->orderService->validatorCreateOrder($request);
$goods = $this->orderService->validatorGoods($request);
$this->orderService->validatorLoopCarmis($request);
// 设置商品
$this->orderProcessService->setGoods($goods);
// 优惠码
$coupon = $this->orderService->validatorCoupon($request);
// 设置优惠码
$this->orderProcessService->setCoupon($coupon);
$otherIpt = $this->orderService->validatorChargeInput($goods, $request);
$this->orderProcessService->setOtherIpt($otherIpt);
// 数量
$this->orderProcessService->setBuyAmount($request->input('by_amount'));
// 支付方式
$this->orderProcessService->setPayID($request->input('payway'));
// 下单邮箱
$this->orderProcessService->setEmail($request->input('email'));
// ip地址
$this->orderProcessService->setBuyIP($request->getClientIp());
// 查询密码
$this->orderProcessService->setSearchPwd($request->input('search_pwd', ''));
// 创建订单
$order = $this->orderProcessService->createOrder();
DB::commit();
// 设置订单cookie
$this->queueCookie($order->order_sn);
return redirect(url('/bill', ['orderSN' => $order->order_sn]));
} catch (RuleValidationException $exception) {
DB::rollBack();
return $this->err($exception->getMessage());
}
}
/**
* 设置订单cookie.
* @param string $orderSN 订单号.
*/
private function queueCookie(string $orderSN) : void
{
// 设置订单cookie
$cookies = Cookie::get('dujiaoka_orders');
if (empty($cookies)) {
Cookie::queue('dujiaoka_orders', json_encode([$orderSN]));
} else {
$cookies = json_decode($cookies, true);
array_push($cookies, $orderSN);
Cookie::queue('dujiaoka_orders', json_encode($cookies));
}
}
/**
* 结账
*
* @param string $orderSN
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
*
* @author assimon<ashang@utf8.hk>
* @copyright assimon<ashang@utf8.hk>
* @link http://utf8.hk/
*/
public function bill(string $orderSN)
{
$order = $this->orderService->detailOrderSN($orderSN);
if (empty($order)) {
return $this->err(__('dujiaoka.prompt.order_does_not_exist'));
}
if ($order->status == Order::STATUS_EXPIRED) {
return $this->err(__('dujiaoka.prompt.order_is_expired'));
}
return $this->render('static_pages/bill', $order, __('dujiaoka.page-title.bill'));
}
/**
* 订单状态监测
*
* @param string $orderSN 订单号
* @return \Illuminate\Http\JsonResponse
*
* @author assimon<ashang@utf8.hk>
* @copyright assimon<ashang@utf8.hk>
* @link http://utf8.hk/
*/
public function checkOrderStatus(string $orderSN)
{
$order = $this->orderService->detailOrderSN($orderSN);
// 订单不存在或者已经过期
if (!$order || $order->status == Order::STATUS_EXPIRED) {
return response()->json(['msg' => 'expired', 'code' => 400001]);
}
// 订单已经支付
if ($order->status == Order::STATUS_WAIT_PAY) {
return response()->json(['msg' => 'wait....', 'code' => 400000]);
}
// 成功
if ($order->status > Order::STATUS_WAIT_PAY) {
return response()->json(['msg' => 'success', 'code' => 200]);
}
}
/**
* 通过订单号展示订单详情
*
* @param string $orderSN 订单号.
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
*
* @author assimon<ashang@utf8.hk>
* @copyright assimon<ashang@utf8.hk>
* @link http://utf8.hk/
*/
public function detailOrderSN(string $orderSN)
{
$order = $this->orderService->detailOrderSN($orderSN);
// 订单不存在或者已经过期
if (!$order) {
return $this->err(__('dujiaoka.prompt.order_does_not_exist'));
}
return $this->render('static_pages/orderinfo', ['orders' => [$order]], __('dujiaoka.page-title.order-detail'));
}
/**
* 订单号查询
*
* @param Request $request
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
*
* @author assimon<ashang@utf8.hk>
* @copyright assimon<ashang@utf8.hk>
* @link http://utf8.hk/
*/
public function searchOrderBySN(Request $request)
{
return $this->detailOrderSN($request->input('order_sn'));
}
/**
* 通过邮箱查询
*
* @param Request $request
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
*
* @author assimon<ashang@utf8.hk>
* @copyright assimon<ashang@utf8.hk>
* @link http://utf8.hk/
*/
public function searchOrderByEmail(Request $request)
{
if (
!$request->has('email') ||
(
dujiaoka_config_get('is_open_search_pwd', \App\Models\BaseModel::STATUS_CLOSE) == \App\Models\BaseModel::STATUS_OPEN &&
!$request->has('search_pwd')
)
) {
return $this->err(__('dujiaoka.prompt.server_illegal_request'));
}
$orders = $this->orderService->withEmailAndPassword($request->input('email'), $request->input('search_pwd',''));
if (!$orders) {
return $this->err(__('dujiaoka.prompt.no_related_order_found'));
}
return $this->render('static_pages/orderinfo', ['orders' => $orders], __('dujiaoka.page-title.order-detail'));
}
/**
* 通过浏览器缓存查询
* @param Request $request
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
*
* @author assimon<ashang@utf8.hk>
* @copyright assimon<ashang@utf8.hk>
* @link http://utf8.hk/
*/
public function searchOrderByBrowser(Request $request)
{
$cookies = Cookie::get('dujiaoka_orders');
if (empty($cookies)) {
return $this->err(__('dujiaoka.prompt.no_related_order_found_for_cache'));
}
$orderSNS = json_decode($cookies, true);
$orders = $this->orderService->byOrderSNS($orderSNS);
return $this->render('static_pages/orderinfo', ['orders' => $orders], __('dujiaoka.page-title.order-detail'));
}
/**
* 订单查询页
*
* @param Request $request
* @return mixed
*
* @author assimon<ashang@utf8.hk>
* @copyright assimon<ashang@utf8.hk>
* @link http://utf8.hk/
*/
public function orderSearch(Request $request)
{
return $this->render('static_pages/searchOrder', [], __('dujiaoka.page-title.order-search'));
}
}
@@ -0,0 +1,111 @@
<?php
namespace App\Http\Controllers\Pay;
use App\Exceptions\RuleValidationException;
use App\Http\Controllers\PayController;
use Illuminate\Http\Request;
use Yansongda\Pay\Pay;
class AlipayController extends PayController
{
/**
* 支付宝支付网关
*
* @param string $payway
* @param string $orderSN
*/
public function gateway(string $payway, string $orderSN)
{
try {
// 加载网关
$this->loadGateWay($orderSN, $payway);
$config = [
'app_id' => $this->payGateway->merchant_id,
'ali_public_key' => $this->payGateway->merchant_key,
'private_key' => $this->payGateway->merchant_pem,
'notify_url' => url($this->payGateway->pay_handleroute . '/notify_url'),
'return_url' => url('detail-order-sn', ['orderSN' => $this->order->order_sn]),
'http' => [ // optional
'timeout' => 10.0,
'connect_timeout' => 10.0,
],
];
$order = [
'out_trade_no' => $this->order->order_sn,
'total_amount' => (float)$this->order->actual_price,
'subject' => $this->order->order_sn
];
switch ($payway){
case 'zfbf2f':
case 'alipayscan':
try{
$result = Pay::alipay($config)->scan($order)->toArray();
$result['payname'] = $this->order->order_sn;
$result['actual_price'] = (float)$this->order->actual_price;
$result['orderid'] = $this->order->order_sn;
$result['jump_payuri'] = $result['qr_code'];
return $this->render('static_pages/qrpay', $result, __('dujiaoka.scan_qrcode_to_pay'));
} catch (\Exception $e) {
return $this->err(__('dujiaoka.prompt.abnormal_payment_channel') . $e->getMessage());
}
case 'aliweb':
try{
$result = Pay::alipay($config)->web($order);
return $result;
} catch (\Exception $e) {
return $this->err(__('dujiaoka.prompt.abnormal_payment_channel') . $e->getMessage());
}
case 'aliwap':
try{
$result = Pay::alipay($config)->wap($order);
return $result;
} catch (\Exception $e) {
return $this->err(__('dujiaoka.prompt.abnormal_payment_channel') . $e->getMessage());
}
}
} catch (RuleValidationException $exception) {
return $this->err($exception->getMessage());
}
}
/**
* 异步通知
*/
public function notifyUrl(Request $request)
{
$orderSN = $request->input('out_trade_no');
$order = $this->orderService->detailOrderSN($orderSN);
if (!$order) {
return 'error';
}
$payGateway = $this->payService->detail($order->pay_id);
if (!$payGateway) {
return 'error';
}
if($payGateway->pay_handleroute != '/pay/alipay'){
return 'fail';
}
$config = [
'app_id' => $payGateway->merchant_id,
'ali_public_key' => $payGateway->merchant_key,
'private_key' => $payGateway->merchant_pem,
];
$pay = Pay::alipay($config);
try{
// 验证签名
$result = $pay->verify();
if ($result->trade_status == 'TRADE_SUCCESS' || $result->trade_status == 'TRADE_FINISHED') {
$this->orderProcessService->completedOrder($result->out_trade_no, $result->total_amount, $result->trade_no);
}
return 'success';
} catch (\Exception $exception) {
return 'fail';
}
}
}
@@ -0,0 +1,143 @@
<?php
namespace App\Http\Controllers\Pay;
use App\Exceptions\RuleValidationException;
use App\Http\Controllers\PayController;
use Illuminate\Http\Request;
class CoinbaseController extends PayController
{
public function gateway(string $payway, string $orderSN)
{
try {
// 加载网关
$this->loadGateWay($orderSN, $payway);
//构造要请求的参数数组,无需改动
switch ($payway) {
case 'coinbase':
default:
try {
$createOrderUrl="https://api.commerce.coinbase.com/charges";
$price_amount = sprintf('%.2f', (float)$this->order->actual_price);// 只取小数点后两位
$fees = (double)$this->payGateway->merchant_id;//手续费费率 比如 0.05
if($fees>0.00)
{
$price_amount =(double)$price_amount * (1.00+$fees);// 价格 * 1 + 0.05
}
$redirect_url = url('detail-order-sn', ['orderSN' => $this->order->order_sn]); //同步地址
$cancel_url = url('detail-order-sn', ['orderSN' => $this->order->order_sn]); //同步地址
$config = [
'name'=>$this->order->title,
'description'=>$this->order->title.'需付款'.$price_amount.'元',
'pricing_type' => 'fixed_price',
'local_price' => [
'amount' => $price_amount,
'currency' => 'CNY'
],
'metadata' => [
'customer_id' => $this->order->order_sn,
'customer_name' => $this->order->title
],
'redirect_url' =>$redirect_url,
'cancel_url'=> $cancel_url
];
$header = array();
$header[] = 'Content-Type:application/json';
$header[] = 'X-CC-Api-Key:'.$this->payGateway->merchant_key; //APP key
$header[] = 'X-CC-Version: 2018-03-22';
$ch = curl_init(); //使用curl请求
curl_setopt($ch, CURLOPT_URL, $createOrderUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($config));
$coinbase_json = curl_exec($ch);
curl_close($ch);
$coinbase_date=json_decode($coinbase_json,true);
if(is_array($coinbase_date))
{
$payment_url = $coinbase_date['data']['hosted_url'];
}
else
{
return 'fail|Coinbase支付接口请求失败';
}
return redirect()->away($payment_url);
} catch (\Exception $e) {
throw new RuleValidationException(__('dujiaoka.prompt.abnormal_payment_channel') . $e->getMessage());
}
break;
}
} catch (RuleValidationException $exception) {
return $this->err($exception->getMessage());
}
}
public function notifyUrl(Request $request)
{
$payload = file_get_contents( 'php://input' );
$sig = $_SERVER['HTTP_X_CC_WEBHOOK_SIGNATURE'];
$data = json_decode( $payload, true );
$event_data = $data['event']['data'];
$order = $this->orderService->detailOrderSN($event_data['metadata']['customer_id']);//
if (!$order) {
return 'fail';
}
$payGateway = $this->payService->detail($order->pay_id);
if (!$payGateway) {
return 'fail';
}
if($payGateway->pay_handleroute != 'pay/coinbase'){
return 'fail';
}
$secret = $payGateway->merchant_pem;//共享密钥
$sig2 = hash_hmac( 'sha256', $payload, $secret );
$result_str=array("confirmed","resolved");//返回的结果字符串数组
if (!empty( $payload ) && ($sig === $sig2))
{
foreach ($event_data['payments'] as $payment) {
//if ((strtolower($payment['status']) === 'confirmed')||(strtolower($payment['status']) === 'resolved')) {
if(in_array(strtolower($payment['status']),$result_str)){
$return_pay_amount = $payment['value']['local']['amount'];
$return_currency=$payment['value']['local']['currency'];
$return_status=strtolower($payment['status']);
}
}
if($return_currency !== 'CNY')
{
return 'error|Notify: Wrong currency:'.$return_currency;
}
$bccomp = bccomp($order->actual_price, $return_pay_amount, 2); //如果订单金额 大于 实际支付金额 返回1,抛出异常
if ($bccomp == 1) {
throw new \Exception(__('Coinbase付款金额不足'));
}
$return_merchant_order_id = $event_data['metadata']['customer_id'];//卡网订单号
$tradeid = $event_data['code'];//Coinbase订单号
//if($return_status === 'confirmed'||$return_status === 'resolved')
if(in_array(strtolower($payment['status']),$result_str)) {
$this->orderProcessService->completedOrder($return_merchant_order_id, $order->actual_price, $tradeid);// 卡网订单号,订单金额(不能传入支付金额,否则抛出订单金额不一致异常),收款平台订单号
return "{\"status\": 200}";
} else {
//不合法的数据
return 'fail';
//返回失败 继续补单
}
} else {
//不合法的数据
return 'fail|wrong sig';
//返回失败 继续补单
}
}
}
@@ -0,0 +1,104 @@
<?php
/**
* The file was created by Assimon.
*
* @author assimon<ashang@utf8.hk>
* @copyright assimon<ashang@utf8.hk>
* @link http://utf8.hk/
*/
namespace App\Http\Controllers\Pay;
use App\Exceptions\RuleValidationException;
use App\Http\Controllers\PayController;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Http\Request;
class EpusdtController extends PayController
{
public function gateway(string $payway, string $orderSN)
{
try {
// 加载网关
$this->loadGateWay($orderSN, $payway);
//构造要请求的参数数组,无需改动
$parameter = [
"amount" => (float)$this->order->actual_price,//原价
"order_id" => $this->order->order_sn, //可以是用户ID,站内商户订单号,用户名
'redirect_url' => route('epusdt-return', ['order_id' => $this->order->order_sn]),
'notify_url' => url($this->payGateway->pay_handleroute . '/notify_url'),
];
$parameter['signature'] = $this->epusdtSign($parameter, $this->payGateway->merchant_id);
$client = new Client([
'headers' => [ 'Content-Type' => 'application/json' ]
]);
$response = $client->post($this->payGateway->merchant_pem, ['body' => json_encode($parameter)]);
$body = json_decode($response->getBody()->getContents(), true);
if (!isset($body['status_code']) || $body['status_code'] != 200) {
return $this->err(__('dujiaoka.prompt.abnormal_payment_channel') . $body['message']);
}
return redirect()->away($body['data']['payment_url']);
} catch (RuleValidationException $exception) {
} catch (GuzzleException $exception) {
return $this->err($exception->getMessage());
}
}
private function epusdtSign(array $parameter, string $signKey)
{
ksort($parameter);
reset($parameter); //内部指针指向数组中的第一个元素
$sign = '';
$urls = '';
foreach ($parameter as $key => $val) {
if ($val == '') continue;
if ($key != 'signature') {
if ($sign != '') {
$sign .= "&";
$urls .= "&";
}
$sign .= "$key=$val"; //拼接为url参数形式
$urls .= "$key=" . urlencode($val); //拼接为url参数形式
}
}
$sign = md5($sign . $signKey);//密码追加进入开始MD5签名
return $sign;
}
public function notifyUrl(Request $request)
{
$data = $request->all();
$order = $this->orderService->detailOrderSN($data['order_id']);
if (!$order) {
return 'fail';
}
$payGateway = $this->payService->detail($order->pay_id);
if (!$payGateway) {
return 'fail';
}
if($payGateway->pay_handleroute != 'pay/epusdt'){
return 'fail';
}
$signature = $this->epusdtSign($data, $payGateway->merchant_id);
if ($data['signature'] != $signature) { //不合法的数据
return 'fail'; //返回失败 继续补单
} else {
//合法的数据
//业务处理
$this->orderProcessService->completedOrder($data['order_id'], $data['amount'], $data['trade_id']);
return 'ok';
}
}
public function returnUrl(Request $request)
{
$oid = $request->get('order_id');
// 异步通知还没到就跳转了,所以这里休眠2秒
sleep(2);
return redirect(url('detail-order-sn', ['orderSN' => $oid]));
}
}
@@ -0,0 +1,83 @@
<?php
namespace App\Http\Controllers\Pay;
use App\Exceptions\RuleValidationException;
use App\Http\Controllers\PayController;
use Illuminate\Http\Request;
class MapayController extends PayController
{
public function gateway(string $payway, string $orderSN)
{
try {
// 加载网关
$this->loadGateWay($orderSN, $payway);
//构造要请求的参数数组,无需改动
$parameter = array(
"id" => (int)$this->payGateway->merchant_id,//平台ID号
"price" => (float)$this->order->actual_price,//原价
"pay_id" => $this->order->order_sn, //可以是用户ID,站内商户订单号,用户名
"param" => $this->payGateway->pay_check,//自定义参数
"act" => 0,//是否开启认证版的免挂机功能
"outTime" => 120,//二维码超时设置
"page" => 1,//付款页面展示方式
'return_url' => url('detail-order-sn', ['orderSN' => $this->order->order_sn]),
'notify_url' => url($this->payGateway->pay_handleroute . '/notify_url'),
"pay_type" => 0,//支付宝使用官方接口
"chart" => 'utf-8'//字符编码方式
//其他业务参数根据在线开发文档,添加参数.文档地址:https://codepay.fateqq.com/apiword/
//如"参数名"=>"参数值"
);
switch ($payway){
case 'mqq':
$parameter['type'] = 2;
break;
case 'mzfb':
$parameter['type'] = 1;
break;
case 'mwx':
default:
$parameter['type'] = 3;
break;
}
$quri = md5_signquery($parameter, $this->payGateway->merchant_pem);
$payurl = $this->payGateway->merchant_key . $quri; //支付页面
return redirect()->away($payurl);
} catch (RuleValidationException $exception) {
return $this->err($exception->getMessage());
}
}
public function notifyUrl(Request $request)
{
$data = $request->post();
$order = $this->orderService->detailOrderSN($data['pay_id']);
if (!$order) {
return 'fail';
}
$payGateway = $this->payService->detail($order->pay_id);
if (!$payGateway) {
return 'fail';
}
if($payGateway->pay_handleroute != '/pay/mapay'){
return 'fail';
}
$query = signquery_string($data);
if (!$data['pay_no'] || md5($query . $payGateway->merchant_pem ) != $data['sign']) { //不合法的数据
return 'fail'; //返回失败 继续补单
} else { //合法的数据
//业务处理
$this->orderProcessService->completedOrder($data['pay_id'], $data['money'], $data['pay_id']);
return 'success';
}
}
}
@@ -0,0 +1,70 @@
<?php
namespace App\Http\Controllers\Pay;
use App\Exceptions\RuleValidationException;
use App\Http\Controllers\PayController;
use Illuminate\Http\Request;
use Xhat\Payjs\Facades\Payjs;
class PayjsController extends PayController
{
public function gateway(string $payway, string $orderSN)
{
try {
// 加载网关
$this->loadGateWay($orderSN, $payway);
// 构造订单基础信息
$data = [
'body' => $this->order->order_sn, // 订单标题
'total_fee' => bcmul($this->order->actual_price, 100, 0), // 订单金额
'out_trade_no' => $this->order->order_sn, // 订单号
'notify_url' => url($this->payGateway->pay_handleroute . '/notify_url'),
];
config(['payjs.mchid' => $this->payGateway->merchant_id, 'payjs.key' => $this->payGateway->merchant_pem]);
switch ($payway){
case 'payjswescan':
try{
$payres = Payjs::native($data);
if ($payres['return_code'] != 1) {
throw new RuleValidationException($payres['return_msg']);
}
$result['payname'] = $this->payGateway->pay_name;
$result['actual_price'] = (float)$this->order->actual_price;
$result['orderid'] = $this->order->order_sn;
$result['qr_code'] = $payres['code_url'];
return $this->render('static_pages/qrpay', $result, __('dujiaoka.scan_qrcode_to_pay'));
} catch (\Exception $e) {
throw new RuleValidationException(__('dujiaoka.prompt.abnormal_payment_channel') . $e->getMessage());
}
break;
}
} catch (RuleValidationException $exception) {
return $this->err($exception->getMessage());
}
}
public function notifyUrl(Request $request)
{
$orderSN = $request->input('out_trade_no');
$order = $this->orderService->detailOrderSN($orderSN);
if (!$order) {
return 'error';
}
$payGateway = $this->payService->detail($order->pay_id);
if (!$payGateway) {
return 'error';
}
if($payGateway->pay_handleroute != '/pay/payjs'){
return 'fail';
}
config(['payjs.mchid' => $payGateway->merchant_id, 'payjs.key' => $payGateway->merchant_pem]);
$notify_info = Payjs::notify();
$totalFee = bcdiv($notify_info['total_fee'], 100, 2);
$this->orderProcessService->completedOrder($notify_info['out_trade_no'], $totalFee, $notify_info['payjs_order_id']);
return 'success';
}
}
@@ -0,0 +1,148 @@
<?php
namespace App\Http\Controllers\Pay;
use AmrShawky\LaravelCurrency\Facade\Currency;
use App\Exceptions\RuleValidationException;
use App\Http\Controllers\PayController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use PayPal\Api\Amount;
use PayPal\Api\Details;
use PayPal\Api\Item;
use PayPal\Api\ItemList;
use PayPal\Api\Payer;
use PayPal\Api\Payment;
use PayPal\Api\PaymentExecution;
use PayPal\Api\RedirectUrls;
use PayPal\Api\Transaction;
use PayPal\Auth\OAuthTokenCredential;
use PayPal\Exception\PayPalConnectionException;
use PayPal\Rest\ApiContext;
class PaypalPayController extends PayController
{
const Currency = 'USD'; //货币单位
public function gateway(string $payway, string $orderSN)
{
try {
// 加载网关
$this->loadGateWay($orderSN, $payway);
$paypal = new ApiContext(
new OAuthTokenCredential(
$this->payGateway->merchant_key,
$this->payGateway->merchant_pem
)
);
$paypal->setConfig(['mode' => 'live']);
$product = $this->order->title;
// 得到汇率
$total = Currency::convert()
->from('CNY')
->to('USD')
->amount($this->order->actual_price)
->round(2)
->get();
$shipping = 0;
$description = $this->order->title;
$payer = new Payer();
$payer->setPaymentMethod('paypal');
$item = new Item();
$item->setName($product)->setCurrency(self::Currency)->setQuantity(1)->setPrice($total);
$itemList = new ItemList();
$itemList->setItems([$item]);
$details = new Details();
$details->setShipping($shipping)->setSubtotal($total);
$amount = new Amount();
$amount->setCurrency(self::Currency)->setTotal($total)->setDetails($details);
$transaction = new Transaction();
$transaction->setAmount($amount)->setItemList($itemList)->setDescription($description)->setInvoiceNumber($this->order->order_sn);
$redirectUrls = new RedirectUrls();
$redirectUrls->setReturnUrl(route('paypal-return', ['success' => 'ok', 'orderSN' => $this->order->order_sn]))->setCancelUrl(route('paypal-return', ['success' => 'no', 'orderSN' => $this->order->order_sn]));
$payment = new Payment();
$payment->setIntent('sale')->setPayer($payer)->setRedirectUrls($redirectUrls)->setTransactions([$transaction]);
$payment->create($paypal);
$approvalUrl = $payment->getApprovalLink();
return redirect($approvalUrl);
} catch (PayPalConnectionException $payPalConnectionException) {
return $this->err($payPalConnectionException->getMessage());
} catch (RuleValidationException $exception) {
return $this->err($exception->getMessage());
}
}
/**
*paypal 同步回调
*/
public function returnUrl(Request $request)
{
$success = $request->input('success');
$paymentId = $request->input('paymentId');
$payerID = $request->input('PayerID');
$orderSN = $request->input('orderSN');
if ($success == 'no' || empty($paymentId) || empty($payerID)) {
// 取消支付
redirect(url('detail-order-sn', ['orderSN' => $payerID]));
}
$order = $this->orderService->detailOrderSN($orderSN);
if (!$order) {
return 'error';
}
$payGateway = $this->payService->detail($order->pay_id);
if (!$payGateway) {
return 'error';
}
if($payGateway->pay_handleroute != '/pay/paypal'){
return 'error';
}
$paypal = new ApiContext(
new OAuthTokenCredential(
$payGateway->merchant_key,
$payGateway->merchant_pem
)
);
$paypal->setConfig(['mode' => 'live']);
$payment = Payment::get($paymentId, $paypal);
$execute = new PaymentExecution();
$execute->setPayerId($payerID);
try {
$payment->execute($execute, $paypal);
$this->orderProcessService->completedOrder($orderSN, $order->actual_price, $paymentId);
Log::info("paypal支付成功", ['支付成功,支付ID【' . $paymentId . '】,支付人ID【' . $payerID . '】']);
} catch (\Exception $e) {
Log::error("paypal支付失败", ['支付失败,支付ID【' . $paymentId . '】,支付人ID【' . $payerID . '】']);
}
return redirect(url('detail-order-sn', ['orderSN' => $orderSN]));
}
/**
* 异步通知
* TODO: 暂未实现,但是好像只实现同步回调即可。这个可以放在后面实现
*/
public function notifyUrl(Request $request)
{
//获取回调结果
$json_data = $this->get_JsonData();
if(!empty($json_data)){
Log::debug("paypal notify info:\r\n" . json_encode($json_data));
}else{
Log::debug("paypal notify fail:参加为空");
}
}
private function get_JsonData()
{
$json = file_get_contents('php://input');
if ($json) {
$json = str_replace("'", '', $json);
$json = json_decode($json,true);
}
return $json;
}
}
@@ -0,0 +1,113 @@
<?php
namespace App\Http\Controllers\Pay;
use App\Exceptions\RuleValidationException;
use App\Http\Controllers\PayController;
use Illuminate\Http\Request;
class PaysapiController extends PayController
{
const PAY_URI = 'https://pay.bearsoftware.net.cn/';
public function gateway(string $payway, string $orderSN)
{
try {
// 加载网关
$this->loadGateWay($orderSN, $payway);
//从网页传入price:支付价格, istype:支付渠道:1-支付宝;2-微信支付
$price = (float)$this->order->actual_price;
$orderuid = $this->order->email; //此处传入您网站用户的用户名,方便在paysapi后台查看是谁付的款,强烈建议加上。可忽略。
//校验传入的表单,确保价格为正常价格(整数,1位小数,2位小数都可以),支付渠道只能是1或者2,orderuid长度不要超过33个中英文字。
//此处就在您服务器生成新订单,并把创建的订单号传入到下面的orderid中。
$goodsname = $this->order->order_sn;
$orderid = $this->order->order_sn; //每次有任何参数变化,订单号就变一个吧。
$uid = $this->payGateway->merchant_id; //"此处填写PaysApi的uid";
$token = $this->payGateway->merchant_pem; //"此处填写PaysApi的Token";
$return_url = route('paysapi-return', ['order_id' => $this->order->order_sn]);
$notify_url = url($this->payGateway->pay_handleroute . '/notify_url');
switch ($payway){
case 'pszfb':
$istype = 1;
break;
case 'pswx':
default:
$istype = 2;
break;
}
$key = md5($goodsname. $istype . $notify_url . $orderid . $orderuid . $price . $return_url . $token . $uid);
//经常遇到有研发问为啥key值返回错误,大多数原因:1.参数的排列顺序不对;2.上面的参数少传了,但是这里的key值又带进去计算了,导致服务端key算出来和你的不一样。
$html = "
<html><head>
<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">
<title>loading pay...</title>
<style type=\"text/css\">
body {margin:0;padding:0;}
p {position:absolute;
left:50%;top:50%;
width:330px;height:30px;
margin:-35px 0 0 -160px;
padding:20px;font:bold 14px/30px \"宋体\", Arial;
text-indent:22px;border:1px solid #c5d0dc;}
#waiting {font-family:Arial;}
</style>
<script>
function open_without_referrer(link){
document.body.appendChild(document.createElement('iframe')).src='javascript:\"<script>top.location.replace(\''+link+'\')<\/script>\"';
}
</script>
</head>
<body style=\"\">
<form id=\"alipaysubmit\" name=\"alipaysubmit\" action=\"".self::PAY_URI."\" method=\"post\">
<input type=\"hidden\" name=\"goodsname\" value=\"".$goodsname."\">
<input type=\"hidden\" name=\"istype\" value=\"".$istype."\">
<input type=\"hidden\" name=\"key\" value=\"".$key."\">
<input type=\"hidden\" name=\"notify_url\" value=\"".$notify_url."\">
<input type=\"hidden\" name=\"orderid\" value=\"".$orderid."\">
<input type=\"hidden\" name=\"orderuid\" value=\"".$orderuid."\">
<input type=\"hidden\" name=\"price\" value=\"".$price."\">
<input type=\"hidden\" name=\"return_url\" value=\"".$return_url."\">
<input type=\"hidden\" name=\"uid\" value=\"".$uid."\">
<input type=\"submit\" value=\"正在跳转\">
</form><script>document.forms['alipaysubmit'].submit();</script></body></html>
";
return $html;
} catch (RuleValidationException $exception) {
return $this->err($exception->getMessage());
}
}
public function notifyUrl(Request $request)
{
$data = $request->post();
$order = $this->orderService->detailOrderSN($data['orderid']);
if (!$order) {
return 'error';
}
$payGateway = $this->payService->detail($order->pay_id);
if (!$payGateway) {
return 'error';
}
if($payGateway->pay_handleroute != '/pay/paysapi'){
return 'error';
}
$temps = md5($data['orderid'] . $data['orderuid'] . $data['paysapi_id'] . $data['price'] . $data['realprice'] . $payGateway->merchant_pem);
if ($temps != $data['key']){
return 'fail';
}else{
//校验key成功,是自己人。执行自己的业务逻辑:加余额,订单付款成功,装备购买成功等等。
//业务处理
$this->orderProcessService->completedOrder($data['orderid'], $data['price'], $data['paysapi_id']);
return 'success';
}
}
public function returnUrl(Request $request)
{
$oid = $request->input('order_id');
sleep(1);
return redirect(url('detail-order-sn', ['orderSN' => $oid]));
}
}
@@ -0,0 +1,540 @@
<?php
namespace App\Http\Controllers\Pay;
use App\Exceptions\RuleValidationException;
use App\Http\Controllers\PayController;
use Illuminate\Http\Request;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\Redis;
use URL;
class StripeController extends PayController
{
public function gateway(string $payway, string $orderSN)
{
// 加载网关
$this->loadGateWay($orderSN, $payway);
//构造要请求的参数数组,无需改动
switch ($payway) {
case 'wx':
case 'alipay':
default:
try {
\Stripe\Stripe::setApiKey($this->payGateway->merchant_id);
$amount = bcmul($this->order->actual_price, 100, 2);
$price = $this->order->actual_price;
$usd = bcmul($this->getUsdCurrency($this->order->actual_price), 100, 2);
$orderid = $this->order->order_sn;
$pk = $this->payGateway->merchant_id;
$return_url = site_url() . $this->payGateway->pay_handleroute . '/return_url/?orderid=' . $this->order->order_sn;
$html = "<html class=\"js cssanimations\">
<head lang=\"en\">
<meta charset=\"UTF-8\">
<title>收银台</title>
<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">
<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">
<meta name=\"format-detection\" content=\"telephone=no\">
<meta name=\"renderer\" content=\"webkit\">
<meta http-equiv=\"Cache-Control\" content=\"no-siteapp\">
<link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/amazeui@2.7.2/dist/css/amazeui.min.css\">
<script src=\"https://cdn.jsdelivr.net/npm/jquery@2.1.4/dist/jquery.min.js\"></script>
<script src=\"https://cdn.jsdelivr.net/npm/jquery.qrcode@1.0.3/jquery.qrcode.min.js\"></script>
<script src=\"https://cdn.jsdelivr.net/npm/amazeui@2.7.2/dist/js/amazeui.min.js\"></script>
<script src=\"https://js.stripe.com/v3/\"></script>
<style>
@media only screen and (min-width: 641px) {
.am-offcanvas {
display: block;
position: static;
background: none;
}
.am-offcanvas-bar {
position: static;
width: auto;
background: none;
-webkit-transform: translate3d(0, 0, 0);
-ms-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
.am-offcanvas-bar:after {
content: none;
}
}
@media only screen and (max-width: 640px) {
.am-offcanvas-bar .am-nav > li > a {
color: #ccc;
border-radius: 0;
border-top: 1px solid rgba(0, 0, 0, .3);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .05)
}
.am-offcanvas-bar .am-nav > li > a:hover {
background: #404040;
color: #fff
}
.am-offcanvas-bar .am-nav > li.am-nav-header {
color: #777;
background: #404040;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .05);
text-shadow: 0 1px 0 rgba(0, 0, 0, .5);
border-top: 1px solid rgba(0, 0, 0, .3);
font-weight: 400;
font-size: 75%
}
.am-offcanvas-bar .am-nav > li.am-active > a {
background: #1a1a1a;
color: #fff;
box-shadow: inset 0 1px 3px rgba(0, 0, 0, .3)
}
.am-offcanvas-bar .am-nav > li + li {
margin-top: 0;
}
}
.my-head {
margin-top: 40px;
text-align: center;
}
.am-tab-panel {
text-align: center;
margin-top: 50px;
margin-bottom: 50px;
}
.my-footer {
border-top: 1px solid #eeeeee;
padding: 10px 0;
margin-top: 10px;
text-align: center;
}
.panel-title {
display: inline;
font-weight: bold;
}
.display-table {
display: table;
}
.display-tr {
display: table-row;
}
.display-td {
display: table-cell;
vertical-align: middle;
width: 61%;
}
.StripeElement {
box-sizing: border-box;
height: 40px;
padding: 10px 12px;
border: 1px solid transparent;
border-radius: 4px;
background-color: white;
box-shadow: 0 1px 3px 0 #e6ebf1;
-webkit-transition: box-shadow 150ms ease;
transition: box-shadow 150ms ease;
}
.StripeElement--focus {
box-shadow: 0 1px 3px 0 #cfd7df;
}
.StripeElement--invalid {
border-color: #fa755a;
}
.StripeElement--webkit-autofill {
background-color: #fefde5 !important;
}
.form-row {
width: 70%;
float: left;
}
.wrapper {
width: 670px;
margin: 0 auto;
}
label {
font-weight: 500;
font-size: 14px;
display: block;
margin-bottom: 8px;
}
.button {
border: none;
border-radius: 4px;
outline: none;
text-decoration: none;
color: #fff;
background: #32325d;
white-space: nowrap;
display: inline-block;
height: 40px;
line-height: 40px;
padding: 0 14px;
box-shadow: 0 4px 6px rgba(50, 50, 93, .11), 0 1px 3px rgba(0, 0, 0, .08);
border-radius: 4px;
font-size: 16px;
font-weight: 600;
letter-spacing: 0.025em;
text-decoration: none;
-webkit-transition: all 150ms ease;
transition: all 150ms ease;
margin-top: 10px;
}
</style>
</head>
<body>
<header class=\"am-g my-head\">
<div class=\"am-u-sm-12 am-article\">
<h1 class=\"am-article-title\">收银台</h1>
</div>
</header>
<hr class=\"am-article-divider\">
<div class=\"am-container\">
<h2>付款信息
<div class=\"am-topbar-right\"{$price}</div>
</h2>
<p><small>订单编号:$orderid</small></p>
<div class=\"am-tabs\" data-am-tabs=\"\">
<ul class=\"am-tabs-nav am-nav am-nav-tabs\">
<li class=\"am-active\"><a href=\"#alipay\">Alipay 支付宝</a></li>
<li class=\"request-wechat-pay\"><a href=\"#wcpay\">微信支付</a></li>
<li class=\"request-card-pay\"><a href=\"#cardpay\">银行卡支付</a></li>
</ul>
<div class=\"am-tabs-bd am-tabs-bd-ofv\"
style=\"touch-action: pan-y; user-select: none; -webkit-user-drag: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\">
<div class=\"am-tab-panel am-active\" id=\"alipay\">
<a class=\"am-btn am-btn-lg am-btn-warning am-btn-primary\" id=\"alipaybtn\" href=\"#\">进入支付宝付款</a>
<p></p>
</div>
<div class=\"am-tab-panel am-fade\" id=\"wcpay\">
<div class=\"text-align:center; margin:0 auto; width:60%\">
<div class=\"wcpay-qrcode\" style=\"text-align: center; \" data-requested=\"0\">
正在加载中...
</div>
</div>
</div>
<div class=\"am-tab-panel am-fade\" id=\"cardpay\">
<div class=\"text-align:center; margin:0 auto; width:60%\">
<div class=\"wrapper cardpay_content\" style=\"max-width:500px\">
<div class=\"am-alert am-alert-danger\" style=\"display:none\">支付失败,请更换卡片或检查输入信息</div>
<form action=\"/pay/stripe/charge\" method=\"post\" id=\"payment-form\">
<div class=\"form-row\">
<label for=\"card-element\">
<p class='am-alert am-alert-secondary'>借记卡或信用卡</p>
</label>
<div id=\"card-element\">
<!-- A Stripe Element will be inserted here. -->
</div>
<!-- Used to display form errors. -->
<div id=\"card-errors\" role=\"alert\"></div>
</div>
<div class=\"form-row\">
<button class=\"button\">支付</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
var stripe = Stripe('$pk');
var source = '';
// Create a Stripe client.
// Create an instance of Elements.
var elements = stripe.elements();
// Custom styling can be passed to options when creating an Element.
// (Note that this demo uses a wider set of styles than the guide below.)
var style = {
base: {
color: '#32325d',
fontFamily: '\"Helvetica Neue\", Helvetica, sans-serif',
fontSmoothing: 'antialiased',
fontSize: '16px',
'::placeholder': {
color: '#aab7c4'
}
},
invalid: {
color: '#fa755a',
iconColor: '#fa755a'
}
};
// Create an instance of the card Element.
var card = elements.create('card', {style: style});
// Add an instance of the card Element into the `card-element` <div>.
card.mount('#card-element');
// Handle real-time validation errors from the card Element.
card.on('change', function (event) {
var displayError = document.getElementById('card-errors');
if (event.error) {
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
});
// Handle form submission.
var form = document.getElementById('payment-form');
form.addEventListener('submit', function (event) {
event.preventDefault();
$(\".button\").attr(\"disabled\",\"true\");
$(\".button\").html(\"请稍后\");
stripe.createToken(card).then(function (result) {
if (result.error) {
// Inform the user if there was an error.
var errorElement = document.getElementById('card-errors');
errorElement.textContent = result.error.message;
} else {
// Send the token to your server.
stripeTokenHandler(result.token);
}
});
});
// Submit the form with the token ID.
function stripeTokenHandler(token) {
// Insert the token ID into the form so it gets submitted to the server
var form = document.getElementById('payment-form');
var hiddenInput = document.createElement('input');
var hiddenInput1 = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'stripeToken');
hiddenInput.setAttribute('value', token.id);
hiddenInput1.setAttribute('type', 'hidden');
hiddenInput1.setAttribute('name', 'orderid');
hiddenInput1.setAttribute('value', '$orderid');
form.appendChild(hiddenInput);
form.appendChild(hiddenInput1);
// Submit the form
//form.submit();
$.ajax({
url: '/pay/stripe/charge/?orderid=$orderid&stripeToken=' + token.id,
type: 'GET',
success: function (result) {
if (result == \"success\") {
$(\".cardpay_content\").html(\"\");
$(\".cardpay_content\").html(\"<p class='am-alert am-alert-success'>支付成功,正在跳转页面</p>\");
window.setTimeout(function () {
location.href = \"/detail-order-sn/$orderid\"
}, 800);
} else {
$(\".am-alert\").show();
$(\".button\").removeAttr(\"disabled\");
$(\".button\").html(\"支付\");
setTimeout(\" $('.am-alert').hide();\", 3000);
}
}
});
}
(function () {
stripe.createSource({
type: 'alipay',
amount: $amount,
currency: 'cny',
// 这里你需要渲染出一些用户的信息,不然后期没法知道是谁在付钱
owner: {
name: '$orderid',
},
redirect: {
return_url: '$return_url',
},
}).then(function (result) {
$(\"#alipaybtn\").attr(\"href\", result.source.redirect.url);
});
})();
function paymentcheck() {
$.ajax({
url: '/pay/stripe/check/?orderid=$orderid&source=' + source,
type: 'GET',
success: function (result) {
if (result == \"success\") {
$(\".wcpay-qrcode\").html(\"\");
$(\".wcpay-qrcode\").html(\"<p class='am-alert am-alert-success'>支付成功,正在跳转页面</p>\");
window.setTimeout(function () {
location.href = \"/detail-order-sn/$orderid\"
}, 800);
} else {
setTimeout(\"paymentcheck()\", 1000);
}
}
});
}
$(\".request-wechat-pay\").click(function () {
if ($(\".wcpay-qrcode\").data(\"requested\") == 0) {
stripe.createSource({
type: 'wechat',
amount: $usd,
currency: 'usd',
owner: {
name: '$orderid'
},
}).then(function (result) {
if (result.source.id) {
$(\".wcpay-qrcode\").html(\"<p class='am-alert am-alert-success'>打开微信 - 扫一扫</p>\");
$(\".wcpay-qrcode\").qrcode(result.source.wechat.qr_code_url);
$(\".wcpay-qrcode\").data(\"requested\", 1);
$(\".wcpay-qrcode\").data(\"sid\", result.source.id);
$(\".wcpay-qrcode\").data(\"scs\", result.source.client_secret);
source = result.source.id;
setTimeout(\"paymentcheck()\", 3000);
} else {
alert(\"微信支付加载失败\");
$(\".wcpay-qrcode\").html(\"<p class='am-alert am-alert-danger'>加载失败,请刷新页面。</p>\");
}
// handle result.error or result.source
});
}
});
</script>
</body>
</html>";
return $html;
} catch (\Exception $e) {
throw new RuleValidationException(__('dujiaoka.prompt.abnormal_payment_channel') . $e->getMessage());
}
break;
}
}
public function returnUrl(Request $request)
{
$data = $request->all();
$cacheord = $this->orderService->detailOrderSN($data['orderid']);
if (!$cacheord) {
return redirect(url('detail-order-sn', ['orderSN' => $data['orderid']]));
}
$payGateway = $this->payService->detail($cacheord->pay_id);
\Stripe\Stripe::setApiKey($payGateway -> merchant_pem);
$source_object = \Stripe\Source::retrieve($data['source']);
//die($source_object);
if ($source_object->status == 'chargeable') {
\Stripe\Charge::create([
'amount' => $source_object->amount,
'currency' => $source_object->currency,
'source' => $data['source'],
]);
if ($source_object->owner->name == $data['orderid']) {
$this->orderProcessService->completedOrder($data['orderid'], $source_object->amount / 100, $source_object->id);
}
}
return redirect(url('detail-order-sn', ['orderSN' => $data['orderid']]));
}
public function check(Request $request)
{
$data = $request->all();
$cacheord = $this->orderService->detailOrderSN($data['orderid']);
if (!$cacheord) {
//可能已异步回调成功,跳转
return 'fail';
} else {
$payGateway = $this->payService->detail($cacheord->pay_id);
\Stripe\Stripe::setApiKey($payGateway -> merchant_pem);
$source_object = \Stripe\Source::retrieve($data['source']);
if ($source_object->status == 'chargeable') {
\Stripe\Charge::create([
'amount' => $source_object->amount,
'currency' => $source_object->currency,
'source' => $data['source'],
]);
}
if ($source_object->status == 'consumed' && $source_object->owner->name == $data['orderid']) {
$this->orderProcessService->completedOrder($data['orderid'], $cacheord->actual_price, $source_object->id);
return 'success';
} else {
return 'fail';
}
}
}
public function charge(Request $request)
{
$data = $request->all();
$cacheord = $this->orderService->detailOrderSN($data['orderid']);
if (!$cacheord) {
//可能已异步回调成功,跳转
return 'fail';
} else {
try {
$payGateway = $this->payService->detail($cacheord->pay_id);
\Stripe\Stripe::setApiKey($payGateway -> merchant_pem);
$result = \Stripe\Charge::create([
'amount' => bcmul($this->getUsdCurrency($cacheord->actual_price), 100,0),
'currency' => 'usd',
'source' => $data['stripeToken'],
]);
if ($result->status == 'succeeded') {
$this->orderProcessService->completedOrder($data['orderid'], $cacheord->actual_price, $data['stripeToken']);
return 'success';
}
return $result;
} catch (\Exception $e) {
return $e->getMessage();
}
}
}
/**
* 根据RMB获取美元
* @param $cny
* @return float|int
* @throws \Exception
*/
public function getUsdCurrency($cny)
{
$client = new Client();
$res = $client->get('https://m.cmbchina.com/api/rate/fx-rate');
$fxrate = json_decode($res->getBody(), true);
$data = $fxrate['body']['data'];
if (!isset($data)) {
throw new \Exception('汇率接口异常');
}
$dfFxrate = 0.13;
foreach ($data as $item) {
if ($item['ccyNbr'] == "美元") {
$dfFxrate = bcdiv(100, $item['rtcOfr'], 2);
break;
}
}
return bcmul($cny , $dfFxrate , 2);
}
}
@@ -0,0 +1,105 @@
<?php
/**
* The file was created by LightCountry.
*
* @author https://github.com/LightCountry
* @copyright https://github.com/LightCountry
* @link https://github.com/LightCountry/TokenPay
*/
namespace App\Http\Controllers\Pay;
use App\Exceptions\RuleValidationException;
use App\Http\Controllers\PayController;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Http\Request;
class TokenPayController extends PayController
{
public function gateway(string $payway, string $orderSN)
{
try {
// 加载网关
$this->loadGateWay($orderSN, $payway);
//构造要请求的参数数组,无需改动
$parameter = [
"ActualAmount" => (float)$this->order->actual_price,//原价
"OutOrderId" => $this->order->order_sn,
"OrderUserKey" => $this->order->email,
"Currency" => $this->payGateway->merchant_id,
'RedirectUrl' => route('tokenpay-return', ['order_id' => $this->order->order_sn]),
'NotifyUrl' => url($this->payGateway->pay_handleroute . '/notify_url'),
];
$parameter['Signature'] = $this->VerifySign($parameter, $this->payGateway->merchant_key);
$client = new Client([
'headers' => [ 'Content-Type' => 'application/json' ]
]);
$response = $client->post($this->payGateway->merchant_pem.'/CreateOrder', ['body' => json_encode($parameter)]);
$body = json_decode($response->getBody()->getContents(), true);
if (!isset($body['success']) || $body['success'] != true) {
return $this->err(__('dujiaoka.prompt.abnormal_payment_channel') . $body['message']);
}
return redirect()->away($body['data']);
} catch (RuleValidationException $exception) {
} catch (GuzzleException $exception) {
return $this->err($exception->getMessage());
}
}
private function VerifySign(array $parameter, string $signKey)
{
ksort($parameter);
reset($parameter); //内部指针指向数组中的第一个元素
$sign = '';
$urls = '';
foreach ($parameter as $key => $val) {
if ($key != 'Signature') {
if ($sign != '') {
$sign .= "&";
$urls .= "&";
}
$sign .= "$key=$val"; //拼接为url参数形式
$urls .= "$key=" . urlencode($val); //拼接为url参数形式
}
}
$sign = md5($sign . $signKey);//密码追加进入开始MD5签名
return $sign;
}
public function notifyUrl(Request $request)
{
$data = $request->all();
$order = $this->orderService->detailOrderSN($data['OutOrderId']);
if (!$order) {
return 'fail';
}
$payGateway = $this->payService->detail($order->pay_id);
if (!$payGateway) {
return 'fail';
}
if($payGateway->pay_handleroute != 'pay/tokenpay'){
return 'fail';
}
//合法的数据
$signature = $this->VerifySign($data, $payGateway->merchant_key);
if ($data['Signature'] != $signature) { //不合法的数据
return 'fail'; //返回失败 继续补单
} else {
//合法的数据
//业务处理
$this->orderProcessService->completedOrder($data['OutOrderId'], $data['ActualAmount'], $data['Id']);
return 'ok';
}
}
public function returnUrl(Request $request)
{
$oid = $request->get('order_id');
// 异步通知还没到就跳转了,所以这里休眠2秒
sleep(2);
return redirect(url('detail-order-sn', ['orderSN' => $oid]));
}
}
@@ -0,0 +1,94 @@
<?php
/**
* VpayController.php
* V免签
* Author iLay1678
* Created on 2020/5/1 11:59
*/
namespace App\Http\Controllers\Pay;
use App\Exceptions\RuleValidationException;
use App\Http\Controllers\PayController;
use Illuminate\Http\Request;
class VpayController extends PayController
{
public function gateway(string $payway, string $orderSN)
{
try {
// 加载网关
$this->loadGateWay($orderSN, $payway);
//构造要请求的参数数组,无需改动
$parameter = array(
"payId" => date('YmdHis') . rand(1, 65535),//平台ID号
"price" => (float)$this->order->actual_price,//原价
'param' => $this->order->order_sn,
'returnUrl' => route('vpay-return', ['order_id' => $this->order->order_sn]),
'notifyUrl' => url($this->payGateway->pay_handleroute . '/notify_url'),
"isHtml" => 1,
);
switch ($payway) {
case 'vzfb':
$parameter['type'] = 2;
break;
case 'vwx':
default:
$parameter['type'] = 1;
break;
}
$parameter['sign'] = md5($parameter['payId'] . $parameter['param'] . $parameter['type'] . $parameter['price'] . $this->payGateway->merchant_id);
$payurl = $this->payGateway->merchant_pem . 'createOrder?' . http_build_query($parameter); //支付页面
return redirect()->away($payurl);
} catch (RuleValidationException $exception) {
return $this->err($exception->getMessage());
}
}
public function notifyUrl(Request $request)
{
$data = $request->all();
$order = $this->orderService->detailOrderSN($data['param']);
if (!$order) {
return 'fail';
}
$payGateway = $this->payService->detail($order->pay_id);
if($payGateway->pay_handleroute != 'pay/vpay'){
return 'fail';
}
if (!$payGateway) {
return 'fail';
}
$key = $payGateway->merchant_id;//通讯密钥
$payId = $data['payId'];//商户订单号
$param = $data['param'];//创建订单的时候传入的参数
$type = $data['type'];//支付方式 :微信支付为1 支付宝支付为2
$price = $data['price'];//订单金额
$reallyPrice = $data['reallyPrice'];//实际支付金额
$sign = $data['sign'];//校验签名,计算方式 = md5(payId + param + type + price + reallyPrice + 通讯密钥)
//开始校验签名
$_sign = md5($payId . $param . $type . $price . $reallyPrice . $key);
if ($_sign != $sign) { //不合法的数据
return 'fail'; //返回失败 继续补单
} else { //合法的数据
//业务处理
$this->orderProcessService->completedOrder($param, $price, $payId);
return 'success';
}
}
public function returnUrl(Request $request)
{
$oid = $request->get('order_id');
// 异步通知还没到就跳转了,所以这里休眠2秒
sleep(2);
return redirect(url('detail-order-sn', ['orderSN' => $oid]));
}
}
@@ -0,0 +1,89 @@
<?php
namespace App\Http\Controllers\Pay;
use App\Exceptions\RuleValidationException;
use App\Http\Controllers\PayController;
use Yansongda\Pay\Pay;
class WepayController extends PayController
{
public function gateway(string $payway, string $orderSN)
{
try {
// 加载网关
$this->loadGateWay($orderSN, $payway);
$config = [
'app_id' => $this->payGateway->merchant_id,
'mch_id' => $this->payGateway->merchant_key,
'key' => $this->payGateway->merchant_pem,
'notify_url' => url($this->payGateway->pay_handleroute . '/notify_url'),
'return_url' => url('detail-order-sn', ['orderSN' => $this->order->order_sn]),
'http' => [ // optional
'timeout' => 10.0,
'connect_timeout' => 10.0,
],
];
$order = [
'out_trade_no' => $this->order->order_sn,
'total_fee' => bcmul($this->order->actual_price, 100, 0),
'body' => $this->order->order_sn
];
switch ($payway){
case 'wescan':
try{
$result = Pay::wechat($config)->scan($order)->toArray();
$result['qr_code'] = $result['code_url'];
$result['payname'] =$this->payGateway->pay_name;
$result['actual_price'] = (float)$this->order->actual_price;
$result['orderid'] = $this->order->order_sn;
return $this->render('static_pages/qrpay', $result, __('dujiaoka.scan_qrcode_to_pay'));
} catch (\Exception $e) {
throw new RuleValidationException(__('dujiaoka.prompt.abnormal_payment_channel') . $e->getMessage());
}
break;
}
} catch (RuleValidationException $exception) {
return $this->err($exception->getMessage());
}
}
/**
* 异步通知
*/
public function notifyUrl()
{
$xml = file_get_contents('php://input');
$arr = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
$oid = $arr['out_trade_no'];
$order = $this->orderService->detailOrderSN($oid);
if (!$order) {
return 'error';
}
$payGateway = $this->payService->detail($order->pay_id);
if (!$payGateway) {
return 'error';
}
if($payGateway->pay_handleroute != '/pay/wepay'){
return 'error';
}
$config = [
'app_id' => $payGateway->merchant_id,
'mch_id' => $payGateway->merchant_key,
'key' => $payGateway->merchant_pem,
];
$pay = Pay::wechat($config);
try{
// 验证签名
$result = $pay->verify();
$total_fee = bcdiv($result->total_fee, 100, 2);
$this->orderProcessService->completedOrder($result->out_trade_no, $total_fee, $result->transaction_id);
return 'success';
} catch (\Exception $exception) {
return 'fail';
}
}
}
@@ -0,0 +1,103 @@
<?php
namespace App\Http\Controllers\Pay;
use App\Exceptions\RuleValidationException;
use App\Http\Controllers\PayController;
use Illuminate\Http\Request;
class YipayController extends PayController
{
public function gateway(string $payway, string $orderSN)
{
try {
// 加载网关
$this->loadGateWay($orderSN, $payway);
//组装支付参数
$parameter = [
'pid' => $this->payGateway->merchant_id,
'type' => $payway,
'out_trade_no' => $this->order->order_sn,
'return_url' => route('yipay-return', ['order_id' => $this->order->order_sn]),
'notify_url' => url($this->payGateway->pay_handleroute . '/notify_url'),
'name' => $this->order->order_sn,
'money' => (float)$this->order->actual_price,
'sign' => $this->payGateway->merchant_pem,
'sign_type' =>'MD5'
];
ksort($parameter); //重新排序$data数组
reset($parameter); //内部指针指向数组中的第一个元素
$sign = '';
foreach ($parameter as $key => $val) {
if ($key == "sign" || $key == "sign_type" || $val == "") continue;
if ($key != 'sign') {
if ($sign != '') {
$sign .= "&";
}
$sign .= "$key=$val"; //拼接为url参数形式
}
}
$sign = md5($sign . $this->payGateway->merchant_pem);//密码追加进入开始MD5签名
$parameter['sign'] = $sign;
//待请求参数数组
$sHtml = "<form id='alipaysubmit' name='alipaysubmit' action='" . $this->payGateway->merchant_key . "' method='get'>";
foreach($parameter as $key => $val) {
$sHtml.= "<input type='hidden' name='".$key."' value='".$val."'/>";
}
//submit按钮控件请不要含有name属性
$sHtml = $sHtml."<input type='submit' value=''></form>";
$sHtml = $sHtml."<script>document.forms['alipaysubmit'].submit();</script>";
return $sHtml;
} catch (RuleValidationException $exception) {
return $this->err($exception->getMessage());
}
}
public function notifyUrl(Request $request)
{
$data = $request->all();
$order = $this->orderService->detailOrderSN($data['out_trade_no']);
if (!$order) {
return 'fail';
}
$payGateway = $this->payService->detail($order->pay_id);
if (!$payGateway) {
return 'fail';
}
if($payGateway->pay_handleroute != '/pay/yipay'){
return 'fail';
}
ksort($data); //重新排序$data数组
reset($data); //内部指针指向数组中的第一个元素
$sign = '';
foreach ($data as $key => $val) {
if ($key == "sign" || $key == "sign_type" || $val == "") continue;
if ($key != 'sign') {
if ($sign != '') {
$sign .= "&";
}
$sign .= "$key=$val"; //拼接为url参数形式
}
}
if (!$data['trade_no'] || md5($sign . $payGateway->merchant_pem) != $data['sign']) { //不合法的数据
return 'fail'; //返回失败 继续补单
} else {
//合法的数据
//业务处理
$this->orderProcessService->completedOrder($data['out_trade_no'], $data['money'], $data['trade_no']);
return 'success';
}
}
public function returnUrl(Request $request)
{
$oid = $request->get('order_id');
// 有些易支付太垃了,异步通知还没到就跳转了,导致订单显示待支付,其实已经支付了,所以这里休眠2秒
sleep(2);
return redirect(url('detail-order-sn', ['orderSN' => $oid]));
}
}
+130
View File
@@ -0,0 +1,130 @@
<?php
namespace App\Http\Controllers;
use App\Exceptions\RuleValidationException;
use App\Models\Order;
use App\Service\OrderProcessService;
class PayController extends BaseController
{
/**
* 支付网关
* @var \App\Models\Pay
*/
protected $payGateway;
/**
* 订单
* @var \App\Models\Order
*/
protected $order;
/**
* 订单服务层
* @var \App\Service\OrderService
*/
protected $orderService;
/**
* 支付服务层
* @var \App\Service\PayService
*/
protected $payService;
/**
* 订单处理层.
* @var OrderProcessService
*/
protected $orderProcessService;
public function __construct()
{
$this->orderService = app('Service\OrderService');
$this->payService = app('Service\PayService');
$this->orderProcessService = app('Service\OrderProcessService');
}
/**
* 订单检测
*
* @param string $orderSN
* @throws RuleValidationException
*
* @author assimon<ashang@utf8.hk>
* @copyright assimon<ashang@utf8.hk>
* @link http://utf8.hk/
*/
public function checkOrder(string $orderSN)
{
// 订单
$this->order = $this->orderService->detailOrderSN($orderSN);
if (!$this->order) {
throw new RuleValidationException(__('dujiaoka.prompt.order_does_not_exist'));
}
// 订单过期
if ($this->order->status == Order::STATUS_EXPIRED) {
throw new RuleValidationException(__('dujiaoka.prompt.order_is_expired'));
}
// 已经支付了
if ($this->order->status > Order::STATUS_WAIT_PAY) {
throw new RuleValidationException(__('dujiaoka.prompt.order_already_paid'));
}
}
/**
* 加载支付网关
*
* @param string $orderSN 订单号
* @param string $payCheck 支付标识
* @throws RuleValidationException
*
* @author assimon<ashang@utf8.hk>
* @copyright assimon<ashang@utf8.hk>
* @link http://utf8.hk/
*/
public function loadGateWay(string $orderSN, string $payCheck)
{
$this->checkOrder($orderSN);
// 支付配置
$this->payGateway = $this->payService->detailByCheck($payCheck);
if (!$this->payGateway) {
throw new RuleValidationException(__('dujiaoka.prompt.pay_gateway_does_not_exist'));
}
// 临时保存支付方式
$this->order->pay_id = $this->payGateway->id;
$this->order->save();
}
/**
* 网关处理.
*
* @param string $handle 跳转方法
* @param string $payway 支付标识
* @param string $orderSN 订单.
*
* @author assimon<ashang@utf8.hk>
* @copyright assimon<ashang@utf8.hk>
* @link http://utf8.hk/
*/
public function redirectGateway(string $handle,string $payway, string $orderSN)
{
try {
$this->checkOrder($orderSN);
$bccomp = bccomp($this->order->actual_price, 0.00, 2);
// 如果订单金额为0 代表无需支付,直接成功
if ($bccomp == 0) {
$this->orderProcessService->completedOrder($this->order->order_sn, 0.00);
return redirect(url('detail-order-sn', ['orderSN' => $this->order->order_sn]));
}
return redirect(url(urldecode($handle), ['payway' => $payway, 'orderSN' => $orderSN]));
} catch (RuleValidationException $exception) {
return $this->err($exception->getMessage());
}
}
}
+89
View File
@@ -0,0 +1,89 @@
<?php
namespace App\Http;
use App\Http\Middleware\DujiaoBoot;
use App\Http\Middleware\InstallCheck;
use App\Http\Middleware\PayGateWay;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* @var array
*/
protected $middleware = [
\App\Http\Middleware\TrustProxies::class,
\App\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\App\Http\Middleware\DujiaoSystem::class,
];
/**
* The application's route middleware groups.
*
* @var array
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'throttle:60,1',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* @var array
*/
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'dujiaoka.boot' => DujiaoBoot::class,
'dujiaoka.pay_gate_way' => PayGateWay::class,
'install.check' => InstallCheck::class,
];
/**
* The priority-sorted list of middleware.
*
* This forces non-global middleware to always be in the given order.
*
* @var array
*/
protected $middlewarePriority = [
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\Authenticate::class,
\Illuminate\Routing\Middleware\ThrottleRequests::class,
\Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Auth\Middleware\Authorize::class,
];
}
+21
View File
@@ -0,0 +1,21 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
class Authenticate extends Middleware
{
/**
* Get the path the user should be redirected to when they are not authenticated.
*
* @param \Illuminate\Http\Request $request
* @return string|null
*/
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
return route('login');
}
}
}
@@ -0,0 +1,17 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode as Middleware;
class CheckForMaintenanceMode extends Middleware
{
/**
* The URIs that should be reachable while maintenance mode is enabled.
*
* @var array
*/
protected $except = [
//
];
}
+58
View File
@@ -0,0 +1,58 @@
<?php
namespace App\Http\Middleware;
use App\Models\BaseModel;
use Closure;
use Germey\Geetest\GeetestServiceProvider;
class DujiaoBoot
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
// 安装检查
$installLock = base_path() . DIRECTORY_SEPARATOR . 'install.lock';
if (!file_exists($installLock)) {
return redirect(url('install'));
}
// 浏览器检测
$userAgent = $request->header('user-agent');
$nowUri = site_url() . $request->path();
$tplPath = 'common/notencent';
if (
(strpos($userAgent, 'QQ/')
||
strpos($userAgent, 'MicroMessenger') !== false)
&&
dujiaoka_config_get('is_open_anti_red', BaseModel::STATUS_OPEN) == BaseModel::STATUS_OPEN
) {
return response()->view($tplPath, ['nowUri' => $nowUri]);
}
// 语言检测
$lang = dujiaoka_config_get('language', 'zh_CN');
app()->setLocale($lang);
// 极验
$geetest = dujiaoka_config_get('is_open_geetest', BaseModel::STATUS_CLOSE);
if ($geetest == BaseModel::STATUS_OPEN) {
$geetestConfig = [
'key' => dujiaoka_config_get('geetest_key'),
'id' => dujiaoka_config_get('geetest_id'),
'lang' => $lang
];
// 覆盖 配置
config([
'geetest' => array_merge(config('mail'), $geetestConfig)
]);
// 重新注册服务
(new GeetestServiceProvider(app()))->register();
}
return $next($request);
}
}
+31
View File
@@ -0,0 +1,31 @@
<?php
namespace App\Http\Middleware;
use App\Providers\AppServiceProvider;
use Closure;
class DujiaoSystem
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
// 检测https
if ($request->getScheme() == 'https') {
$httpsConfig = [
'https' => true
];
config([
'admin' => array_merge(config('admin'), $httpsConfig)
]);
(new AppServiceProvider(app()))->register();
}
return $next($request);
}
}
+17
View File
@@ -0,0 +1,17 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
class EncryptCookies extends Middleware
{
/**
* The names of the cookies that should not be encrypted.
*
* @var array
*/
protected $except = [
//
];
}
+25
View File
@@ -0,0 +1,25 @@
<?php
namespace App\Http\Middleware;
use Closure;
class InstallCheck
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
// 安装检查
$installLock = base_path() . DIRECTORY_SEPARATOR . 'install.lock';
if (file_exists($installLock)) {
return redirect(url('/'));
}
return $next($request);
}
}
+21
View File
@@ -0,0 +1,21 @@
<?php
namespace App\Http\Middleware;
use Closure;
class PayGateWay
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
return $next($request);
}
}
@@ -0,0 +1,27 @@
<?php
namespace App\Http\Middleware;
use App\Providers\RouteServiceProvider;
use Closure;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null $guard
* @return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
return redirect(RouteServiceProvider::HOME);
}
return $next($request);
}
}
+18
View File
@@ -0,0 +1,18 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\TrimStrings as Middleware;
class TrimStrings extends Middleware
{
/**
* The names of the attributes that should not be trimmed.
*
* @var array
*/
protected $except = [
'password',
'password_confirmation',
];
}
+23
View File
@@ -0,0 +1,23 @@
<?php
namespace App\Http\Middleware;
use Fideloper\Proxy\TrustProxies as Middleware;
use Illuminate\Http\Request;
class TrustProxies extends Middleware
{
/**
* The trusted proxies for this application.
*
* @var array|string
*/
protected $proxies;
/**
* The headers that should be used to detect proxies.
*
* @var int
*/
protected $headers = Request::HEADER_X_FORWARDED_ALL;
}
+24
View File
@@ -0,0 +1,24 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
/**
* Indicates whether the XSRF-TOKEN cookie should be set on the response.
*
* @var bool
*/
protected $addHttpCookie = true;
/**
* The URIs that should be excluded from CSRF verification.
*
* @var array
*/
protected $except = [
'pay/*',
];
}