gz
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
use api\Httpcurl;
|
||||
use think\facade\Db;
|
||||
|
||||
const DOMAIN = 'www.evus.cn';
|
||||
const DOMAIN = 'evus.acvisa.cn';
|
||||
/**
|
||||
* 发给py进行提交注册
|
||||
*/
|
||||
|
||||
@@ -12,9 +12,9 @@ const GET_ORDER_URL = 'https://uniuser.jzvisa.com/home/order/orderList';
|
||||
const INCOICETYPE = '1';
|
||||
|
||||
const MODEL = 'msg';
|
||||
const BUCKET = 'jnevus';
|
||||
const BUCKET = 'gzevus';
|
||||
const COUNTRY = 'EVUS登记';
|
||||
const SOURCE = 'cn';
|
||||
const SOURCE = 'evus.acvisa.cn';
|
||||
const PAY_MARK = 'evuscn';
|
||||
const OSS_URL = 'https://files.jzvisa.com/' . BUCKET . '/';
|
||||
|
||||
|
||||
@@ -72,12 +72,19 @@ class Base extends BaseController
|
||||
Config::set(['pay_url' => $config_result['data']['pay']['pay_url']], 'app');
|
||||
Config::set(['order_url' => $config_result['data']['order_url']], 'app');
|
||||
Config::set(['user_url' => $config_result['data']['user_url']], 'app');
|
||||
Config::set(['yzm_url' => $config_result['data']['yzm_url'] ?? ''], 'app');
|
||||
Config::set(['principals' => $config_result['data']['principals']], 'app');
|
||||
Config::set(['get_evus_detail_url' => $config_result['data']['get_evus_detail_url']], 'app');
|
||||
Config::set(['get_order_detail_url' => $config_result['data']['get_order_detail_url']], 'app');
|
||||
Config::set(['download_evus_url' => $config_result['data']['download_evus_url']], 'app');
|
||||
Config::set(['update_order_url' => $config_result['data']['update_order_url']], 'app');
|
||||
|
||||
$paymentMethods = $config_result['data']['payment_methods'] ?? [];
|
||||
$paymentMethods = is_array($paymentMethods) ? $paymentMethods : [];
|
||||
Config::set(['payment_methods_configured' => (new \app\service\PaymentSelectionService($paymentMethods))->hasEnabledMethods()], 'app');
|
||||
Config::set(['payment_methods' => $paymentMethods], 'app');
|
||||
Config::set(['selected_payment' => $config_result['data']['pay_qz'] ?? []], 'app');
|
||||
|
||||
/*ocr 识别 配置参数 */
|
||||
Config::set(['OCR_BASE_URL' => $config_result['data']['ocr_base_url']], 'app');
|
||||
Config::set(['OCR_APP_ID' => $config_result['data']['ocr_app_id']], 'app');
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
declare (strict_types=1);
|
||||
|
||||
declare(strict_types=1);
|
||||
namespace app\home\controller;
|
||||
|
||||
use think\facade\View;
|
||||
@@ -9,6 +9,21 @@ class Company extends Base
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
return View::fetch();
|
||||
$config=json_decode(file_get_contents(app()->getRootPath().'data/config.json'),true);
|
||||
$data=$config['data']??[];
|
||||
// Render configured rich text as escaped paragraphs, without executable HTML or inline styles.
|
||||
$brief=is_string($data['brief']??null)?$data['brief']:'';
|
||||
$parts=preg_split('~</(?:p|div|h[1-6]|li)>|<br\s*/?>~i',$brief)?:[];
|
||||
$paragraphs=[];
|
||||
foreach($parts as $part) {
|
||||
$text=html_entity_decode(strip_tags($part),ENT_QUOTES|ENT_HTML5,'UTF-8');
|
||||
$text=trim(preg_replace('/[\s\x{00a0}]+/u',' ',$text)??'');
|
||||
if($text!=='') $paragraphs[]=$text;
|
||||
}
|
||||
View::assign('company_name',is_string($data['company_name']??null)?$data['company_name']:'');
|
||||
View::assign('company_paragraphs',$paragraphs);
|
||||
View::assign('company_phone', is_string($data['phone'] ?? null) ? $data['phone'] : '');
|
||||
View::assign('company_email', is_string($data['email'] ?? null) ? $data['email'] : '');
|
||||
return View::fetch('company/index');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,11 @@ class Detail extends Base
|
||||
|
||||
public function index()
|
||||
{
|
||||
$methods = (new \app\service\PaymentSelectionService((array) config('app.payment_methods', [])))
|
||||
->methods((string) ($_SERVER['HTTP_USER_AGENT'] ?? ''));
|
||||
View::assign('payment_methods', $methods);
|
||||
View::assign('payment_methods_configured', (bool) config('app.payment_methods_configured', false));
|
||||
View::assign('payment_english', \think\facade\Lang::getLangSet() === 'en-us');
|
||||
View::assign('country_list', json_decode(file_get_contents('./json/country.json'), true));
|
||||
View::assign('phone_prefix', json_decode(file_get_contents('./json/phone_prefix.json'), true));
|
||||
View::assign('us', json_decode(file_get_contents('./json/us.json'), true));
|
||||
@@ -22,6 +27,17 @@ class Detail extends Base
|
||||
}
|
||||
public function do_apply()
|
||||
{
|
||||
$paymentConfigured = (bool) config('app.payment_methods_configured', false);
|
||||
$paymentMethod = '';
|
||||
if ($paymentConfigured) {
|
||||
try {
|
||||
$paymentMethod = (new \app\service\PaymentSelectionService((array) config('app.payment_methods', [])))
|
||||
->select($_REQUEST['payment_method'] ?? '', (string) ($_SERVER['HTTP_USER_AGENT'] ?? ''));
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
return $this->error($e->getMessage());
|
||||
}
|
||||
}
|
||||
unset($_REQUEST['payment_method']);
|
||||
unset($_REQUEST['s']);
|
||||
$order_sn = $_REQUEST['order_sn'] = getOrderNumber();
|
||||
$total_price = $_REQUEST['total_price'];
|
||||
@@ -78,7 +94,12 @@ class Detail extends Base
|
||||
if ($order['is_pay'] == 1) {
|
||||
return $this->success('操作成功', url('home/pay/succ', ['order_sn' => $order_sn])->build());
|
||||
}
|
||||
return $this->success('操作成功', url('home/pay/index', ['order_sn' => $order_sn])->build());
|
||||
if (!$paymentConfigured) {
|
||||
return $this->success('操作成功', url('home/pay/index', ['order_sn' => $order_sn])->build());
|
||||
}
|
||||
return $this->success('操作成功', url('home/pay/checkout', ['order_sn' => $order_sn, 'payment_method' => $paymentMethod])->build(), [
|
||||
'open_new_tab' => !isMobile() && $paymentMethod === 'alipay',
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -14,6 +14,11 @@ class Esta extends Base
|
||||
|
||||
public function index()
|
||||
{
|
||||
$methods = (new \app\service\PaymentSelectionService((array) config('app.payment_methods', [])))
|
||||
->methods((string) ($_SERVER['HTTP_USER_AGENT'] ?? ''));
|
||||
View::assign('payment_methods', $methods);
|
||||
View::assign('payment_methods_configured', (bool) config('app.payment_methods_configured', false));
|
||||
View::assign('payment_english', \think\facade\Lang::getLangSet() === 'en-us');
|
||||
View::assign('country_list', json_decode(file_get_contents('./json/country.json'), true));
|
||||
View::assign('phone_prefix', json_decode(file_get_contents('./json/phone_prefix.json'), true));
|
||||
View::assign('us', json_decode(file_get_contents('./json/us.json'), true));
|
||||
@@ -26,6 +31,17 @@ class Esta extends Base
|
||||
|
||||
public function do_apply()
|
||||
{
|
||||
$paymentConfigured = (bool) config('app.payment_methods_configured', false);
|
||||
$paymentMethod = '';
|
||||
if ($paymentConfigured) {
|
||||
try {
|
||||
$paymentMethod = (new \app\service\PaymentSelectionService((array) config('app.payment_methods', [])))
|
||||
->select($_REQUEST['payment_method'] ?? '', (string) ($_SERVER['HTTP_USER_AGENT'] ?? ''));
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
return $this->error($e->getMessage());
|
||||
}
|
||||
}
|
||||
unset($_REQUEST['payment_method']);
|
||||
unset($_REQUEST['s']);
|
||||
unset($_REQUEST['file']);
|
||||
$order_sn = $_REQUEST['order_sn'] = getOrderNumber();
|
||||
@@ -75,7 +91,12 @@ class Esta extends Base
|
||||
if (!$order['code']) {
|
||||
return $this->error("提交失败,请联系管理员!");
|
||||
}
|
||||
return $this->success('操作成功', url('home/payesta/index', ['order_sn' => $order_sn])->build());
|
||||
if (!$paymentConfigured) {
|
||||
return $this->success('操作成功', url('home/payesta/index', ['order_sn' => $order_sn])->build());
|
||||
}
|
||||
return $this->success('操作成功', url('home/payesta/checkout', ['order_sn' => $order_sn, 'payment_method' => $paymentMethod])->build(), [
|
||||
'open_new_tab' => !isMobile() && $paymentMethod === 'alipay',
|
||||
]);
|
||||
}
|
||||
public function wxmini()
|
||||
{
|
||||
|
||||
@@ -28,13 +28,16 @@ class Login extends Base
|
||||
// $result['code'] = 1;
|
||||
$code = mt_rand(1001, 9999);
|
||||
//进行发送验证 走接口
|
||||
$res = Httpcurl::request(YZM_URL, 'post', [
|
||||
$smsUrl = (string) config('app.yzm_url', '');
|
||||
if (!filter_var($smsUrl, FILTER_VALIDATE_URL) || strtolower((string) parse_url($smsUrl, PHP_URL_SCHEME)) !== 'https') {
|
||||
return $this->error('短信服务尚未配置,请联系客服');
|
||||
}
|
||||
$res = Httpcurl::request($smsUrl, 'post', [
|
||||
'mobile' => $param['mobile'],
|
||||
'code' => $code,
|
||||
]);
|
||||
$result = json_decode($res[0], true);
|
||||
Log::info(json_encode($result));
|
||||
if (!$result['code']) {
|
||||
], [], 15);
|
||||
$result = json_decode((string) ($res[0] ?? ''), true);
|
||||
if (!empty($res[3]) || (int) ($result['code'] ?? 0) !== 1) {
|
||||
return $this->error('发送验证码失败');
|
||||
}
|
||||
// 进行记录
|
||||
|
||||
@@ -13,6 +13,13 @@ use think\Response;
|
||||
|
||||
class Pay extends Base
|
||||
{
|
||||
use \app\home\controller\concern\SelectedPayment;
|
||||
|
||||
public function checkout()
|
||||
{
|
||||
return $this->selectedCheckout(MODEL, PAY_MARK, COUNTRY, (string) config('app.get_evus_detail_url'), 'pay');
|
||||
}
|
||||
|
||||
private $order_sn = '';
|
||||
|
||||
public function initialize()
|
||||
|
||||
@@ -13,6 +13,13 @@ use think\Response;
|
||||
|
||||
class Payesta extends Base
|
||||
{
|
||||
use \app\home\controller\concern\SelectedPayment;
|
||||
|
||||
public function checkout()
|
||||
{
|
||||
return $this->selectedCheckout(ESTA_MODEL, PAY_ESTA_MARK, ESTA_COUNTRY, (string) config('app.get_order_detail_url'), 'payesta');
|
||||
}
|
||||
|
||||
private $order_sn = '';
|
||||
|
||||
public function initialize()
|
||||
|
||||
54
app/home/controller/concern/SelectedPayment.php
Normal file
54
app/home/controller/concern/SelectedPayment.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace app\home\controller\concern;
|
||||
|
||||
use api\Httpcurl;
|
||||
use app\service\PaymentSelectionService;
|
||||
use think\facade\View;
|
||||
|
||||
trait SelectedPayment
|
||||
{
|
||||
protected function selectedCheckout(string $model, string $mark, string $country, string $detailUrl, string $route)
|
||||
{
|
||||
try {
|
||||
$response = Httpcurl::request($detailUrl, 'post', ['order_sn' => $this->order_sn, 'model' => $model], [], 15);
|
||||
$result = json_decode((string) ($response[0] ?? ''), true);
|
||||
$order = $result['data'] ?? null;
|
||||
if (!empty($response[3]) || (int) ($result['code'] ?? 0) !== 1 || !is_array($order)
|
||||
|| ($order['order_sn'] ?? '') !== $this->order_sn
|
||||
|| !in_array($order['pay_status'] ?? null, [0, 1, '0', '1'], true)) {
|
||||
throw new \RuntimeException('订单信息获取失败,请稍后重试');
|
||||
}
|
||||
if ((int) $order['pay_status'] === 1) return redirect(url($route . '/succ', ['order_sn' => $this->order_sn])->build());
|
||||
if (!isset($order['total_price']) || !ctype_digit((string) $order['total_price']) || (int) $order['total_price'] <= 0) {
|
||||
throw new \RuntimeException('订单金额无效,请联系客服');
|
||||
}
|
||||
$service = new PaymentSelectionService((array) config('app.payment_methods', []));
|
||||
$ua = (string) ($_SERVER['HTTP_USER_AGENT'] ?? '');
|
||||
$method = $service->select(request()->param('payment_method', ''), $ua);
|
||||
$action = $service->action($method, isMobile(), $ua);
|
||||
$key = $method === 'alipay' ? (isMobile() ? 'alih5pay' : 'alipcpay')
|
||||
: ['pcpay' => 'wechatpcpay', 'wxpay' => 'wechatpay', 'h5pay' => 'wechath5pay'][$action];
|
||||
$endpoint = (string) config('app.selected_payment.' . $key, '');
|
||||
if (!filter_var($endpoint, FILTER_VALIDATE_URL) || strtolower((string) parse_url($endpoint, PHP_URL_SCHEME)) !== 'https') {
|
||||
throw new \RuntimeException('支付通道尚未配置,请联系客服');
|
||||
}
|
||||
$params = ['order_sn' => $this->order_sn, 'mark' => $mark, 'body' => $country . '服务费'];
|
||||
if ($method === 'wechat' && $action !== 'pcpay') {
|
||||
return redirect($endpoint . (str_contains($endpoint, '?') ? '&' : '?') . http_build_query($params));
|
||||
}
|
||||
// Keep the existing PC Alipay gateway contract; H5 accepts the plain body.
|
||||
if ($action === 'alipay') $params['body'] = urlencode($params['body']);
|
||||
$response = Httpcurl::request($endpoint, 'get', $params, [], 15);
|
||||
$url = $service->gatewayUrl($response, $method === 'alipay' && isMobile());
|
||||
if ($method === 'alipay') return redirect($url);
|
||||
View::assign('url', $url);
|
||||
View::assign('aliurl', '');
|
||||
View::assign('order_sn', $this->order_sn);
|
||||
View::assign('total_fee', number_format((int) $order['total_price'] / 100, 2));
|
||||
return View::fetch($route . '/pcpay');
|
||||
} catch (\RuntimeException | \InvalidArgumentException $e) {
|
||||
return $this->error($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,17 +13,14 @@
|
||||
<div class="company-section">
|
||||
<h2>公司简介</h2>
|
||||
<div class="company-intro">
|
||||
<p>济南经纬九州出入境服务有限公司,于2014年4月4日经山东省工商局批准成立。2016年5月,我公司职员受邀参加山东省外事机关组织的“EVUS”登记说明会,由当时的现任美国签证官亲自解说指导,我司员工是唯一的非政府机构参会人员。自该业务开展以来,我司的EVUS登记业务,所有的有效签证已全部登记成功;有一部分客户因签证本身无效无法登记成功,我司职员凭借专业的经验引导这部分客户重新获取签证,并登记成功。</p>
|
||||
<p>多年来,经纬九州出入境始终追求“专业化,规范化”的经营理念,践行“一带一路”伟大倡议,为我国公民提供因私出入境服务,经纬九州员工锐意进取,不断开拓精品项目。独立开发的eVUS大数据模型系统,能够快速的协助客户完成美签电子更新。</p>
|
||||
<p>历经市场考验,经纬九州人坚守“不忘初心,不辱使命”之愿景,立志成为业务门类齐全、有相当社会知名度的中介服务机构。evus.cn网热忱欢迎中外企业和各类优秀人才加盟合作,共创未来。</p>
|
||||
{foreach $company_paragraphs as $paragraph}<p>{$paragraph|htmlspecialchars|raw}</p>{/foreach}
|
||||
{if empty($company_paragraphs)}<p>公司简介正在更新中,欢迎通过网站客服了解更多信息。</p>{/if}
|
||||
</div>
|
||||
|
||||
<div class="company-meta">
|
||||
<p><strong>公司:</strong>济南经纬九州出入境服务有限公司</p>
|
||||
<p><strong>地址:</strong>山东省 济南市 历下区</p>
|
||||
<p><strong>邮编:</strong>250013</p>
|
||||
<p><strong>手机:</strong>4000-878-958</p>
|
||||
<p><strong>网站:</strong>www.evus.cn</p>
|
||||
{if !empty($company_name)}<p><strong>公司:</strong>{$company_name|htmlspecialchars|raw}</p>{/if}
|
||||
{if !empty($company_phone)}<p><strong>电话:</strong>{$company_phone|htmlspecialchars|raw}</p>{/if}
|
||||
{if !empty($company_email)}<p><strong>邮箱:</strong>{$company_email|htmlspecialchars|raw}</p>{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{include file="public/head" /}
|
||||
<link rel="stylesheet" href="/static/home/css/payment-choice.css?v=1">
|
||||
<link rel="stylesheet" href="/static/visa/nvisa.css?v=1">
|
||||
<link rel="stylesheet" href="/static/home/css/home-menu.css?v=4">
|
||||
<link rel="stylesheet" href="/static/home/css/detail.css?v=5">
|
||||
@@ -1677,6 +1678,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{include file="public/payment_methods" /}
|
||||
<div class="layui-row text-center">
|
||||
<div class="layui-col-xs12">
|
||||
<div class="layui-form-item">
|
||||
@@ -1773,7 +1775,8 @@
|
||||
{include file="public/footer" /}
|
||||
</body>
|
||||
<!--<script src="/static/js/signature_pad.min.js"></script>-->
|
||||
<script src="/static/visa/nvisa.js?v=8"></script>
|
||||
<script src="/static/home/js/payment-choice.js?v=1"></script>
|
||||
<script src="/static/visa/nvisa.js?v=payment-1"></script>
|
||||
<script src="/static/visa/visa-ocr-passport-sync.js?v=1"></script>
|
||||
<script>
|
||||
var area = window.getAgreementLayerArea();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{include file="public/head" /}
|
||||
<link rel="stylesheet" href="/static/home/css/payment-choice.css?v=1">
|
||||
<link rel="stylesheet" href="/static/home/css/home-menu.css?v=4">
|
||||
<link rel="stylesheet" href="/static/visa/nvisa.css">
|
||||
<link rel="stylesheet" href="/static/visa/calendar/calendar.min.css?v=3"/>
|
||||
@@ -1414,6 +1415,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{include file="public/payment_methods" /}
|
||||
<div class="layui-row text-center">
|
||||
<div class="layui-col-xs12">
|
||||
<div class="layui-form-item">
|
||||
@@ -1433,7 +1435,8 @@
|
||||
</div>
|
||||
</body>
|
||||
{include file="public/footer" /}
|
||||
<script src="/static/visa/esta.js"></script>
|
||||
<script src="/static/home/js/payment-choice.js?v=1"></script>
|
||||
<script src="/static/visa/esta.js?v=payment-1"></script>
|
||||
<script>
|
||||
var passportOcrFile = null;
|
||||
var ocrConfigRaw = '{$ocr_config|default = ''}'.replace(/"/g, '"');
|
||||
|
||||
@@ -120,12 +120,12 @@
|
||||
.login-row .login-get{ width: 35%;}
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="/static/home/css/login.css?v=2">
|
||||
<link rel="stylesheet" href="/static/home/css/login.css?v=3">
|
||||
<body class="login-bg home-layout-page login-page">
|
||||
<div class="content login-shell">
|
||||
{include file="public/home_menu" /}
|
||||
<div class="login-box">
|
||||
<div class="login-logo">www.evus.cn</div>
|
||||
<a class="login-logo" href="{:url('home/index/index')}" aria-label="EVUS 首页"><img src="{$logo|default='/static/home/images/logo_113.png'}" alt="EVUS 中文登记服务"></a>
|
||||
<div class="login-con">
|
||||
<div class="login-row">
|
||||
<input class="login-text" type="tel" name="mobile" id="mobile" placeholder="手机号"/>
|
||||
|
||||
16
app/home/view/public/payment_methods.html
Normal file
16
app/home/view/public/payment_methods.html
Normal file
@@ -0,0 +1,16 @@
|
||||
{if condition="!empty($payment_methods_configured)"}
|
||||
<fieldset class="payment-choice" data-mobile="{$ismobile}" data-english="{$payment_english ? '1' : '0'}">
|
||||
<legend>{$payment_english ? 'Payment method' : '选择支付方式'}</legend>
|
||||
<div class="payment-choice-options">
|
||||
{volist name="payment_methods" id="method"}
|
||||
<label class="payment-choice-option">
|
||||
<input type="radio" name="payment_method" value="{$method}" lay-ignore {eq name="i" value="1"}checked{/eq}>
|
||||
<span class="payment-choice-icon payment-choice-icon--{$method}" aria-hidden="true">{$method == 'alipay' ? '支' : '微'}</span>
|
||||
<span>{if condition="$method == 'alipay'"}{$payment_english ? 'Alipay' : '支付宝'}{else /}{$payment_english ? 'WeChat Pay' : '微信支付'}{/if}</span>
|
||||
</label>
|
||||
{/volist}
|
||||
</div>
|
||||
{empty name="payment_methods"}<p role="alert">{$payment_english ? 'No payment method is available. Please use another browser or contact support.' : '当前浏览器没有可用支付方式,请更换浏览器或联系客服。'}</p>{/empty}
|
||||
<div class="payment-choice-status" role="status" aria-live="polite"></div>
|
||||
</fieldset>
|
||||
{/if}
|
||||
60
app/service/PaymentSelectionService.php
Normal file
60
app/service/PaymentSelectionService.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace app\service;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use RuntimeException;
|
||||
|
||||
final class PaymentSelectionService
|
||||
{
|
||||
public function __construct(private array $configured) {}
|
||||
|
||||
public function hasEnabledMethods(): bool
|
||||
{
|
||||
// The legacy fallback depends on configuration, not the visitor's browser.
|
||||
return $this->methods('') !== [];
|
||||
}
|
||||
|
||||
public function methods(string $userAgent): array
|
||||
{
|
||||
$enabled = [];
|
||||
foreach ($this->configured as $row) {
|
||||
if (is_array($row) && in_array($row['code'] ?? '', ['alipay', 'wechat'], true)
|
||||
&& filter_var($row['enabled'] ?? false, FILTER_VALIDATE_BOOLEAN)) $enabled[$row['code']] = true;
|
||||
}
|
||||
$allowed = stripos($userAgent, 'MicroMessenger') !== false ? ['wechat'] : ['alipay', 'wechat'];
|
||||
return array_values(array_filter($allowed, static fn($code) => isset($enabled[$code])));
|
||||
}
|
||||
|
||||
public function select($method, string $userAgent): string
|
||||
{
|
||||
$methods = $this->methods($userAgent);
|
||||
if (!is_string($method)) throw new InvalidArgumentException('支付方式无效');
|
||||
if (!$methods) throw new InvalidArgumentException('当前浏览器没有可用支付方式,请更换浏览器或联系客服');
|
||||
if ($method === '') return $methods[0];
|
||||
if (!in_array($method, $methods, true)) throw new InvalidArgumentException('支付方式已停用或当前浏览器不支持,请重新选择');
|
||||
return $method;
|
||||
}
|
||||
|
||||
public function action(string $method, bool $mobile, string $userAgent): string
|
||||
{
|
||||
$this->select($method, $userAgent);
|
||||
if (!$mobile) return $method === 'alipay' ? 'alipay' : 'pcpay';
|
||||
return $method === 'wechat' && stripos($userAgent, 'MicroMessenger') !== false ? 'wxpay' : 'h5pay';
|
||||
}
|
||||
|
||||
public function gatewayUrl(array $response, bool $requireCode): string
|
||||
{
|
||||
$body = json_decode((string) ($response[0] ?? ''), true);
|
||||
$status = (int) ($response[2]['http_code'] ?? 0);
|
||||
$url = is_string($body['url'] ?? null) ? trim($body['url']) : '';
|
||||
if (!empty($response[3]) || $status < 200 || $status >= 300
|
||||
|| ($requireCode && (int) ($body['code'] ?? 0) !== 1)
|
||||
|| (isset($body['code']) && (int) $body['code'] !== 1)
|
||||
|| !filter_var($url, FILTER_VALIDATE_URL) || strtolower((string) parse_url($url, PHP_URL_SCHEME)) !== 'https'
|
||||
|| parse_url($url, PHP_URL_USER) !== null || parse_url($url, PHP_URL_PASS) !== null || preg_match('/[\r\n]/', $url)) {
|
||||
throw new RuntimeException('支付接口未返回有效地址,请稍后重试');
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,9 @@
|
||||
margin-top: -30px;
|
||||
margin-left: -90px;
|
||||
display: block;
|
||||
background: url("../images/loginbg3.png") no-repeat center top;
|
||||
background: #fff;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.08);
|
||||
background-size: 180px 60px;
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
@@ -52,6 +54,14 @@
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.login-page .login-logo img {
|
||||
width: 156px;
|
||||
height: 50px;
|
||||
margin: 10px 12px;
|
||||
object-fit: contain;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.login-page .login-con {
|
||||
padding: 10px 20px 0 !important;
|
||||
overflow: hidden;
|
||||
|
||||
2
public/static/home/css/payment-choice.css
Normal file
2
public/static/home/css/payment-choice.css
Normal file
@@ -0,0 +1,2 @@
|
||||
.payment-choice{margin:24px 0;padding:20px;border:1px solid #dbe3ee;border-radius:12px;background:#f8fafc}.payment-choice legend{padding:0 8px;font-size:16px;font-weight:600;color:#142b4a}.payment-choice-options{display:flex;gap:14px;flex-wrap:wrap}.payment-choice-option{display:flex;align-items:center;gap:10px;min-width:150px;padding:14px 18px;border:1px solid #cbd5e1;border-radius:8px;background:#fff;cursor:pointer}.payment-choice-option:has(input:checked){border-color:#1677ff;box-shadow:0 0 0 1px #1677ff}.payment-choice-option input{display:inline-block!important;appearance:auto;width:18px;height:18px;accent-color:#1677ff}.payment-choice-option:focus-within{outline:2px solid #1677ff;outline-offset:3px}.payment-choice-option>span:last-child{white-space:nowrap}.payment-choice-icon{flex-shrink:0;display:grid;place-items:center;width:30px;height:30px;color:#fff;border-radius:7px;font-weight:bold}.payment-choice-icon--alipay{background:#1677ff}.payment-choice-icon--wechat{background:#07a951}.payment-choice-status{margin-top:12px;line-height:1.6}.payment-choice-status a{color:#1265c8;text-decoration:underline}@media(max-width:480px){.payment-choice-options{gap:10px}.payment-choice-option{min-width:0;flex:1;padding:12px 6px;gap:6px;font-size:14px}}
|
||||
@media(max-width:350px){.payment-choice-option{flex-basis:100%}}
|
||||
68
public/static/home/js/payment-choice.js
Normal file
68
public/static/home/js/payment-choice.js
Normal file
@@ -0,0 +1,68 @@
|
||||
(function (global) {
|
||||
'use strict';
|
||||
var busy = false, completed = false;
|
||||
var fieldset = document.querySelector('.payment-choice');
|
||||
if (!fieldset) return;
|
||||
var english = fieldset.dataset.english === '1';
|
||||
var text = function (zh, en) { return english ? en : zh; };
|
||||
var button = document.getElementById('submit');
|
||||
if (!fieldset.querySelector('input[name="payment_method"]')) button.disabled = true;
|
||||
global.PaymentChoice = {
|
||||
submit: function (url, payload) {
|
||||
if (busy || completed) return;
|
||||
var selected = fieldset.querySelector('input[name="payment_method"]:checked');
|
||||
if (!selected) { layer.msg(text('请选择支付方式', 'Please select a payment method')); return; }
|
||||
payload.payment_method = selected.value;
|
||||
busy = true;
|
||||
button.disabled = true;
|
||||
layer.closeAll('page');
|
||||
var status = fieldset.querySelector('.payment-choice-status');
|
||||
status.textContent = text('正在提交,请勿重复操作…', 'Submitting, please wait…');
|
||||
// Reserve the new tab during the click, before the asynchronous order request.
|
||||
var tab = fieldset.dataset.mobile === '0' && selected.value === 'alipay' ? global.open('about:blank', '_blank') : null;
|
||||
if (tab) tab.opener = null;
|
||||
var loading = layer.load(2, {shade: 0.3});
|
||||
$.ajax({url: url, type: 'POST', data: payload, dataType: 'json'})
|
||||
.done(function (result) {
|
||||
if (result.code !== 1) {
|
||||
if (tab) tab.close();
|
||||
status.textContent = result.msg || text('提交失败,请稍后重试', 'Submission failed. Please retry.');
|
||||
return;
|
||||
}
|
||||
// Never create a second order when the customer returns from checkout.
|
||||
completed = true;
|
||||
var destination = new URL(result.url, global.location.href);
|
||||
if (destination.origin !== global.location.origin || !['http:', 'https:'].includes(destination.protocol)) {
|
||||
if (tab) tab.close();
|
||||
status.textContent = text('订单已提交,请到我的订单继续支付', 'Order submitted. Continue payment from My orders.');
|
||||
return;
|
||||
}
|
||||
if (result.data && result.data.open_new_tab) {
|
||||
if (tab && !tab.closed) tab.location.replace(destination.href);
|
||||
status.textContent = text('订单已提交,请在支付页面完成付款。', 'Order submitted. Complete payment on the checkout page.');
|
||||
var link = document.createElement('a');
|
||||
link.href = destination.href;
|
||||
link.target = '_blank';
|
||||
link.rel = 'noopener noreferrer';
|
||||
link.textContent = text('打开/重新打开支付页面', 'Open / reopen checkout');
|
||||
status.appendChild(document.createElement('br'));
|
||||
status.appendChild(link);
|
||||
} else {
|
||||
if (tab) tab.close();
|
||||
global.location.href = destination.href;
|
||||
}
|
||||
})
|
||||
.fail(function () {
|
||||
if (tab) tab.close();
|
||||
// The server may have created the order even if the response was lost.
|
||||
completed = true;
|
||||
status.textContent = text('提交结果暂未确认,请先到“我的订单”核实,避免重复下单。', 'Submission is unconfirmed. Check My orders before submitting again.');
|
||||
})
|
||||
.always(function () {
|
||||
layer.close(loading);
|
||||
busy = false;
|
||||
button.disabled = completed;
|
||||
});
|
||||
}
|
||||
};
|
||||
})(window);
|
||||
@@ -93,6 +93,10 @@ form.on('submit(formSubmit)', function (data) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (window.PaymentChoice) {
|
||||
window.PaymentChoice.submit(window.estaOrderApplyUrl || '/home/esta/do_apply', submitVal);
|
||||
return false;
|
||||
}
|
||||
var load = layer.load(2, {shade: 0.3})
|
||||
console.log(submitVal)
|
||||
$.ajax({
|
||||
|
||||
@@ -154,6 +154,10 @@ form.on('submit(formSubmit)', function (data) {
|
||||
anim: -1,
|
||||
isOutAnim: false,
|
||||
yes: function () {
|
||||
if (window.PaymentChoice) {
|
||||
window.PaymentChoice.submit(window.nvisaSubmitUrl || '/home/detail/do_apply', submitVal);
|
||||
return;
|
||||
}
|
||||
var load = layer.load(2, {shade: 0.3})
|
||||
$.ajax({
|
||||
url: window.nvisaSubmitUrl || "/home/detail/do_apply", type: "POST", data: submitVal, success: function (data) {
|
||||
|
||||
Reference in New Issue
Block a user